From 8790bef310a3fc6b9972142bce79c7da14d158c0 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 16:32:17 +0200 Subject: [PATCH 001/107] Fix unsafe bool handling at Solidity/Yul assembly boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Solidity `bool` may be any nonzero value for truthy when it enters an assembly block. This commit normalizes bool values at every site where they are used in arithmetic, bitwise operations, ABI encoding for external calls, or (transient) storage writes. Utility libraries (highest leverage — inlined throughout codebase): - Ternary: use iszero-inversion trick (single iszero, 3 gas) for ternary/maybeSwap; lt(0x00, c) for orZero - FastLogic.and: rewrite via De Morgan (was wrong: and(2,1)=0) - FastLogic.andNot: rewrite via gt(iszero(b), iszero(a)) - FastLogic.toUint, Math.toInt: normalize with lt(0x00, b) - UnsafeMath.unsafeInc/Dec(bool), Math.inc/dec: normalize with lt(0x00, b) External call encoding (mstore/mstore8/shl of bool): - EkuboV2, EkuboV3, MaverickV2, PancakeInfinity, UniswapV3Fork, FlashAccountingCommon, SafePermit, Hanji: wrap bool in lt(0x00, x) Transient storage: - CurveTricrypto: clean on write and read External callback data validation: - EkuboV2: revert with empty reason if bool > 1 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/core/CurveTricrypto.sol | 4 ++-- src/core/EkuboV2.sol | 8 ++++--- src/core/EkuboV3.sol | 6 +++-- src/core/FlashAccountingCommon.sol | 6 ++--- src/core/Hanji.sol | 4 ++++ src/core/MaverickV2.sol | 2 +- src/core/PancakeInfinity.sol | 4 ++-- src/core/UniswapV3Fork.sol | 4 ++-- src/utils/FastLogic.sol | 11 ++++++--- src/utils/SafePermit.sol | 4 ++-- src/utils/Ternary.sol | 38 +++++++++++++++++------------- src/utils/UnsafeMath.sol | 10 ++++---- 12 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/core/CurveTricrypto.sol b/src/core/CurveTricrypto.sol index 54bb632dc..4a3ba9e8b 100644 --- a/src/core/CurveTricrypto.sol +++ b/src/core/CurveTricrypto.sol @@ -101,7 +101,7 @@ abstract contract CurveTricrypto is SettlerSwapAbstract { */ bool isForwarded = _isForwarded(); assembly ("memory-safe") { - tstore(0x00, isForwarded) + tstore(0x00, lt(0x00, isForwarded)) tstore(0x01, mload(add(0x20, mload(permit)))) // amount tstore(0x02, mload(add(0x20, permit))) // nonce tstore(0x03, mload(add(0x40, permit))) // deadline @@ -152,7 +152,7 @@ abstract contract CurveTricrypto is SettlerSwapAbstract { uint256 deadline; bytes memory sig; assembly ("memory-safe") { - isForwarded := tload(0x00) + isForwarded := lt(0x00, tload(0x00)) tstore(0x00, 0x00) permittedAmount := tload(0x01) tstore(0x01, 0x00) diff --git a/src/core/EkuboV2.sol b/src/core/EkuboV2.sol index 395809156..3e36ed05f 100644 --- a/src/core/EkuboV2.sol +++ b/src/core/EkuboV2.sol @@ -79,7 +79,7 @@ library UnsafeEkuboCore { mcopy(poolKeyPtr, poolKey, 0x60) // ABI decoding in Ekubo will check if amount fits in int128 mstore(add(0x80, ptr), amount) - mstore(add(0xa0, ptr), isToken1) + mstore(add(0xa0, ptr), lt(0x00, isToken1)) mstore(add(0xc0, ptr), and(0xffffffffffffffffffffffff, sqrtRatioLimit)) mstore(add(0xe0, ptr), 0x00) @@ -110,7 +110,7 @@ library UnsafeEkuboCore { let poolKeyPtr := add(0x34, ptr) mcopy(poolKeyPtr, poolKey, 0x60) mstore(add(0x94, ptr), amount) - mstore(add(0xb4, ptr), isToken1) + mstore(add(0xb4, ptr), lt(0x00, isToken1)) mstore(add(0xd4, ptr), and(0xffffffffffffffffffffffff, sqrtRatioLimit)) mstore(add(0xf4, ptr), 0x00) @@ -284,7 +284,7 @@ abstract contract EkuboV2 is SettlerSwapAbstract { if iszero(eq(payer, address())) { // let's skip token and sell amount and reuse the values already in data calldatacopy(add(0x64, data), add(0x40, permit), 0x40) - mstore(add(0xa4, data), isForwarded) + mstore(add(0xa4, data), lt(0x00, isForwarded)) mstore(add(0xc4, data), sig.length) calldatacopy(add(0xe4, data), sig.offset, sig.length) size := add(size, add(0x80, sig.length)) @@ -529,6 +529,8 @@ abstract contract EkuboV2 is SettlerSwapAbstract { // starts at the beginning of sellToken permit := add(0x20, data.offset) isForwarded := calldataload(add(0xa0, data.offset)) + // Validate bool from external callback data; revert if dirty + if shr(0x01, isForwarded) { revert(0x00, 0x00) } sig.offset := add(0xc0, data.offset) sig.length := calldataload(sig.offset) diff --git a/src/core/EkuboV3.sol b/src/core/EkuboV3.sol index 63dd6fe65..147b3c584 100644 --- a/src/core/EkuboV3.sol +++ b/src/core/EkuboV3.sol @@ -66,7 +66,8 @@ library UnsafeEkuboCore { // Compact params (uint96 sqrtRatioLimit, int128 amount, bool isToken1, uint32 skipAhead) // skipAhead is encoded as 31 bits // mstore(add(0x80, ptr), 0x00) // skipAhead harcoded to zero - mstore(add(0x80, ptr), shl(0x1f, isToken1)) // sets skipAhead to zero + // Solidity `bool` may be any nonzero value; normalize for bit-packed encoding + mstore(add(0x80, ptr), shl(0x1f, lt(0x00, isToken1))) // sets skipAhead to zero mstore(add(0x7c, ptr), amount) mstore(add(0x6c, ptr), sqrtRatioLimit) mcopy(add(0x20, ptr), poolKey, 0x60) @@ -102,7 +103,8 @@ library UnsafeEkuboCore { /// Compact params (uint96 sqrtRatioLimit, int128 amount, bool isToken1, uint32 skipAhead) // skipAhead is encoded as 31 bits // mstore(add(0x94, ptr), 0x00) // skipAhead harcoded to zero - mstore(add(0x94, ptr), shl(0x1f, isToken1)) // sets skipAhead to zero + // Solidity `bool` may be any nonzero value; normalize for bit-packed encoding + mstore(add(0x94, ptr), shl(0x1f, lt(0x00, isToken1))) // sets skipAhead to zero mstore(add(0x90, ptr), amount) mstore(add(0x80, ptr), sqrtRatioLimit) mcopy(add(0x34, ptr), poolKey, 0x60) diff --git a/src/core/FlashAccountingCommon.sol b/src/core/FlashAccountingCommon.sol index 3c3afd7e5..c32236d21 100644 --- a/src/core/FlashAccountingCommon.sol +++ b/src/core/FlashAccountingCommon.sol @@ -409,7 +409,7 @@ library Encoder { mstore(add(0x24, data), 0x20) mstore(add(0x04, data), unlockSelector) mstore(data, add(0xb3, pathLen)) - mstore8(add(0xa8, data), feeOnTransfer) + mstore8(add(0xa8, data), lt(0x00, feeOnTransfer)) mstore(0x40, add(data, add(0xd3, pathLen))) } @@ -455,7 +455,7 @@ library Encoder { mstore(0x40, add(0x03, ptr)) } - mstore8(add(0x131, data), isForwarded) + mstore8(add(0x131, data), lt(0x00, isForwarded)) mcopy(add(0xf1, data), add(0x20, permit), 0x40) mcopy(add(0xb1, data), mload(permit), 0x40) // aliases `payer` on purpose mstore(add(0x9d, data), 0x00) // payer @@ -470,7 +470,7 @@ library Encoder { mstore(add(0x04, data), unlockSelector) mstore(data, add(0x115, add(pathLen, sigLen))) - mstore8(add(0xa8, data), feeOnTransfer) + mstore8(add(0xa8, data), lt(0x00, feeOnTransfer)) } } } diff --git a/src/core/Hanji.sol b/src/core/Hanji.sol index 119d9a000..2c846ecfe 100644 --- a/src/core/Hanji.sol +++ b/src/core/Hanji.sol @@ -64,6 +64,8 @@ library FastHanjiPool { ) internal returns (uint256 executed) { assembly ("memory-safe") { let ptr := mload(0x40) + // Solidity `bool` may be any nonzero value; normalize once for arithmetic use below + isAsk := lt(0x00, isAsk) mstore(ptr, xor(0xad73d32e, mul(0x58603c62, isAsk))) // selector mstore(add(0x20, ptr), isAsk) mstore(add(0x40, ptr), and(0xffffffffffffffffffffffffffffffff, quantity)) @@ -90,6 +92,8 @@ library FastHanjiPool { function getToken(IHanjiPool pool, bool tokenY) internal view returns (IERC20 result) { assembly ("memory-safe") { let ptr := mload(0x40) + // Solidity `bool` may be any nonzero value; normalize for use as shift operand + tokenY := lt(0x00, tokenY) mstore(0x00, 0xc3f909d4) // IHanjiPool.getConfig.selector if iszero(staticcall(gas(), pool, 0x1c, 0x04, 0x00, 0x80)) { diff --git a/src/core/MaverickV2.sol b/src/core/MaverickV2.sol index f26646e0a..767e3cc51 100644 --- a/src/core/MaverickV2.sol +++ b/src/core/MaverickV2.sol @@ -150,7 +150,7 @@ library FastMaverickV2Pool { mstore(add(0xc4, data), 0xc0) mstore(add(0xa4, data), signextend(0x03, tickLimit)) mstore(add(0x84, data), 0x00) // exactOutput is false - mstore(add(0x64, data), tokenAIn) + mstore(add(0x64, data), lt(0x00, tokenAIn)) mstore(add(0x44, data), amount) mstore(add(0x24, data), recipient) mstore(add(0x10, data), 0x3eece7db000000000000000000000000) // selector for `swap(address,(uint256,bool,bool,int32),bytes)` with `recipient`'s padding diff --git a/src/core/PancakeInfinity.sol b/src/core/PancakeInfinity.sol index d211b00cf..2b310be18 100644 --- a/src/core/PancakeInfinity.sol +++ b/src/core/PancakeInfinity.sol @@ -149,7 +149,7 @@ library UnsafePancakeInfinityPoolManager { let ptr := mload(0x40) mstore(ptr, 0xcd0cc1ce) // selector for `swap((address,address,address,address,uint24,bytes32),(bool,int256,uint160),bytes)` mcopy(add(0x20, ptr), key, 0xc0) - mstore(add(0xe0, ptr), zeroForOne) + mstore(add(0xe0, ptr), lt(0x00, zeroForOne)) mstore(add(0x100, ptr), amountSpecified) mstore(add(0x120, ptr), sqrtPriceLimitX96) mstore(add(0x140, ptr), 0x140) @@ -178,7 +178,7 @@ library UnsafePancakeInfinityBinPoolManager { let ptr := mload(0x40) mstore(ptr, 0x911a63b7) // selector for `swap((address,address,address,address,uint24,bytes32),bool,int128,bytes)` mcopy(add(0x20, ptr), key, 0xc0) - mstore(add(0xe0, ptr), swapForY) + mstore(add(0xe0, ptr), lt(0x00, swapForY)) mstore(add(0x100, ptr), signextend(0x0f, amountSpecified)) mstore(add(0x120, ptr), 0x120) mstore(add(0x140, ptr), hookData.length) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index b95deff3e..a3359dec7 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -158,7 +158,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { mstore(add(0xa4, data), 0xa0) mstore(add(0x84, data), and(0xffffffffffffffffffffffffffffffffffffffff, sqrtPriceLimitX96)) mstore(add(0x64, data), sellAmount) - mstore(add(0x44, data), zeroForOne) + mstore(add(0x44, data), lt(0x00, zeroForOne)) mstore(add(0x24, data), to) mstore(add(0x10, data), 0x128acb08000000000000000000000000) // selector for `swap(address,bool,int256,uint160,bytes)` with `to`'s padding @@ -248,7 +248,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { assembly ("memory-safe") { mstore(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, swapCallbackData), mload(add(0x20, mload(permit)))) mcopy(add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, 0x20), swapCallbackData), add(0x20, permit), 0x40) - mstore8(add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), swapCallbackData), isForwarded) + mstore8(add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), swapCallbackData), lt(0x00, isForwarded)) mcopy( add( add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), ISFORWARDED_DATA_SIZE), diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index bec56ad78..dad97bcf4 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; +// Solidity `bool` may be any nonzero value for truthy. Bitwise `or` preserves truthiness so +// `or(a, b)` is safe. `and`/`andNot` are rewritten using `iszero` (always 0/1) to implement +// correct logical semantics. `toUint` normalizes with `lt(0x00, b)` (PUSH0 + LT = 5 gas). library FastLogic { function or(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { @@ -9,20 +12,22 @@ library FastLogic { } function and(bool a, bool b) internal pure returns (bool r) { + // De Morgan: a ∧ b ≡ ¬(¬a ∨ ¬b) assembly ("memory-safe") { - r := and(a, b) + r := iszero(or(iszero(a), iszero(b))) } } function andNot(bool a, bool b) internal pure returns (bool r) { + // a ∧ ¬b: normalize via iszero then compare assembly ("memory-safe") { - r := gt(a, b) + r := gt(iszero(b), iszero(a)) } } function toUint(bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := b + r := lt(0x00, b) } } } diff --git a/src/utils/SafePermit.sol b/src/utils/SafePermit.sol index 6a836ae79..359af53dd 100644 --- a/src/utils/SafePermit.sol +++ b/src/utils/SafePermit.sol @@ -48,7 +48,7 @@ library FastPermit { mstore(add(0xf4, ptr), and(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, vs)) // `s`. mstore(add(0xd4, ptr), r) // `r`. mstore(add(0xb4, ptr), add(0x1b, shr(0xff, vs))) // `v`. - mstore(add(0x94, ptr), allowed) + mstore(add(0x94, ptr), lt(0x00, allowed)) mstore(add(0x74, ptr), expiry) mstore(add(0x54, ptr), nonce) mstore(add(0x34, ptr), spender) @@ -272,7 +272,7 @@ library SafePermit { mstore(add(0x80, ptr), spender) mstore(add(0xa0, ptr), nonce) mstore(add(0xc0, ptr), deadline) - mstore(add(0xe0, ptr), allowed) + mstore(add(0xe0, ptr), lt(0x00, allowed)) mstore(add(0x40, ptr), keccak256(add(0x40, ptr), 0xc0)) signingHash := keccak256(add(0x1e, ptr), 0x42) } diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index 629ca728c..901f136ed 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -8,65 +8,69 @@ library Ternary { //// it doesn't need to do a ton of masking when types are cast to each other without //// modification. + // Solidity `bool` may be any nonzero value for truthy. `iszero(c)` produces clean 0/1 and we + // restructure each formula around the negated condition so a single `iszero` suffices. + // `orZero` has no negation-based reformulation, so it uses `lt(0x00, c)` to normalize. + function ternary(bool c, uint256 x, uint256 y) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function ternary(bool c, int256 x, int256 y) internal pure returns (int256 r) { assembly ("memory-safe") { - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function ternary(bool c, bytes4 x, bytes4 y) internal pure returns (bytes4 r) { assembly ("memory-safe") { - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function ternary(bool c, address x, address y) internal pure returns (address r) { assembly ("memory-safe") { - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function orZero(bool c, uint256 x) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := mul(x, c) + r := mul(x, lt(0x00, c)) } } function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } } diff --git a/src/utils/UnsafeMath.sol b/src/utils/UnsafeMath.sol index b4573059b..e0341c9f4 100644 --- a/src/utils/UnsafeMath.sol +++ b/src/utils/UnsafeMath.sol @@ -12,7 +12,7 @@ library UnsafeMath { function unsafeInc(uint256 x, bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := add(x, b) + r := add(x, lt(0x00, b)) } } @@ -30,7 +30,7 @@ library UnsafeMath { function unsafeDec(uint256 x, bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := sub(x, b) + r := sub(x, lt(0x00, b)) } } @@ -113,7 +113,7 @@ library UnsafeMath { library Math { function inc(uint256 x, bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := add(x, c) + r := add(x, lt(0x00, c)) } if (r < x) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); @@ -122,7 +122,7 @@ library Math { function dec(uint256 x, bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := sub(x, c) + r := sub(x, lt(0x00, c)) } if (r > x) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); @@ -131,7 +131,7 @@ library Math { function toInt(bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := c + r := lt(0x00, c) } } From edb5e6bd14f3421988781faa515a2099a829cb92 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 16:35:24 +0200 Subject: [PATCH 002/107] Fix bool cleanliness at Yul boundaries --- src/CrossChainReceiverFactory.sol | 2 +- src/SettlerIntent.sol | 1 + src/core/EkuboV2.sol | 10 +- src/core/EkuboV3.sol | 4 +- src/core/EulerSwap.sol | 6 +- src/core/FlashAccountingCommon.sol | 10 +- src/core/Hanji.sol | 3 +- src/core/MaverickV2.sol | 2 +- src/core/PancakeInfinity.sol | 4 +- src/core/UniswapV2.sol | 4 +- src/core/UniswapV3Fork.sol | 11 +- src/utils/FastLogic.sol | 8 +- src/utils/SafePermit.sol | 4 +- src/utils/Ternary.sol | 9 + src/utils/UnsafeMath.sol | 10 +- test/0.8.25/BoolBoundary.t.sol | 503 +++++++++++++++++++++++++ test/unit/core/UniswapV3UnitTest.t.sol | 40 ++ 17 files changed, 598 insertions(+), 33 deletions(-) create mode 100644 test/0.8.25/BoolBoundary.t.sol diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index 1142d9e38..4b38cf532 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -960,7 +960,7 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte revert(codesize(), callvalue()) } - wrappedBalance := mul(hasWnative, mload(callvalue())) + wrappedBalance := mul(iszero(iszero(hasWnative)), mload(callvalue())) } uint256 toUnwrap = (address(this).balance + wrappedBalance < value) diff --git a/src/SettlerIntent.sol b/src/SettlerIntent.sol index 3ae6dafae..64f4e7a79 100644 --- a/src/SettlerIntent.sol +++ b/src/SettlerIntent.sol @@ -138,6 +138,7 @@ abstract contract SettlerIntent is MultiCallContext, Permit2PaymentIntent, Settl // Clean dirty bits. prev := shr(0x60, shl(0x60, prev)) solver := shr(0x60, shl(0x60, solver)) + addNotRemove := iszero(iszero(addNotRemove)) // A solver of zero is special-cased. It is forbidden to set it because that would // corrupt the list. diff --git a/src/core/EkuboV2.sol b/src/core/EkuboV2.sol index 395809156..478a4f947 100644 --- a/src/core/EkuboV2.sol +++ b/src/core/EkuboV2.sol @@ -79,7 +79,7 @@ library UnsafeEkuboCore { mcopy(poolKeyPtr, poolKey, 0x60) // ABI decoding in Ekubo will check if amount fits in int128 mstore(add(0x80, ptr), amount) - mstore(add(0xa0, ptr), isToken1) + mstore(add(0xa0, ptr), iszero(iszero(isToken1))) mstore(add(0xc0, ptr), and(0xffffffffffffffffffffffff, sqrtRatioLimit)) mstore(add(0xe0, ptr), 0x00) @@ -110,7 +110,7 @@ library UnsafeEkuboCore { let poolKeyPtr := add(0x34, ptr) mcopy(poolKeyPtr, poolKey, 0x60) mstore(add(0x94, ptr), amount) - mstore(add(0xb4, ptr), isToken1) + mstore(add(0xb4, ptr), iszero(iszero(isToken1))) mstore(add(0xd4, ptr), and(0xffffffffffffffffffffffff, sqrtRatioLimit)) mstore(add(0xf4, ptr), 0x00) @@ -284,7 +284,7 @@ abstract contract EkuboV2 is SettlerSwapAbstract { if iszero(eq(payer, address())) { // let's skip token and sell amount and reuse the values already in data calldatacopy(add(0x64, data), add(0x40, permit), 0x40) - mstore(add(0xa4, data), isForwarded) + mstore(add(0xa4, data), iszero(iszero(isForwarded))) mstore(add(0xc4, data), sig.length) calldatacopy(add(0xe4, data), sig.offset, sig.length) size := add(size, add(0x80, sig.length)) @@ -528,7 +528,9 @@ abstract contract EkuboV2 is SettlerSwapAbstract { assembly ("memory-safe") { // starts at the beginning of sellToken permit := add(0x20, data.offset) - isForwarded := calldataload(add(0xa0, data.offset)) + let isForwarded_ := calldataload(add(0xa0, data.offset)) + if shr(0x01, isForwarded_) { revert(0x00, 0x00) } + isForwarded := isForwarded_ sig.offset := add(0xc0, data.offset) sig.length := calldataload(sig.offset) diff --git a/src/core/EkuboV3.sol b/src/core/EkuboV3.sol index 63dd6fe65..08c687122 100644 --- a/src/core/EkuboV3.sol +++ b/src/core/EkuboV3.sol @@ -66,7 +66,7 @@ library UnsafeEkuboCore { // Compact params (uint96 sqrtRatioLimit, int128 amount, bool isToken1, uint32 skipAhead) // skipAhead is encoded as 31 bits // mstore(add(0x80, ptr), 0x00) // skipAhead harcoded to zero - mstore(add(0x80, ptr), shl(0x1f, isToken1)) // sets skipAhead to zero + mstore(add(0x80, ptr), shl(0x1f, iszero(iszero(isToken1)))) // sets skipAhead to zero mstore(add(0x7c, ptr), amount) mstore(add(0x6c, ptr), sqrtRatioLimit) mcopy(add(0x20, ptr), poolKey, 0x60) @@ -102,7 +102,7 @@ library UnsafeEkuboCore { /// Compact params (uint96 sqrtRatioLimit, int128 amount, bool isToken1, uint32 skipAhead) // skipAhead is encoded as 31 bits // mstore(add(0x94, ptr), 0x00) // skipAhead harcoded to zero - mstore(add(0x94, ptr), shl(0x1f, isToken1)) // sets skipAhead to zero + mstore(add(0x94, ptr), shl(0x1f, iszero(iszero(isToken1)))) // sets skipAhead to zero mstore(add(0x90, ptr), amount) mstore(add(0x80, ptr), sqrtRatioLimit) mcopy(add(0x34, ptr), poolKey, 0x60) diff --git a/src/core/EulerSwap.sol b/src/core/EulerSwap.sol index 83a363fd1..7ff0c29e9 100644 --- a/src/core/EulerSwap.sol +++ b/src/core/EulerSwap.sol @@ -55,7 +55,9 @@ library FastEvc { returndatacopy(ptr_, 0x00, returndatasize()) revert(ptr_, returndatasize()) } - authorized := mload(0x00) + let authorized_ := mload(0x00) + if or(lt(returndatasize(), 0x20), shr(0x01, authorized_)) { revert(0x00, 0x00) } + authorized := authorized_ mstore(0x40, ptr) } } @@ -384,7 +386,7 @@ library FastEulerSwap { let ptr := mload(0x40) mstore(ptr, 0x022c0d9f) // selector for `swap(uint256,uint256,address,bytes)` { - zeroForOne := shl(0x05, zeroForOne) + zeroForOne := shl(0x05, iszero(iszero(zeroForOne))) let amountsStart := add(0x20, ptr) let amountWord := add(amountsStart, zeroForOne) let zeroWord := add(xor(0x20, zeroForOne), amountsStart) diff --git a/src/core/FlashAccountingCommon.sol b/src/core/FlashAccountingCommon.sol index 3c3afd7e5..614944508 100644 --- a/src/core/FlashAccountingCommon.sol +++ b/src/core/FlashAccountingCommon.sol @@ -409,7 +409,7 @@ library Encoder { mstore(add(0x24, data), 0x20) mstore(add(0x04, data), unlockSelector) mstore(data, add(0xb3, pathLen)) - mstore8(add(0xa8, data), feeOnTransfer) + mstore8(add(0xa8, data), iszero(iszero(feeOnTransfer))) mstore(0x40, add(data, add(0xd3, pathLen))) } @@ -455,7 +455,7 @@ library Encoder { mstore(0x40, add(0x03, ptr)) } - mstore8(add(0x131, data), isForwarded) + mstore8(add(0x131, data), iszero(iszero(isForwarded))) mcopy(add(0xf1, data), add(0x20, permit), 0x40) mcopy(add(0xb1, data), mload(permit), 0x40) // aliases `payer` on purpose mstore(add(0x9d, data), 0x00) // payer @@ -470,7 +470,7 @@ library Encoder { mstore(add(0x04, data), unlockSelector) mstore(data, add(0x115, add(pathLen, sigLen))) - mstore8(add(0xa8, data), feeOnTransfer) + mstore8(add(0xa8, data), iszero(iszero(feeOnTransfer))) } } } @@ -694,7 +694,9 @@ library Decoder { // the middle of `payer`, because `payer` is all zeroes, it's treated as padding // for the first word of `permit`, which is the sell token permit := sub(data.offset, 0x0c) - isForwarded := and(0x01, calldataload(add(0x55, data.offset))) + let isForwarded_ := and(0xff, calldataload(add(0x55, data.offset))) + if shr(0x01, isForwarded_) { revert(0x00, 0x00) } + isForwarded := isForwarded_ // `sig` is packed at the end of `data`, in "reverse ABI-ish encoded" fashion sig.offset := sub(add(data.offset, data.length), 0x03) diff --git a/src/core/Hanji.sol b/src/core/Hanji.sol index 119d9a000..8116bd675 100644 --- a/src/core/Hanji.sol +++ b/src/core/Hanji.sol @@ -64,6 +64,7 @@ library FastHanjiPool { ) internal returns (uint256 executed) { assembly ("memory-safe") { let ptr := mload(0x40) + isAsk := iszero(iszero(isAsk)) mstore(ptr, xor(0xad73d32e, mul(0x58603c62, isAsk))) // selector mstore(add(0x20, ptr), isAsk) mstore(add(0x40, ptr), and(0xffffffffffffffffffffffffffffffff, quantity)) @@ -97,7 +98,7 @@ library FastHanjiPool { revert(ptr, returndatasize()) } - result := mload(add(0x40, shl(0x05, tokenY))) + result := mload(add(0x40, shl(0x05, iszero(iszero(tokenY))))) mstore(0x40, ptr) mstore(0x60, 0x00) diff --git a/src/core/MaverickV2.sol b/src/core/MaverickV2.sol index f26646e0a..4c02a943b 100644 --- a/src/core/MaverickV2.sol +++ b/src/core/MaverickV2.sol @@ -150,7 +150,7 @@ library FastMaverickV2Pool { mstore(add(0xc4, data), 0xc0) mstore(add(0xa4, data), signextend(0x03, tickLimit)) mstore(add(0x84, data), 0x00) // exactOutput is false - mstore(add(0x64, data), tokenAIn) + mstore(add(0x64, data), iszero(iszero(tokenAIn))) mstore(add(0x44, data), amount) mstore(add(0x24, data), recipient) mstore(add(0x10, data), 0x3eece7db000000000000000000000000) // selector for `swap(address,(uint256,bool,bool,int32),bytes)` with `recipient`'s padding diff --git a/src/core/PancakeInfinity.sol b/src/core/PancakeInfinity.sol index d211b00cf..f35a6b1d6 100644 --- a/src/core/PancakeInfinity.sol +++ b/src/core/PancakeInfinity.sol @@ -149,7 +149,7 @@ library UnsafePancakeInfinityPoolManager { let ptr := mload(0x40) mstore(ptr, 0xcd0cc1ce) // selector for `swap((address,address,address,address,uint24,bytes32),(bool,int256,uint160),bytes)` mcopy(add(0x20, ptr), key, 0xc0) - mstore(add(0xe0, ptr), zeroForOne) + mstore(add(0xe0, ptr), iszero(iszero(zeroForOne))) mstore(add(0x100, ptr), amountSpecified) mstore(add(0x120, ptr), sqrtPriceLimitX96) mstore(add(0x140, ptr), 0x140) @@ -178,7 +178,7 @@ library UnsafePancakeInfinityBinPoolManager { let ptr := mload(0x40) mstore(ptr, 0x911a63b7) // selector for `swap((address,address,address,address,uint24,bytes32),bool,int128,bytes)` mcopy(add(0x20, ptr), key, 0xc0) - mstore(add(0xe0, ptr), swapForY) + mstore(add(0xe0, ptr), iszero(iszero(swapForY))) mstore(add(0x100, ptr), signextend(0x0f, amountSpecified)) mstore(add(0x120, ptr), 0x120) mstore(add(0x140, ptr), hookData.length) diff --git a/src/core/UniswapV2.sol b/src/core/UniswapV2.sol index 48c6c001e..cb8e5cf6d 100644 --- a/src/core/UniswapV2.sol +++ b/src/core/UniswapV2.sol @@ -34,7 +34,7 @@ library fastUniswapV2Pool { revert(ptr, returndatasize()) } if lt(returndatasize(), 0x40) { revert(0x00, 0x00) } - let r := shl(0x05, zeroForOne) + let r := shl(0x05, iszero(iszero(zeroForOne))) buyReserve := mload(r) sellReserve := mload(xor(0x20, r)) } @@ -63,7 +63,7 @@ library fastUniswapV2Pool { // set amount0Out and amount1Out let buyAmountBaseOffset := add(0x20, ptr) // If `zeroForOne`, buyAmount offset is 0x40, else 0x20 - let directionOffset := shl(0x05, zeroForOne) + let directionOffset := shl(0x05, iszero(iszero(zeroForOne))) mstore(add(buyAmountBaseOffset, directionOffset), buyAmount) mstore(add(buyAmountBaseOffset, xor(0x20, directionOffset)), 0x00) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index b95deff3e..6c784b6b2 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -158,7 +158,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { mstore(add(0xa4, data), 0xa0) mstore(add(0x84, data), and(0xffffffffffffffffffffffffffffffffffffffff, sqrtPriceLimitX96)) mstore(add(0x64, data), sellAmount) - mstore(add(0x44, data), zeroForOne) + mstore(add(0x44, data), iszero(iszero(zeroForOne))) mstore(add(0x24, data), to) mstore(add(0x10, data), 0x128acb08000000000000000000000000) // selector for `swap(address,bool,int256,uint160,bytes)` with `to`'s padding @@ -248,7 +248,10 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { assembly ("memory-safe") { mstore(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, swapCallbackData), mload(add(0x20, mload(permit)))) mcopy(add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, 0x20), swapCallbackData), add(0x20, permit), 0x40) - mstore8(add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), swapCallbackData), isForwarded) + mstore8( + add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), swapCallbackData), + iszero(iszero(isForwarded)) + ) mcopy( add( add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), ISFORWARDED_DATA_SIZE), @@ -362,7 +365,9 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // middle of `payer`, because `payer` is all zeroes, it's treated as padding for the // first word of `permit`, which is the sell token permit := sub(permit2Data.offset, 0x0c) - isForwarded := and(0x01, calldataload(add(0x55, permit2Data.offset))) + let isForwarded_ := and(0xff, calldataload(add(0x55, permit2Data.offset))) + if shr(0x01, isForwarded_) { revert(0x00, 0x00) } + isForwarded := isForwarded_ sig.offset := add(0x75, permit2Data.offset) sig.length := sub(permit2Data.length, 0x75) } diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index bec56ad78..34c98ae05 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -4,25 +4,25 @@ pragma solidity ^0.8.25; library FastLogic { function or(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { - r := or(a, b) + r := iszero(iszero(or(a, b))) } } function and(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { - r := and(a, b) + r := iszero(or(iszero(a), iszero(b))) } } function andNot(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { - r := gt(a, b) + r := iszero(or(iszero(a), b)) } } function toUint(bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := b + r := iszero(iszero(b)) } } } diff --git a/src/utils/SafePermit.sol b/src/utils/SafePermit.sol index 6a836ae79..d6a2738c4 100644 --- a/src/utils/SafePermit.sol +++ b/src/utils/SafePermit.sol @@ -48,7 +48,7 @@ library FastPermit { mstore(add(0xf4, ptr), and(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, vs)) // `s`. mstore(add(0xd4, ptr), r) // `r`. mstore(add(0xb4, ptr), add(0x1b, shr(0xff, vs))) // `v`. - mstore(add(0x94, ptr), allowed) + mstore(add(0x94, ptr), iszero(iszero(allowed))) mstore(add(0x74, ptr), expiry) mstore(add(0x54, ptr), nonce) mstore(add(0x34, ptr), spender) @@ -272,7 +272,7 @@ library SafePermit { mstore(add(0x80, ptr), spender) mstore(add(0xa0, ptr), nonce) mstore(add(0xc0, ptr), deadline) - mstore(add(0xe0, ptr), allowed) + mstore(add(0xe0, ptr), iszero(iszero(allowed))) mstore(add(0x40, ptr), keccak256(add(0x40, ptr), 0xc0)) signingHash := keccak256(add(0x1e, ptr), 0x42) } diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index 629ca728c..f150f03b7 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -10,36 +10,42 @@ library Ternary { function ternary(bool c, uint256 x, uint256 y) internal pure returns (uint256 r) { assembly ("memory-safe") { + c := iszero(iszero(c)) r := xor(y, mul(xor(x, y), c)) } } function ternary(bool c, int256 x, int256 y) internal pure returns (int256 r) { assembly ("memory-safe") { + c := iszero(iszero(c)) r := xor(y, mul(xor(x, y), c)) } } function ternary(bool c, bytes4 x, bytes4 y) internal pure returns (bytes4 r) { assembly ("memory-safe") { + c := iszero(iszero(c)) r := xor(y, mul(xor(x, y), c)) } } function ternary(bool c, address x, address y) internal pure returns (address r) { assembly ("memory-safe") { + c := iszero(iszero(c)) r := xor(y, mul(xor(x, y), c)) } } function orZero(bool c, uint256 x) internal pure returns (uint256 r) { assembly ("memory-safe") { + c := iszero(iszero(c)) r := mul(x, c) } } function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { + c := iszero(iszero(c)) let t := mul(xor(x, y), c) a := xor(x, t) b := xor(y, t) @@ -48,6 +54,7 @@ library Ternary { function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { + c := iszero(iszero(c)) let t := mul(xor(x, y), c) a := xor(x, t) b := xor(y, t) @@ -56,6 +63,7 @@ library Ternary { function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { + c := iszero(iszero(c)) let t := mul(xor(x, y), c) a := xor(x, t) b := xor(y, t) @@ -64,6 +72,7 @@ library Ternary { function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { + c := iszero(iszero(c)) let t := mul(xor(x, y), c) a := xor(x, t) b := xor(y, t) diff --git a/src/utils/UnsafeMath.sol b/src/utils/UnsafeMath.sol index b4573059b..0ed3f4ad3 100644 --- a/src/utils/UnsafeMath.sol +++ b/src/utils/UnsafeMath.sol @@ -12,7 +12,7 @@ library UnsafeMath { function unsafeInc(uint256 x, bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := add(x, b) + r := add(x, iszero(iszero(b))) } } @@ -30,7 +30,7 @@ library UnsafeMath { function unsafeDec(uint256 x, bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := sub(x, b) + r := sub(x, iszero(iszero(b))) } } @@ -113,7 +113,7 @@ library UnsafeMath { library Math { function inc(uint256 x, bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := add(x, c) + r := add(x, iszero(iszero(c))) } if (r < x) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); @@ -122,7 +122,7 @@ library Math { function dec(uint256 x, bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := sub(x, c) + r := sub(x, iszero(iszero(c))) } if (r > x) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); @@ -131,7 +131,7 @@ library Math { function toInt(bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := c + r := iszero(iszero(c)) } } diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol new file mode 100644 index 000000000..fcbc96b3a --- /dev/null +++ b/test/0.8.25/BoolBoundary.t.sol @@ -0,0 +1,503 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; + +import {FastLogic} from "src/utils/FastLogic.sol"; +import {Ternary} from "src/utils/Ternary.sol"; +import {UnsafeMath, Math} from "src/utils/UnsafeMath.sol"; +import {FastPermit} from "src/utils/SafePermit.sol"; +import {IDAIStylePermit} from "src/interfaces/IERC2612.sol"; + +import {IEVC, FastEvc, IEulerSwap, FastEulerSwap} from "src/core/EulerSwap.sol"; +import {IUniV2Pair, fastUniswapV2Pool} from "src/core/UniswapV2.sol"; +import {IHanjiPool, FastHanjiPool} from "src/core/Hanji.sol"; +import {IMaverickV2Pool, FastMaverickV2Pool} from "src/core/MaverickV2.sol"; +import {IEkuboCore, PoolKey as EkuboPoolKey, Config, SqrtRatio, UnsafeEkuboCore} from "src/core/EkuboV2.sol"; +import { + IPancakeInfinityCLPoolManager, + IPancakeInfinityBinPoolManager, + PoolKey as PancakePoolKey, + IHooks, + UnsafePancakeInfinityPoolManager, + UnsafePancakeInfinityBinPoolManager +} from "src/core/PancakeInfinity.sol"; +import {Encoder} from "src/core/FlashAccountingCommon.sol"; +import {BalanceDelta} from "src/core/UniswapV4Types.sol"; + +contract MockDaiPermitToken { + bool public lastAllowed; + + function permit(address, address, uint256, uint256, bool allowed, uint8, bytes32, bytes32) external returns (bool) { + lastAllowed = allowed; + return true; + } +} + +contract MockEvcBool { + bytes internal response; + + function setResponse(bytes memory newResponse) external { + response = newResponse; + } + + fallback(bytes calldata) external returns (bytes memory) { + return response; + } +} + +contract MockUniswapV2Pair is IUniV2Pair { + uint112 internal reserve0; + uint112 internal reserve1; + + uint256 public amount0Out; + uint256 public amount1Out; + address public recipient; + bytes public swapData; + + function setReserves(uint112 reserve0_, uint112 reserve1_) external { + reserve0 = reserve0_; + reserve1 = reserve1_; + } + + function token0() external pure returns (address) { + return address(0); + } + + function token1() external pure returns (address) { + return address(0); + } + + function getReserves() external view returns (uint112, uint112, uint32) { + return (reserve0, reserve1, 0); + } + + function swap(uint256 amount0Out_, uint256 amount1Out_, address recipient_, bytes calldata data_) external { + amount0Out = amount0Out_; + amount1Out = amount1Out_; + recipient = recipient_; + swapData = data_; + } +} + +contract MockEulerSwap { + uint256 public amount0Out; + uint256 public amount1Out; + address public recipient; + + function swap(uint256 amount0Out_, uint256 amount1Out_, address to, bytes calldata) external { + amount0Out = amount0Out_; + amount1Out = amount1Out_; + recipient = to; + } +} + +contract MockHanjiPool is IHanjiPool { + bool public lastIsAsk; + bytes4 public lastSelector; + + address internal tokenX; + address internal tokenY; + + constructor(address tokenX_, address tokenY_) { + tokenX = tokenX_; + tokenY = tokenY_; + } + + function placeOrder(bool isAsk, uint128, uint72, uint128, bool, bool, bool, uint256) + external + payable + returns (uint64, uint128, uint128, uint128) + { + lastSelector = msg.sig; + lastIsAsk = isAsk; + return (0, 0, 0, 0); + } + + function placeMarketOrderWithTargetValue(bool isAsk, uint128, uint72, uint128, bool, uint256) + external + payable + returns (uint128, uint128, uint128) + { + lastSelector = msg.sig; + lastIsAsk = isAsk; + return (0, 0, 0); + } + + function getConfig() + external + view + returns (uint256, uint256, address, address, bool, bool, address, address, uint64, uint64, uint64, uint64, bool) + { + return (0, 0, tokenX, tokenY, false, false, address(0), address(0), 0, 0, 0, 0, false); + } +} + +contract MockMaverickPool { + address public lastRecipient; + uint256 public lastAmount; + bool public lastTokenAIn; + bool public lastExactOutput; + int32 public lastTickLimit; + bytes public lastData; + + function swap(address recipient, IMaverickV2Pool.SwapParams calldata params, bytes calldata data) + external + returns (uint256 amountIn, uint256 amountOut) + { + lastRecipient = recipient; + lastAmount = params.amount; + lastTokenAIn = params.tokenAIn; + lastExactOutput = params.exactOutput; + lastTickLimit = params.tickLimit; + lastData = data; + return (0, 0); + } +} + +contract MockEkuboCore is IEkuboCore { + bool public lastIsToken1; + + function lock() external {} + + function swap_611415377(EkuboPoolKey memory, int128, bool isToken1, SqrtRatio, uint256) + external + payable + returns (int128 delta0, int128 delta1) + { + lastIsToken1 = isToken1; + return (0, 0); + } + + function forward(address) external {} + + function pay(address) external pure returns (uint128 payment) { + return 0; + } + + function withdraw(address, address, uint128) external {} +} + +contract MockPancakeClManager { + bool public lastZeroForOne; + bytes public lastHookData; + + function swap( + PancakePoolKey memory, + IPancakeInfinityCLPoolManager.SwapParams calldata params, + bytes calldata hookData + ) external returns (BalanceDelta delta) { + lastZeroForOne = params.zeroForOne; + lastHookData = hookData; + return BalanceDelta.wrap(0); + } +} + +contract MockPancakeBinManager { + bool public lastSwapForY; + bytes public lastHookData; + + function swap(PancakePoolKey memory, bool swapForY, int128, bytes calldata hookData) + external + returns (BalanceDelta delta) + { + lastSwapForY = swapForY; + lastHookData = hookData; + return BalanceDelta.wrap(0); + } +} + +contract BoolBoundaryHarness { + function fastIsAuthorized(IEVC evc) external view returns (bool) { + return FastEvc.fastIsAccountOperatorAuthorized(evc, address(0x11), address(0x22)); + } + + function fastDaiPermit(IDAIStylePermit token) external returns (bool success) { + bool allowed; + assembly ("memory-safe") { + allowed := 0x02 + } + return + FastPermit.fastDAIPermit(token, address(0x11), address(0x22), 0x33, 0x44, allowed, bytes32(0), bytes32(0)); + } + + function fastUniswapV2GetReserves(address pool) external view returns (uint256 sellReserve, uint256 buyReserve) { + bool zeroForOne; + assembly ("memory-safe") { + zeroForOne := 0x02 + } + return fastUniswapV2Pool.fastGetReserves(pool, zeroForOne); + } + + function fastUniswapV2Swap(address pool, uint256 buyAmount, address recipient) external { + bool zeroForOne; + assembly ("memory-safe") { + zeroForOne := 0x02 + } + fastUniswapV2Pool.fastSwap(pool, zeroForOne, buyAmount, recipient); + } + + function fastEulerSwap(IEulerSwap pool, uint256 amountOut, address recipient) external { + bool zeroForOne; + assembly ("memory-safe") { + zeroForOne := 0x02 + } + FastEulerSwap.fastSwap(pool, zeroForOne, amountOut, recipient); + } + + function hanjiPlaceMarketOrder(IHanjiPool pool) external returns (uint256 executed) { + bool isAsk; + assembly ("memory-safe") { + isAsk := 0x02 + } + return FastHanjiPool.placeMarketOrder(pool, 0, isAsk, 7, 11); + } + + function hanjiGetToken(IHanjiPool pool) external view returns (IERC20 token) { + bool tokenY; + assembly ("memory-safe") { + tokenY := 0x02 + } + return FastHanjiPool.getToken(pool, tokenY); + } + + function maverickEncode(address recipient, uint256 amount, int256 tickLimit, bytes memory swapCallbackData) + external + pure + returns (bytes memory data) + { + bool tokenAIn; + assembly ("memory-safe") { + tokenAIn := 0x02 + } + return FastMaverickV2Pool.fastEncodeSwap( + IMaverickV2Pool(address(0)), recipient, amount, tokenAIn, tickLimit, swapCallbackData + ); + } + + function ekuboV2Swap(IEkuboCore core, EkuboPoolKey memory poolKey, int256 amount, SqrtRatio sqrtRatioLimit) + external + returns (int256 delta0, int256 delta1) + { + bool isToken1; + assembly ("memory-safe") { + isToken1 := 0x02 + } + return UnsafeEkuboCore.unsafeSwap(core, poolKey, amount, isToken1, sqrtRatioLimit); + } + + function pancakeClSwap( + IPancakeInfinityCLPoolManager poolManager, + PancakePoolKey memory key, + int256 amountSpecified, + uint256 sqrtPriceLimitX96, + bytes calldata hookData + ) external returns (BalanceDelta delta) { + bool zeroForOne; + assembly ("memory-safe") { + zeroForOne := 0x02 + } + return UnsafePancakeInfinityPoolManager.unsafeSwap( + poolManager, key, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData + ); + } + + function pancakeBinSwap( + IPancakeInfinityBinPoolManager poolManager, + PancakePoolKey memory key, + int128 amountSpecified, + bytes calldata hookData + ) external returns (BalanceDelta delta) { + bool swapForY; + assembly ("memory-safe") { + swapForY := 0x02 + } + return UnsafePancakeInfinityBinPoolManager.unsafeSwap(poolManager, key, swapForY, amountSpecified, hookData); + } + + function flashEncode(bytes memory fills) external view returns (bytes memory data) { + bool feeOnTransfer; + assembly ("memory-safe") { + feeOnTransfer := 0x02 + } + return Encoder.encode(0x12345678, address(0x11), IERC20(address(0x22)), 1, feeOnTransfer, 1, 2, fills, 3); + } + + function flashEncodeVip(bytes memory fills, bytes memory sig) external pure returns (bytes memory data) { + bool feeOnTransfer; + bool isForwarded; + assembly ("memory-safe") { + feeOnTransfer := 0x02 + isForwarded := 0x03 + } + ISignatureTransfer.PermitTransferFrom memory permit = ISignatureTransfer.PermitTransferFrom({ + permitted: ISignatureTransfer.TokenPermissions({token: address(0x33), amount: 4}), nonce: 5, deadline: 6 + }); + return Encoder.encodeVIP(0x12345678, address(0x11), feeOnTransfer, 1, 2, fills, permit, sig, isForwarded, 3); + } +} + +contract BoolBoundaryTest is Test { + using FastLogic for bool; + using Ternary for bool; + using UnsafeMath for uint256; + using Math for uint256; + + BoolBoundaryHarness internal harness; + + function setUp() public { + harness = new BoolBoundaryHarness(); + } + + function testHelpersAcceptDirtyBools() public { + bool dirtyTrue; + assembly ("memory-safe") { + dirtyTrue := 0x02 + } + + assertTrue(dirtyTrue.or(false)); + assertTrue(dirtyTrue.and(true)); + assertTrue(dirtyTrue.andNot(false)); + assertEq(dirtyTrue.toUint(), 1); + + assertEq(dirtyTrue.ternary(uint256(7), uint256(9)), 7); + assertEq(dirtyTrue.ternary(int256(7), int256(9)), 7); + assertEq(dirtyTrue.ternary(bytes4(0x01020304), bytes4(0x05060708)), bytes4(0x01020304)); + assertEq(dirtyTrue.ternary(address(0x11), address(0x22)), address(0x11)); + assertEq(dirtyTrue.orZero(13), 13); + + (uint256 a, uint256 b) = dirtyTrue.maybeSwap(uint256(1), uint256(2)); + assertEq(a, 2); + assertEq(b, 1); + + (int256 x, int256 y) = dirtyTrue.maybeSwap(int256(3), int256(4)); + assertEq(x, 4); + assertEq(y, 3); + + assertEq(uint256(5).unsafeInc(dirtyTrue), 6); + assertEq(uint256(5).unsafeDec(dirtyTrue), 4); + assertEq(uint256(5).inc(dirtyTrue), 6); + assertEq(uint256(5).dec(dirtyTrue), 4); + assertEq(Math.toInt(dirtyTrue), 1); + } + + function testFastDaiPermitCanonicalizesDirtyBool() public { + MockDaiPermitToken token = new MockDaiPermitToken(); + + assertTrue(harness.fastDaiPermit(IDAIStylePermit(address(token)))); + assertTrue(token.lastAllowed()); + } + + function testFastEvcAcceptsCanonicalBool() public { + MockEvcBool evc = new MockEvcBool(); + + evc.setResponse(abi.encode(true)); + assertTrue(harness.fastIsAuthorized(IEVC(address(evc)))); + + evc.setResponse(abi.encode(false)); + assertFalse(harness.fastIsAuthorized(IEVC(address(evc)))); + } + + function testFastEvcRejectsShortOrDirtyBool() public { + MockEvcBool evc = new MockEvcBool(); + + evc.setResponse(new bytes(31)); + vm.expectRevert(bytes("")); + harness.fastIsAuthorized(IEVC(address(evc))); + + evc.setResponse(abi.encode(uint256(2))); + vm.expectRevert(bytes("")); + harness.fastIsAuthorized(IEVC(address(evc))); + } + + function testUniswapV2BoundaryUsesCanonicalBit() public { + MockUniswapV2Pair pool = new MockUniswapV2Pair(); + pool.setReserves(11, 22); + + (uint256 sellReserve, uint256 buyReserve) = harness.fastUniswapV2GetReserves(address(pool)); + assertEq(sellReserve, 11); + assertEq(buyReserve, 22); + + harness.fastUniswapV2Swap(address(pool), 7, address(0x44)); + assertEq(pool.amount0Out(), 0); + assertEq(pool.amount1Out(), 7); + assertEq(pool.recipient(), address(0x44)); + assertEq(pool.swapData().length, 0); + } + + function testEulerSwapBoundaryUsesCanonicalBit() public { + MockEulerSwap pool = new MockEulerSwap(); + + harness.fastEulerSwap(IEulerSwap(address(pool)), 9, address(0x55)); + assertEq(pool.amount0Out(), 0); + assertEq(pool.amount1Out(), 9); + assertEq(pool.recipient(), address(0x55)); + } + + function testHanjiBoundaryCanonicalizesDirtyBool() public { + MockHanjiPool pool = new MockHanjiPool(address(0x11), address(0x22)); + + harness.hanjiPlaceMarketOrder(IHanjiPool(address(pool))); + assertTrue(pool.lastIsAsk()); + assertTrue( + pool.lastSelector() == IHanjiPool.placeOrder.selector + || pool.lastSelector() == IHanjiPool.placeMarketOrderWithTargetValue.selector + ); + + assertEq(address(harness.hanjiGetToken(IHanjiPool(address(pool)))), address(0x22)); + } + + function testMaverickEncodeCanonicalizesDirtyBool() public { + MockMaverickPool pool = new MockMaverickPool(); + bytes memory data = harness.maverickEncode(address(0x66), 7, 9, hex"abcd"); + + (bool success,) = address(pool).call(data); + assertTrue(success); + assertEq(pool.lastRecipient(), address(0x66)); + assertEq(pool.lastAmount(), 7); + assertTrue(pool.lastTokenAIn()); + assertFalse(pool.lastExactOutput()); + assertEq(pool.lastTickLimit(), 9); + assertEq(pool.lastData(), hex"abcd"); + } + + function testEkuboV2SwapCanonicalizesDirtyBool() public { + MockEkuboCore core = new MockEkuboCore(); + EkuboPoolKey memory key = EkuboPoolKey({token0: address(0x11), token1: address(0x22), config: Config.wrap(0)}); + + harness.ekuboV2Swap(IEkuboCore(address(core)), key, 7, SqrtRatio.wrap(9)); + assertTrue(core.lastIsToken1()); + } + + function testPancakeInfinityCanonicalizesDirtyBool() public { + MockPancakeClManager cl = new MockPancakeClManager(); + MockPancakeBinManager bin = new MockPancakeBinManager(); + PancakePoolKey memory key = PancakePoolKey({ + currency0: IERC20(address(0x11)), + currency1: IERC20(address(0x22)), + hooks: IHooks.wrap(address(0x33)), + poolManager: IPancakeInfinityCLPoolManager(address(cl)), + fee: 500, + parameters: bytes32(uint256(7)) + }); + + harness.pancakeClSwap(IPancakeInfinityCLPoolManager(address(cl)), key, 1, 2, hex"ab"); + assertTrue(cl.lastZeroForOne()); + assertEq(cl.lastHookData(), hex"ab"); + + harness.pancakeBinSwap(IPancakeInfinityBinPoolManager(address(bin)), key, 3, hex"cd"); + assertTrue(bin.lastSwapForY()); + assertEq(bin.lastHookData(), hex"cd"); + } + + function testFlashEncoderCanonicalizesDirtyBoolBytes() public { + bytes memory data = harness.flashEncode(hex"010203"); + assertEq(uint8(data[0x88]), 1); + + bytes memory vipData = harness.flashEncodeVip(hex"040506", hex"deadbeef"); + assertEq(uint8(vipData[0x88]), 1); + assertEq(uint8(vipData[0x111]), 1); + } +} diff --git a/test/unit/core/UniswapV3UnitTest.t.sol b/test/unit/core/UniswapV3UnitTest.t.sol index 37f740b54..e2d4b0477 100644 --- a/test/unit/core/UniswapV3UnitTest.t.sol +++ b/test/unit/core/UniswapV3UnitTest.t.sol @@ -101,6 +101,28 @@ contract UniswapV3PoolDummy { } } +contract UniswapV3PoolDirtyForwardedBoolDummy { + bytes public RETURN_DATA; + + constructor(bytes memory returnData) { + RETURN_DATA = returnData; + } + + fallback(bytes calldata) external payable returns (bytes memory) { + (,,,, bytes memory data) = abi.decode(msg.data[4:], (address, bool, int256, uint160, bytes)); + data[0x88] = bytes1(uint8(2)); + + (bool success, bytes memory returndata) = + msg.sender.call(abi.encodeWithSignature("uniswapV3SwapCallback(int256,int256,bytes)", int256(1), int256(1), data)); + if (!success) { + assembly ("memory-safe") { + revert(add(0x20, returndata), mload(returndata)) + } + } + return RETURN_DATA; + } +} + contract UniswapV3UnitTest is Utils, Test { UniswapV3Dummy uni; address UNI_FACTORY = _createNamedRejectionDummy("UNI_FACTORY"); @@ -277,4 +299,22 @@ contract UniswapV3UnitTest is Utils, Test { ); // uni.sell(RECIPIENT, encodedPath, minBuyAmount, permitTransfer, hex""); } + + function testUniswapV3SellPermit2RejectsDirtyForwardedBool() public { + uint256 amount = 99999; + + deployCodeTo( + "UniswapV3UnitTest.t.sol:UniswapV3PoolDirtyForwardedBoolDummy", + abi.encode(abi.encodePacked(-int256(amount), -int256(amount))), + POOL + ); + + ISignatureTransfer.TokenPermissions memory permitted = + ISignatureTransfer.TokenPermissions({token: TOKEN0, amount: amount}); + ISignatureTransfer.PermitTransferFrom memory permitTransfer = + ISignatureTransfer.PermitTransferFrom({permitted: permitted, nonce: 0, deadline: 0}); + + vm.expectRevert(bytes("")); + uni.sell(RECIPIENT, encodedPath, permitTransfer, hex"deadbeef", amount); + } } From 6ae07862600a482a705a9e159222c31a023da759 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 18:55:33 +0200 Subject: [PATCH 003/107] Optimize bool truthiness at Yul boundaries --- src/CrossChainReceiverFactory.sol | 4 ++- src/SettlerIntent.sol | 2 +- src/core/CurveTricrypto.sol | 2 +- src/core/EkuboV2.sol | 6 ++--- src/core/EkuboV3.sol | 4 +-- src/core/EulerSwap.sol | 2 +- src/core/FlashAccountingCommon.sol | 6 ++--- src/core/Hanji.sol | 5 ++-- src/core/MaverickV2.sol | 2 +- src/core/PancakeInfinity.sol | 4 +-- src/core/UniswapV2.sol | 4 +-- src/core/UniswapV3Fork.sol | 4 +-- src/utils/FastLogic.sol | 8 +++--- src/utils/SafePermit.sol | 4 +-- src/utils/Ternary.sol | 43 ++++++++++++------------------ src/utils/UnsafeMath.sol | 10 +++---- 16 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index 4b38cf532..c7fb7fe3f 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -407,6 +407,8 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte bytes32 proxyInitCode0 = _proxyInitCode0; bytes32 proxyInitCode1 = _proxyInitCode1; assembly ("memory-safe") { + setOwnerNotCleanup := lt(0x00, setOwnerNotCleanup) + // derive the deployment salt from the owner mstore(0x14, initialOwner) mstore(callvalue(), root) @@ -960,7 +962,7 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte revert(codesize(), callvalue()) } - wrappedBalance := mul(iszero(iszero(hasWnative)), mload(callvalue())) + wrappedBalance := mul(lt(0x00, hasWnative), mload(callvalue())) } uint256 toUnwrap = (address(this).balance + wrappedBalance < value) diff --git a/src/SettlerIntent.sol b/src/SettlerIntent.sol index 64f4e7a79..bbb5f1e4e 100644 --- a/src/SettlerIntent.sol +++ b/src/SettlerIntent.sol @@ -138,7 +138,7 @@ abstract contract SettlerIntent is MultiCallContext, Permit2PaymentIntent, Settl // Clean dirty bits. prev := shr(0x60, shl(0x60, prev)) solver := shr(0x60, shl(0x60, solver)) - addNotRemove := iszero(iszero(addNotRemove)) + addNotRemove := lt(0x00, addNotRemove) // A solver of zero is special-cased. It is forbidden to set it because that would // corrupt the list. diff --git a/src/core/CurveTricrypto.sol b/src/core/CurveTricrypto.sol index 54bb632dc..879fec24a 100644 --- a/src/core/CurveTricrypto.sol +++ b/src/core/CurveTricrypto.sol @@ -101,7 +101,7 @@ abstract contract CurveTricrypto is SettlerSwapAbstract { */ bool isForwarded = _isForwarded(); assembly ("memory-safe") { - tstore(0x00, isForwarded) + tstore(0x00, lt(0x00, isForwarded)) tstore(0x01, mload(add(0x20, mload(permit)))) // amount tstore(0x02, mload(add(0x20, permit))) // nonce tstore(0x03, mload(add(0x40, permit))) // deadline diff --git a/src/core/EkuboV2.sol b/src/core/EkuboV2.sol index 478a4f947..512b4e209 100644 --- a/src/core/EkuboV2.sol +++ b/src/core/EkuboV2.sol @@ -79,7 +79,7 @@ library UnsafeEkuboCore { mcopy(poolKeyPtr, poolKey, 0x60) // ABI decoding in Ekubo will check if amount fits in int128 mstore(add(0x80, ptr), amount) - mstore(add(0xa0, ptr), iszero(iszero(isToken1))) + mstore(add(0xa0, ptr), lt(0x00, isToken1)) mstore(add(0xc0, ptr), and(0xffffffffffffffffffffffff, sqrtRatioLimit)) mstore(add(0xe0, ptr), 0x00) @@ -110,7 +110,7 @@ library UnsafeEkuboCore { let poolKeyPtr := add(0x34, ptr) mcopy(poolKeyPtr, poolKey, 0x60) mstore(add(0x94, ptr), amount) - mstore(add(0xb4, ptr), iszero(iszero(isToken1))) + mstore(add(0xb4, ptr), lt(0x00, isToken1)) mstore(add(0xd4, ptr), and(0xffffffffffffffffffffffff, sqrtRatioLimit)) mstore(add(0xf4, ptr), 0x00) @@ -284,7 +284,7 @@ abstract contract EkuboV2 is SettlerSwapAbstract { if iszero(eq(payer, address())) { // let's skip token and sell amount and reuse the values already in data calldatacopy(add(0x64, data), add(0x40, permit), 0x40) - mstore(add(0xa4, data), iszero(iszero(isForwarded))) + mstore(add(0xa4, data), lt(0x00, isForwarded)) mstore(add(0xc4, data), sig.length) calldatacopy(add(0xe4, data), sig.offset, sig.length) size := add(size, add(0x80, sig.length)) diff --git a/src/core/EkuboV3.sol b/src/core/EkuboV3.sol index 08c687122..bdc29ffc6 100644 --- a/src/core/EkuboV3.sol +++ b/src/core/EkuboV3.sol @@ -66,7 +66,7 @@ library UnsafeEkuboCore { // Compact params (uint96 sqrtRatioLimit, int128 amount, bool isToken1, uint32 skipAhead) // skipAhead is encoded as 31 bits // mstore(add(0x80, ptr), 0x00) // skipAhead harcoded to zero - mstore(add(0x80, ptr), shl(0x1f, iszero(iszero(isToken1)))) // sets skipAhead to zero + mstore(add(0x80, ptr), shl(0x1f, lt(0x00, isToken1))) // sets skipAhead to zero mstore(add(0x7c, ptr), amount) mstore(add(0x6c, ptr), sqrtRatioLimit) mcopy(add(0x20, ptr), poolKey, 0x60) @@ -102,7 +102,7 @@ library UnsafeEkuboCore { /// Compact params (uint96 sqrtRatioLimit, int128 amount, bool isToken1, uint32 skipAhead) // skipAhead is encoded as 31 bits // mstore(add(0x94, ptr), 0x00) // skipAhead harcoded to zero - mstore(add(0x94, ptr), shl(0x1f, iszero(iszero(isToken1)))) // sets skipAhead to zero + mstore(add(0x94, ptr), shl(0x1f, lt(0x00, isToken1))) // sets skipAhead to zero mstore(add(0x90, ptr), amount) mstore(add(0x80, ptr), sqrtRatioLimit) mcopy(add(0x34, ptr), poolKey, 0x60) diff --git a/src/core/EulerSwap.sol b/src/core/EulerSwap.sol index 7ff0c29e9..c9c6203fa 100644 --- a/src/core/EulerSwap.sol +++ b/src/core/EulerSwap.sol @@ -386,7 +386,7 @@ library FastEulerSwap { let ptr := mload(0x40) mstore(ptr, 0x022c0d9f) // selector for `swap(uint256,uint256,address,bytes)` { - zeroForOne := shl(0x05, iszero(iszero(zeroForOne))) + zeroForOne := shl(0x05, lt(0x00, zeroForOne)) let amountsStart := add(0x20, ptr) let amountWord := add(amountsStart, zeroForOne) let zeroWord := add(xor(0x20, zeroForOne), amountsStart) diff --git a/src/core/FlashAccountingCommon.sol b/src/core/FlashAccountingCommon.sol index 614944508..96fafc8d6 100644 --- a/src/core/FlashAccountingCommon.sol +++ b/src/core/FlashAccountingCommon.sol @@ -409,7 +409,7 @@ library Encoder { mstore(add(0x24, data), 0x20) mstore(add(0x04, data), unlockSelector) mstore(data, add(0xb3, pathLen)) - mstore8(add(0xa8, data), iszero(iszero(feeOnTransfer))) + mstore8(add(0xa8, data), lt(0x00, feeOnTransfer)) mstore(0x40, add(data, add(0xd3, pathLen))) } @@ -455,7 +455,7 @@ library Encoder { mstore(0x40, add(0x03, ptr)) } - mstore8(add(0x131, data), iszero(iszero(isForwarded))) + mstore8(add(0x131, data), lt(0x00, isForwarded)) mcopy(add(0xf1, data), add(0x20, permit), 0x40) mcopy(add(0xb1, data), mload(permit), 0x40) // aliases `payer` on purpose mstore(add(0x9d, data), 0x00) // payer @@ -470,7 +470,7 @@ library Encoder { mstore(add(0x04, data), unlockSelector) mstore(data, add(0x115, add(pathLen, sigLen))) - mstore8(add(0xa8, data), iszero(iszero(feeOnTransfer))) + mstore8(add(0xa8, data), lt(0x00, feeOnTransfer)) } } } diff --git a/src/core/Hanji.sol b/src/core/Hanji.sol index 8116bd675..89f85d23c 100644 --- a/src/core/Hanji.sol +++ b/src/core/Hanji.sol @@ -64,7 +64,7 @@ library FastHanjiPool { ) internal returns (uint256 executed) { assembly ("memory-safe") { let ptr := mload(0x40) - isAsk := iszero(iszero(isAsk)) + isAsk := lt(0x00, isAsk) mstore(ptr, xor(0xad73d32e, mul(0x58603c62, isAsk))) // selector mstore(add(0x20, ptr), isAsk) mstore(add(0x40, ptr), and(0xffffffffffffffffffffffffffffffff, quantity)) @@ -91,6 +91,7 @@ library FastHanjiPool { function getToken(IHanjiPool pool, bool tokenY) internal view returns (IERC20 result) { assembly ("memory-safe") { let ptr := mload(0x40) + tokenY := lt(0x00, tokenY) mstore(0x00, 0xc3f909d4) // IHanjiPool.getConfig.selector if iszero(staticcall(gas(), pool, 0x1c, 0x04, 0x00, 0x80)) { @@ -98,7 +99,7 @@ library FastHanjiPool { revert(ptr, returndatasize()) } - result := mload(add(0x40, shl(0x05, iszero(iszero(tokenY))))) + result := mload(add(0x40, shl(0x05, tokenY))) mstore(0x40, ptr) mstore(0x60, 0x00) diff --git a/src/core/MaverickV2.sol b/src/core/MaverickV2.sol index 4c02a943b..767e3cc51 100644 --- a/src/core/MaverickV2.sol +++ b/src/core/MaverickV2.sol @@ -150,7 +150,7 @@ library FastMaverickV2Pool { mstore(add(0xc4, data), 0xc0) mstore(add(0xa4, data), signextend(0x03, tickLimit)) mstore(add(0x84, data), 0x00) // exactOutput is false - mstore(add(0x64, data), iszero(iszero(tokenAIn))) + mstore(add(0x64, data), lt(0x00, tokenAIn)) mstore(add(0x44, data), amount) mstore(add(0x24, data), recipient) mstore(add(0x10, data), 0x3eece7db000000000000000000000000) // selector for `swap(address,(uint256,bool,bool,int32),bytes)` with `recipient`'s padding diff --git a/src/core/PancakeInfinity.sol b/src/core/PancakeInfinity.sol index f35a6b1d6..2b310be18 100644 --- a/src/core/PancakeInfinity.sol +++ b/src/core/PancakeInfinity.sol @@ -149,7 +149,7 @@ library UnsafePancakeInfinityPoolManager { let ptr := mload(0x40) mstore(ptr, 0xcd0cc1ce) // selector for `swap((address,address,address,address,uint24,bytes32),(bool,int256,uint160),bytes)` mcopy(add(0x20, ptr), key, 0xc0) - mstore(add(0xe0, ptr), iszero(iszero(zeroForOne))) + mstore(add(0xe0, ptr), lt(0x00, zeroForOne)) mstore(add(0x100, ptr), amountSpecified) mstore(add(0x120, ptr), sqrtPriceLimitX96) mstore(add(0x140, ptr), 0x140) @@ -178,7 +178,7 @@ library UnsafePancakeInfinityBinPoolManager { let ptr := mload(0x40) mstore(ptr, 0x911a63b7) // selector for `swap((address,address,address,address,uint24,bytes32),bool,int128,bytes)` mcopy(add(0x20, ptr), key, 0xc0) - mstore(add(0xe0, ptr), iszero(iszero(swapForY))) + mstore(add(0xe0, ptr), lt(0x00, swapForY)) mstore(add(0x100, ptr), signextend(0x0f, amountSpecified)) mstore(add(0x120, ptr), 0x120) mstore(add(0x140, ptr), hookData.length) diff --git a/src/core/UniswapV2.sol b/src/core/UniswapV2.sol index cb8e5cf6d..45a7e975f 100644 --- a/src/core/UniswapV2.sol +++ b/src/core/UniswapV2.sol @@ -34,7 +34,7 @@ library fastUniswapV2Pool { revert(ptr, returndatasize()) } if lt(returndatasize(), 0x40) { revert(0x00, 0x00) } - let r := shl(0x05, iszero(iszero(zeroForOne))) + let r := shl(0x05, lt(0x00, zeroForOne)) buyReserve := mload(r) sellReserve := mload(xor(0x20, r)) } @@ -63,7 +63,7 @@ library fastUniswapV2Pool { // set amount0Out and amount1Out let buyAmountBaseOffset := add(0x20, ptr) // If `zeroForOne`, buyAmount offset is 0x40, else 0x20 - let directionOffset := shl(0x05, iszero(iszero(zeroForOne))) + let directionOffset := shl(0x05, lt(0x00, zeroForOne)) mstore(add(buyAmountBaseOffset, directionOffset), buyAmount) mstore(add(buyAmountBaseOffset, xor(0x20, directionOffset)), 0x00) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index 6c784b6b2..ef15be205 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -158,7 +158,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { mstore(add(0xa4, data), 0xa0) mstore(add(0x84, data), and(0xffffffffffffffffffffffffffffffffffffffff, sqrtPriceLimitX96)) mstore(add(0x64, data), sellAmount) - mstore(add(0x44, data), iszero(iszero(zeroForOne))) + mstore(add(0x44, data), lt(0x00, zeroForOne)) mstore(add(0x24, data), to) mstore(add(0x10, data), 0x128acb08000000000000000000000000) // selector for `swap(address,bool,int256,uint160,bytes)` with `to`'s padding @@ -250,7 +250,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { mcopy(add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, 0x20), swapCallbackData), add(0x20, permit), 0x40) mstore8( add(add(SWAP_CALLBACK_PERMIT2DATA_OFFSET, PERMIT_DATA_SIZE), swapCallbackData), - iszero(iszero(isForwarded)) + lt(0x00, isForwarded) ) mcopy( add( diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index 34c98ae05..5ddb4252a 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -4,25 +4,25 @@ pragma solidity ^0.8.25; library FastLogic { function or(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { - r := iszero(iszero(or(a, b))) + r := or(a, b) } } function and(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { - r := iszero(or(iszero(a), iszero(b))) + r := mul(a, lt(0x00, b)) } } function andNot(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { - r := iszero(or(iszero(a), b)) + r := mul(a, iszero(b)) } } function toUint(bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := iszero(iszero(b)) + r := lt(0x00, b) } } } diff --git a/src/utils/SafePermit.sol b/src/utils/SafePermit.sol index d6a2738c4..359af53dd 100644 --- a/src/utils/SafePermit.sol +++ b/src/utils/SafePermit.sol @@ -48,7 +48,7 @@ library FastPermit { mstore(add(0xf4, ptr), and(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, vs)) // `s`. mstore(add(0xd4, ptr), r) // `r`. mstore(add(0xb4, ptr), add(0x1b, shr(0xff, vs))) // `v`. - mstore(add(0x94, ptr), iszero(iszero(allowed))) + mstore(add(0x94, ptr), lt(0x00, allowed)) mstore(add(0x74, ptr), expiry) mstore(add(0x54, ptr), nonce) mstore(add(0x34, ptr), spender) @@ -272,7 +272,7 @@ library SafePermit { mstore(add(0x80, ptr), spender) mstore(add(0xa0, ptr), nonce) mstore(add(0xc0, ptr), deadline) - mstore(add(0xe0, ptr), iszero(iszero(allowed))) + mstore(add(0xe0, ptr), lt(0x00, allowed)) mstore(add(0x40, ptr), keccak256(add(0x40, ptr), 0xc0)) signingHash := keccak256(add(0x1e, ptr), 0x42) } diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index f150f03b7..8275146e4 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -10,72 +10,63 @@ library Ternary { function ternary(bool c, uint256 x, uint256 y) internal pure returns (uint256 r) { assembly ("memory-safe") { - c := iszero(iszero(c)) - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function ternary(bool c, int256 x, int256 y) internal pure returns (int256 r) { assembly ("memory-safe") { - c := iszero(iszero(c)) - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function ternary(bool c, bytes4 x, bytes4 y) internal pure returns (bytes4 r) { assembly ("memory-safe") { - c := iszero(iszero(c)) - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function ternary(bool c, address x, address y) internal pure returns (address r) { assembly ("memory-safe") { - c := iszero(iszero(c)) - r := xor(y, mul(xor(x, y), c)) + r := xor(x, mul(xor(x, y), iszero(c))) } } function orZero(bool c, uint256 x) internal pure returns (uint256 r) { assembly ("memory-safe") { - c := iszero(iszero(c)) - r := mul(x, c) + r := mul(x, lt(0x00, c)) } } function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { - c := iszero(iszero(c)) - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { - c := iszero(iszero(c)) - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { - c := iszero(iszero(c)) - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { - c := iszero(iszero(c)) - let t := mul(xor(x, y), c) - a := xor(x, t) - b := xor(y, t) + let t := mul(xor(x, y), iszero(c)) + a := xor(y, t) + b := xor(x, t) } } } diff --git a/src/utils/UnsafeMath.sol b/src/utils/UnsafeMath.sol index 0ed3f4ad3..e0341c9f4 100644 --- a/src/utils/UnsafeMath.sol +++ b/src/utils/UnsafeMath.sol @@ -12,7 +12,7 @@ library UnsafeMath { function unsafeInc(uint256 x, bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := add(x, iszero(iszero(b))) + r := add(x, lt(0x00, b)) } } @@ -30,7 +30,7 @@ library UnsafeMath { function unsafeDec(uint256 x, bool b) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := sub(x, iszero(iszero(b))) + r := sub(x, lt(0x00, b)) } } @@ -113,7 +113,7 @@ library UnsafeMath { library Math { function inc(uint256 x, bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := add(x, iszero(iszero(c))) + r := add(x, lt(0x00, c)) } if (r < x) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); @@ -122,7 +122,7 @@ library Math { function dec(uint256 x, bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := sub(x, iszero(iszero(c))) + r := sub(x, lt(0x00, c)) } if (r > x) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); @@ -131,7 +131,7 @@ library Math { function toInt(bool c) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := iszero(iszero(c)) + r := lt(0x00, c) } } From 632ee47626dc7c6bcf7700087ab32ada9c323882 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 18:58:07 +0200 Subject: [PATCH 004/107] Fix additional bool cleanup sites missed in first pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FastLogic.andNot: use iszero(or(iszero(a), b)) — cleaner formulation - CurveTricrypto: remove redundant clean-on-read (write-side suffices) - CrossChainReceiverFactory: normalize bool immutable in mul (london EVM, uses iszero(iszero) since no PUSH0) - SettlerIntent.setSolver: normalize addNotRemove for xor/mul/sstore use - EulerSwap: validate bool from external staticcall returndata; normalize zeroForOne before shl - UniswapV2: normalize zeroForOne before shl in both getReserves and swap - FlashAccountingCommon, UniswapV3Fork: upgrade silent and(0x01,...) mask to reverting validation for callback bool data Co-Authored-By: Claude Opus 4.6 (1M context) --- src/CrossChainReceiverFactory.sol | 2 +- src/SettlerIntent.sol | 1 + src/core/CurveTricrypto.sol | 2 +- src/core/EulerSwap.sol | 3 ++- src/core/FlashAccountingCommon.sol | 3 ++- src/core/UniswapV2.sol | 4 ++-- src/core/UniswapV3Fork.sol | 3 ++- src/utils/FastLogic.sol | 4 ++-- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index 1142d9e38..4b38cf532 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -960,7 +960,7 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte revert(codesize(), callvalue()) } - wrappedBalance := mul(hasWnative, mload(callvalue())) + wrappedBalance := mul(iszero(iszero(hasWnative)), mload(callvalue())) } uint256 toUnwrap = (address(this).balance + wrappedBalance < value) diff --git a/src/SettlerIntent.sol b/src/SettlerIntent.sol index 3ae6dafae..bbb5f1e4e 100644 --- a/src/SettlerIntent.sol +++ b/src/SettlerIntent.sol @@ -138,6 +138,7 @@ abstract contract SettlerIntent is MultiCallContext, Permit2PaymentIntent, Settl // Clean dirty bits. prev := shr(0x60, shl(0x60, prev)) solver := shr(0x60, shl(0x60, solver)) + addNotRemove := lt(0x00, addNotRemove) // A solver of zero is special-cased. It is forbidden to set it because that would // corrupt the list. diff --git a/src/core/CurveTricrypto.sol b/src/core/CurveTricrypto.sol index 4a3ba9e8b..879fec24a 100644 --- a/src/core/CurveTricrypto.sol +++ b/src/core/CurveTricrypto.sol @@ -152,7 +152,7 @@ abstract contract CurveTricrypto is SettlerSwapAbstract { uint256 deadline; bytes memory sig; assembly ("memory-safe") { - isForwarded := lt(0x00, tload(0x00)) + isForwarded := tload(0x00) tstore(0x00, 0x00) permittedAmount := tload(0x01) tstore(0x01, 0x00) diff --git a/src/core/EulerSwap.sol b/src/core/EulerSwap.sol index 83a363fd1..dd6b7e6b6 100644 --- a/src/core/EulerSwap.sol +++ b/src/core/EulerSwap.sol @@ -56,6 +56,7 @@ library FastEvc { revert(ptr_, returndatasize()) } authorized := mload(0x00) + if or(lt(returndatasize(), 0x20), shr(0x01, authorized)) { revert(0x00, 0x00) } mstore(0x40, ptr) } } @@ -384,7 +385,7 @@ library FastEulerSwap { let ptr := mload(0x40) mstore(ptr, 0x022c0d9f) // selector for `swap(uint256,uint256,address,bytes)` { - zeroForOne := shl(0x05, zeroForOne) + zeroForOne := shl(0x05, lt(0x00, zeroForOne)) let amountsStart := add(0x20, ptr) let amountWord := add(amountsStart, zeroForOne) let zeroWord := add(xor(0x20, zeroForOne), amountsStart) diff --git a/src/core/FlashAccountingCommon.sol b/src/core/FlashAccountingCommon.sol index c32236d21..8ee022bd9 100644 --- a/src/core/FlashAccountingCommon.sol +++ b/src/core/FlashAccountingCommon.sol @@ -694,7 +694,8 @@ library Decoder { // the middle of `payer`, because `payer` is all zeroes, it's treated as padding // for the first word of `permit`, which is the sell token permit := sub(data.offset, 0x0c) - isForwarded := and(0x01, calldataload(add(0x55, data.offset))) + isForwarded := and(0xff, calldataload(add(0x55, data.offset))) + if shr(0x01, isForwarded) { revert(0x00, 0x00) } // `sig` is packed at the end of `data`, in "reverse ABI-ish encoded" fashion sig.offset := sub(add(data.offset, data.length), 0x03) diff --git a/src/core/UniswapV2.sol b/src/core/UniswapV2.sol index 48c6c001e..45a7e975f 100644 --- a/src/core/UniswapV2.sol +++ b/src/core/UniswapV2.sol @@ -34,7 +34,7 @@ library fastUniswapV2Pool { revert(ptr, returndatasize()) } if lt(returndatasize(), 0x40) { revert(0x00, 0x00) } - let r := shl(0x05, zeroForOne) + let r := shl(0x05, lt(0x00, zeroForOne)) buyReserve := mload(r) sellReserve := mload(xor(0x20, r)) } @@ -63,7 +63,7 @@ library fastUniswapV2Pool { // set amount0Out and amount1Out let buyAmountBaseOffset := add(0x20, ptr) // If `zeroForOne`, buyAmount offset is 0x40, else 0x20 - let directionOffset := shl(0x05, zeroForOne) + let directionOffset := shl(0x05, lt(0x00, zeroForOne)) mstore(add(buyAmountBaseOffset, directionOffset), buyAmount) mstore(add(buyAmountBaseOffset, xor(0x20, directionOffset)), 0x00) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index a3359dec7..1cb915adf 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -362,7 +362,8 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // middle of `payer`, because `payer` is all zeroes, it's treated as padding for the // first word of `permit`, which is the sell token permit := sub(permit2Data.offset, 0x0c) - isForwarded := and(0x01, calldataload(add(0x55, permit2Data.offset))) + isForwarded := and(0xff, calldataload(add(0x55, permit2Data.offset))) + if shr(0x01, isForwarded) { revert(0x00, 0x00) } sig.offset := add(0x75, permit2Data.offset) sig.length := sub(permit2Data.length, 0x75) } diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index dad97bcf4..475224d11 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -19,9 +19,9 @@ library FastLogic { } function andNot(bool a, bool b) internal pure returns (bool r) { - // a ∧ ¬b: normalize via iszero then compare + // a ∧ ¬b ≡ ¬(¬a ∨ b); `b` needs no normalization since any nonzero makes `or` nonzero assembly ("memory-safe") { - r := gt(iszero(b), iszero(a)) + r := iszero(or(iszero(a), b)) } } From a27a056253ca38570a0e5a8b4063a06cc2a63736 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 19:04:00 +0200 Subject: [PATCH 005/107] Simplify strict bool decoder assembly --- src/core/EkuboV2.sol | 5 ++--- src/core/EulerSwap.sol | 5 ++--- src/core/FlashAccountingCommon.sol | 5 ++--- src/core/UniswapV3Fork.sol | 5 ++--- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/core/EkuboV2.sol b/src/core/EkuboV2.sol index 512b4e209..62e50c4b5 100644 --- a/src/core/EkuboV2.sol +++ b/src/core/EkuboV2.sol @@ -528,9 +528,8 @@ abstract contract EkuboV2 is SettlerSwapAbstract { assembly ("memory-safe") { // starts at the beginning of sellToken permit := add(0x20, data.offset) - let isForwarded_ := calldataload(add(0xa0, data.offset)) - if shr(0x01, isForwarded_) { revert(0x00, 0x00) } - isForwarded := isForwarded_ + isForwarded := calldataload(add(0xa0, data.offset)) + if shr(0x01, isForwarded) { revert(0x00, 0x00) } sig.offset := add(0xc0, data.offset) sig.length := calldataload(sig.offset) diff --git a/src/core/EulerSwap.sol b/src/core/EulerSwap.sol index c9c6203fa..dd6b7e6b6 100644 --- a/src/core/EulerSwap.sol +++ b/src/core/EulerSwap.sol @@ -55,9 +55,8 @@ library FastEvc { returndatacopy(ptr_, 0x00, returndatasize()) revert(ptr_, returndatasize()) } - let authorized_ := mload(0x00) - if or(lt(returndatasize(), 0x20), shr(0x01, authorized_)) { revert(0x00, 0x00) } - authorized := authorized_ + authorized := mload(0x00) + if or(lt(returndatasize(), 0x20), shr(0x01, authorized)) { revert(0x00, 0x00) } mstore(0x40, ptr) } } diff --git a/src/core/FlashAccountingCommon.sol b/src/core/FlashAccountingCommon.sol index 96fafc8d6..8ee022bd9 100644 --- a/src/core/FlashAccountingCommon.sol +++ b/src/core/FlashAccountingCommon.sol @@ -694,9 +694,8 @@ library Decoder { // the middle of `payer`, because `payer` is all zeroes, it's treated as padding // for the first word of `permit`, which is the sell token permit := sub(data.offset, 0x0c) - let isForwarded_ := and(0xff, calldataload(add(0x55, data.offset))) - if shr(0x01, isForwarded_) { revert(0x00, 0x00) } - isForwarded := isForwarded_ + isForwarded := and(0xff, calldataload(add(0x55, data.offset))) + if shr(0x01, isForwarded) { revert(0x00, 0x00) } // `sig` is packed at the end of `data`, in "reverse ABI-ish encoded" fashion sig.offset := sub(add(data.offset, data.length), 0x03) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index ef15be205..f8d23a368 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -365,9 +365,8 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // middle of `payer`, because `payer` is all zeroes, it's treated as padding for the // first word of `permit`, which is the sell token permit := sub(permit2Data.offset, 0x0c) - let isForwarded_ := and(0xff, calldataload(add(0x55, permit2Data.offset))) - if shr(0x01, isForwarded_) { revert(0x00, 0x00) } - isForwarded := isForwarded_ + isForwarded := and(0xff, calldataload(add(0x55, permit2Data.offset))) + if shr(0x01, isForwarded) { revert(0x00, 0x00) } sig.offset := add(0x75, permit2Data.offset) sig.length := sub(permit2Data.length, 0x75) } From 2f4e4a0654001f17238baf25cf4aaef176f29b50 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 19:04:01 +0200 Subject: [PATCH 006/107] Improve FastLogic and fix CrossChainReceiverFactory bool cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FastLogic.and: mul(a, lt(0x00, b)) — cheaper than De Morgan (10 gas on Osaka vs 12; 11 on London vs 12) - FastLogic.andNot: mul(a, iszero(b)) — 8 gas, no PUSH0 needed - CrossChainReceiverFactory.deploy: normalize setOwnerNotCleanup bool before arithmetic use (iszero/iszero for London EVM) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/CrossChainReceiverFactory.sol | 2 ++ src/utils/FastLogic.sol | 9 ++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index 4b38cf532..a7bfab8ca 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -407,6 +407,8 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte bytes32 proxyInitCode0 = _proxyInitCode0; bytes32 proxyInitCode1 = _proxyInitCode1; assembly ("memory-safe") { + setOwnerNotCleanup := iszero(iszero(setOwnerNotCleanup)) + // derive the deployment salt from the owner mstore(0x14, initialOwner) mstore(callvalue(), root) diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index 475224d11..5ddb4252a 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -1,9 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -// Solidity `bool` may be any nonzero value for truthy. Bitwise `or` preserves truthiness so -// `or(a, b)` is safe. `and`/`andNot` are rewritten using `iszero` (always 0/1) to implement -// correct logical semantics. `toUint` normalizes with `lt(0x00, b)` (PUSH0 + LT = 5 gas). library FastLogic { function or(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { @@ -12,16 +9,14 @@ library FastLogic { } function and(bool a, bool b) internal pure returns (bool r) { - // De Morgan: a ∧ b ≡ ¬(¬a ∨ ¬b) assembly ("memory-safe") { - r := iszero(or(iszero(a), iszero(b))) + r := mul(a, lt(0x00, b)) } } function andNot(bool a, bool b) internal pure returns (bool r) { - // a ∧ ¬b ≡ ¬(¬a ∨ b); `b` needs no normalization since any nonzero makes `or` nonzero assembly ("memory-safe") { - r := iszero(or(iszero(a), b)) + r := mul(a, iszero(b)) } } From fd8946f4ceee61b71308947354ca2ccf17b325ae Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 19:27:32 +0200 Subject: [PATCH 007/107] Add comments to FastLogic explaining dirty-bool handling Co-Authored-By: Claude Opus 4.6 (1M context) --- src/utils/FastLogic.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index 5ddb4252a..3636dcb85 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -1,19 +1,27 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; +// All functions accept dirty bools (any nonzero value is truthy) and return dirty bools (the +// result is truthy/falsy but not necessarily 0/1). `toUint` is the exception: it normalizes to +// exactly 0 or 1. `lt(0x00, x)` normalizes a dirty bool to 0/1 for 5 gas (PUSH0 + LT). On +// London (no PUSH0), it costs 6 gas and 1 extra byte; `iszero(iszero(x))` is equivalent there. library FastLogic { + // `or(nonzero, anything)` is nonzero; truthiness is preserved without normalization function or(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { r := or(a, b) } } + // Normalize `b` to 0/1, multiply by `a`. No overflow since one factor is always 0 or 1. + // Dirty `a` in the output is fine (truthy iff both inputs truthy). function and(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { r := mul(a, lt(0x00, b)) } } + // `iszero(b)` is 0/1; multiply by `a`. Result is truthy iff `a` truthy and `b` falsy. function andNot(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { r := mul(a, iszero(b)) From ba92d74ee049069cc7c2c950be77f79c22197af8 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 19:44:19 +0200 Subject: [PATCH 008/107] Cleaning up slop --- src/CrossChainReceiverFactory.sol | 4 ++-- src/core/EulerSwap.sol | 3 ++- src/core/FlashAccountingCommon.sol | 3 +-- src/core/UniswapV3Fork.sol | 3 +-- src/utils/FastLogic.sol | 8 -------- src/utils/Ternary.sol | 4 ---- 6 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index a7bfab8ca..203549be9 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -952,7 +952,7 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte if (address(this).balance < value) { uint256 wrappedBalance; IWrappedNative wnative = _WNATIVE; - bool hasWnative = _HAS_WNATIVE; + bool missingWnative = _MISSING_WNATIVE; assembly ("memory-safe") { mstore(0x00, 0x70a08231) // `IERC20.balanceOf.selector` mstore(0x20, address()) @@ -962,7 +962,7 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte revert(codesize(), callvalue()) } - wrappedBalance := mul(iszero(iszero(hasWnative)), mload(callvalue())) + wrappedBalance := mul(iszero(missingWnative), mload(callvalue())) } uint256 toUnwrap = (address(this).balance + wrappedBalance < value) diff --git a/src/core/EulerSwap.sol b/src/core/EulerSwap.sol index dd6b7e6b6..d14905fa1 100644 --- a/src/core/EulerSwap.sol +++ b/src/core/EulerSwap.sol @@ -56,7 +56,8 @@ library FastEvc { revert(ptr_, returndatasize()) } authorized := mload(0x00) - if or(lt(returndatasize(), 0x20), shr(0x01, authorized)) { revert(0x00, 0x00) } + // we don't check for short returndata or dirty bits because we know that `evc` is + // well-behaved mstore(0x40, ptr) } } diff --git a/src/core/FlashAccountingCommon.sol b/src/core/FlashAccountingCommon.sol index 8ee022bd9..c32236d21 100644 --- a/src/core/FlashAccountingCommon.sol +++ b/src/core/FlashAccountingCommon.sol @@ -694,8 +694,7 @@ library Decoder { // the middle of `payer`, because `payer` is all zeroes, it's treated as padding // for the first word of `permit`, which is the sell token permit := sub(data.offset, 0x0c) - isForwarded := and(0xff, calldataload(add(0x55, data.offset))) - if shr(0x01, isForwarded) { revert(0x00, 0x00) } + isForwarded := and(0x01, calldataload(add(0x55, data.offset))) // `sig` is packed at the end of `data`, in "reverse ABI-ish encoded" fashion sig.offset := sub(add(data.offset, data.length), 0x03) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index f8d23a368..8255e1910 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -365,8 +365,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // middle of `payer`, because `payer` is all zeroes, it's treated as padding for the // first word of `permit`, which is the sell token permit := sub(permit2Data.offset, 0x0c) - isForwarded := and(0xff, calldataload(add(0x55, permit2Data.offset))) - if shr(0x01, isForwarded) { revert(0x00, 0x00) } + isForwarded := and(0x01, calldataload(add(0x55, permit2Data.offset))) sig.offset := add(0x75, permit2Data.offset) sig.length := sub(permit2Data.length, 0x75) } diff --git a/src/utils/FastLogic.sol b/src/utils/FastLogic.sol index 3636dcb85..5ddb4252a 100644 --- a/src/utils/FastLogic.sol +++ b/src/utils/FastLogic.sol @@ -1,27 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -// All functions accept dirty bools (any nonzero value is truthy) and return dirty bools (the -// result is truthy/falsy but not necessarily 0/1). `toUint` is the exception: it normalizes to -// exactly 0 or 1. `lt(0x00, x)` normalizes a dirty bool to 0/1 for 5 gas (PUSH0 + LT). On -// London (no PUSH0), it costs 6 gas and 1 extra byte; `iszero(iszero(x))` is equivalent there. library FastLogic { - // `or(nonzero, anything)` is nonzero; truthiness is preserved without normalization function or(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { r := or(a, b) } } - // Normalize `b` to 0/1, multiply by `a`. No overflow since one factor is always 0 or 1. - // Dirty `a` in the output is fine (truthy iff both inputs truthy). function and(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { r := mul(a, lt(0x00, b)) } } - // `iszero(b)` is 0/1; multiply by `a`. Result is truthy iff `a` truthy and `b` falsy. function andNot(bool a, bool b) internal pure returns (bool r) { assembly ("memory-safe") { r := mul(a, iszero(b)) diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index 901f136ed..8275146e4 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -8,10 +8,6 @@ library Ternary { //// it doesn't need to do a ton of masking when types are cast to each other without //// modification. - // Solidity `bool` may be any nonzero value for truthy. `iszero(c)` produces clean 0/1 and we - // restructure each formula around the negated condition so a single `iszero` suffices. - // `orZero` has no negation-based reformulation, so it uses `lt(0x00, c)` to normalize. - function ternary(bool c, uint256 x, uint256 y) internal pure returns (uint256 r) { assembly ("memory-safe") { r := xor(x, mul(xor(x, y), iszero(c))) From cdf522fb536a1cae07aca74d087127963b74b235 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 20:57:27 +0200 Subject: [PATCH 009/107] Stack-too-deep --- .github/workflows/size.yml | 7 ++++++- .github/workflows/test.yml | 13 +++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml index 9da299260..477f29db8 100644 --- a/.github/workflows/size.yml +++ b/.github/workflows/size.yml @@ -36,4 +36,9 @@ jobs: run: npm install - name: Check chain-specific Settler contract sizes - run: forge build --sizes --skip MultiCall.sol --skip CrossChainReceiverFactory.sol --skip AllowanceHolder.sol --skip Deployer.sol --skip 'test/*' -- src/chains/ + run: | + set -Eeufo pipefail -o posix + jq -r '.[].displayName' < chain_config.json | while IFS= read -r chain ; do + echo 'Checking sizes for '"$chain" >&2 + forge build --sizes -- src/chains/"$chain" + done diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index da67c92fe..43631ed5e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,15 @@ jobs: run: forge test --skip 'src/*' --skip 'script/*' --skip 'test/unit/*' --skip 'test/integration/*' --skip 'test/0.8.25/*' --mp test/0.8.28/EulerSwapBUSL.t.sol - name: Build contracts - run: forge build --skip MultiCall.sol --skip CrossChainReceiverFactory.sol --skip AllowanceHolder.sol --skip Deployer.sol --skip 'test/*' --skip 'script/*' + run: forge build --skip MultiCall.sol --skip CrossChainReceiverFactory.sol --skip AllowanceHolder.sol --skip Deployer.sol --skip 'src/chains/*' --skip 'test/*' --skip 'script/*' + + - name: Build chain-specific Settlers + run: | + set -Eeufo pipefail -o posix + jq -r '.[].displayName' < chain_config.json | while IFS= read -r chain ; do + echo 'Building '"$chain" >&2 + forge build -- src/chains/"$chain" + done - name: Build AllowanceHolder and Deployer run: forge build -- src/allowanceholder/AllowanceHolder.sol src/deployer/Deployer.sol @@ -71,9 +79,6 @@ jobs: - name: Run CrossChainReceiverFactory tests run: forge test --skip 'src/*' --skip 'test/integration/*' --skip 'test/0.8.28/*' --skip 'test/0.8.25/*' --mp test/unit/CrossChainReceiverFactory.t.sol - - name: Build Base Settlers - run: forge build src/chains/Base/ - - name: Run all the other tests run: FOUNDRY_FUZZ_SEED="0x$(python3 -c 'import secrets, binascii; print(binascii.hexlify((secrets.randbits(256)).to_bytes(32, byteorder="big")).decode("ascii"))')" forge test --skip 'src/*' --skip 'test/0.8.28/*' --skip CrossChainReceiverFactory.t.sol --skip MultiCall.t.sol env: From 936ebc547e9c44905f84c616b3872ac4804c67a5 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 20:58:45 +0200 Subject: [PATCH 010/107] Stack-too-deep --- src/utils/Ternary.sol | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index 8275146e4..30868e54c 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -40,33 +40,33 @@ library Ternary { function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { - let t := mul(xor(x, y), iszero(c)) - a := xor(y, t) - b := xor(x, t) + let t := mul(sub(y, x), lt(0x00, c)) + a := add(x, t) + b := sub(y, t) } } function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { - let t := mul(xor(x, y), iszero(c)) - a := xor(y, t) - b := xor(x, t) + let t := mul(sub(y, x), lt(0x00, c)) + a := add(x, t) + b := sub(y, t) } } function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { - let t := mul(xor(x, y), iszero(c)) - a := xor(y, t) - b := xor(x, t) + let t := mul(sub(y, x), lt(0x00, c)) + a := add(x, t) + b := sub(y, t) } } function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { - let t := mul(xor(x, y), iszero(c)) - a := xor(y, t) - b := xor(x, t) + let t := mul(sub(y, x), lt(0x00, c)) + a := add(x, t) + b := sub(y, t) } } } From 008ca48f412b4f7e722b027f76c54d2c783a4b73 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 22:34:59 +0200 Subject: [PATCH 011/107] Cleaning up slop --- src/core/EkuboV2.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/EkuboV2.sol b/src/core/EkuboV2.sol index 62e50c4b5..354b6a400 100644 --- a/src/core/EkuboV2.sol +++ b/src/core/EkuboV2.sol @@ -529,7 +529,6 @@ abstract contract EkuboV2 is SettlerSwapAbstract { // starts at the beginning of sellToken permit := add(0x20, data.offset) isForwarded := calldataload(add(0xa0, data.offset)) - if shr(0x01, isForwarded) { revert(0x00, 0x00) } sig.offset := add(0xc0, data.offset) sig.length := calldataload(sig.offset) From cfc6a2e4cba1a9f64a1eb0b20f2a96b8da0b78af Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 22:36:07 +0200 Subject: [PATCH 012/107] Cleaning up slop --- .github/workflows/test.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43631ed5e..4b6729408 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,14 +33,6 @@ jobs: - name: Build contracts run: forge build --skip MultiCall.sol --skip CrossChainReceiverFactory.sol --skip AllowanceHolder.sol --skip Deployer.sol --skip 'src/chains/*' --skip 'test/*' --skip 'script/*' - - name: Build chain-specific Settlers - run: | - set -Eeufo pipefail -o posix - jq -r '.[].displayName' < chain_config.json | while IFS= read -r chain ; do - echo 'Building '"$chain" >&2 - forge build -- src/chains/"$chain" - done - - name: Build AllowanceHolder and Deployer run: forge build -- src/allowanceholder/AllowanceHolder.sol src/deployer/Deployer.sol env: @@ -79,6 +71,9 @@ jobs: - name: Run CrossChainReceiverFactory tests run: forge test --skip 'src/*' --skip 'test/integration/*' --skip 'test/0.8.28/*' --skip 'test/0.8.25/*' --mp test/unit/CrossChainReceiverFactory.t.sol + - name: Build Base Settlers + run: forge build src/chains/Base/ + - name: Run all the other tests run: FOUNDRY_FUZZ_SEED="0x$(python3 -c 'import secrets, binascii; print(binascii.hexlify((secrets.randbits(256)).to_bytes(32, byteorder="big")).decode("ascii"))')" forge test --skip 'src/*' --skip 'test/0.8.28/*' --skip CrossChainReceiverFactory.t.sol --skip MultiCall.t.sol env: From 6551562321b3d142953df1c8df694da4124e67ad Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 22:38:46 +0200 Subject: [PATCH 013/107] Cleaning up slop --- src/core/UniswapV2.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/UniswapV2.sol b/src/core/UniswapV2.sol index 45a7e975f..92a5e5aa7 100644 --- a/src/core/UniswapV2.sol +++ b/src/core/UniswapV2.sol @@ -34,9 +34,9 @@ library fastUniswapV2Pool { revert(ptr, returndatasize()) } if lt(returndatasize(), 0x40) { revert(0x00, 0x00) } - let r := shl(0x05, lt(0x00, zeroForOne)) - buyReserve := mload(r) - sellReserve := mload(xor(0x20, r)) + let r := shl(0x05, iszero(zeroForOne)) + sellReserve := mload(r) + buyReserve := mload(xor(0x20, r)) } } @@ -63,9 +63,9 @@ library fastUniswapV2Pool { // set amount0Out and amount1Out let buyAmountBaseOffset := add(0x20, ptr) // If `zeroForOne`, buyAmount offset is 0x40, else 0x20 - let directionOffset := shl(0x05, lt(0x00, zeroForOne)) - mstore(add(buyAmountBaseOffset, directionOffset), buyAmount) - mstore(add(buyAmountBaseOffset, xor(0x20, directionOffset)), 0x00) + let directionOffset := shl(0x05, iszero(zeroForOne)) + mstore(add(buyAmountBaseOffset, directionOffset), 0x00) + mstore(add(buyAmountBaseOffset, xor(0x20, directionOffset)), buyAmount) mstore(add(0x60, ptr), and(0xffffffffffffffffffffffffffffffffffffffff, recipient)) mstore(add(0x80, ptr), 0x80) // offset to length of data From 7eb275de57b7a69ffcfaaafe676c690592a71aa3 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 22:40:33 +0200 Subject: [PATCH 014/107] Cleaning up slop --- src/core/EulerSwap.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/EulerSwap.sol b/src/core/EulerSwap.sol index d14905fa1..b3abe4929 100644 --- a/src/core/EulerSwap.sol +++ b/src/core/EulerSwap.sol @@ -386,10 +386,10 @@ library FastEulerSwap { let ptr := mload(0x40) mstore(ptr, 0x022c0d9f) // selector for `swap(uint256,uint256,address,bytes)` { - zeroForOne := shl(0x05, lt(0x00, zeroForOne)) + zeroForOne := shl(0x05, iszero(zeroForOne)) let amountsStart := add(0x20, ptr) - let amountWord := add(amountsStart, zeroForOne) - let zeroWord := add(xor(0x20, zeroForOne), amountsStart) + let zeroWord := add(zeroForOne, amountsStart) + let amountWord := add(amountsStart, xor(0x20, zeroForOne)) mstore(amountWord, amountOut) mstore(zeroWord, 0x00) } From 058e62c5fc5036932d140b99f4688e27e2c00bef Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Apr 2026 22:45:39 +0200 Subject: [PATCH 015/107] Reduce stack pressure --- src/utils/Ternary.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index 30868e54c..e31e07eb7 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -34,13 +34,13 @@ library Ternary { function orZero(bool c, uint256 x) internal pure returns (uint256 r) { assembly ("memory-safe") { - r := mul(x, lt(0x00, c)) + r := mul(lt(0x00, c), x) } } function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { - let t := mul(sub(y, x), lt(0x00, c)) + let t := mul(lt(0x00, c), sub(y, x)) a := add(x, t) b := sub(y, t) } @@ -48,7 +48,7 @@ library Ternary { function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { - let t := mul(sub(y, x), lt(0x00, c)) + let t := mul(lt(0x00, c), sub(y, x)) a := add(x, t) b := sub(y, t) } @@ -56,7 +56,7 @@ library Ternary { function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { - let t := mul(sub(y, x), lt(0x00, c)) + let t := mul(lt(0x00, c), sub(y, x)) a := add(x, t) b := sub(y, t) } @@ -64,7 +64,7 @@ library Ternary { function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { - let t := mul(sub(y, x), lt(0x00, c)) + let t := mul(lt(0x00, c), sub(y, x)) a := add(x, t) b := sub(y, t) } From 6f22edc61b15dd12bd95805a232021e4e2872eb5 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 16 Apr 2026 09:18:46 +0200 Subject: [PATCH 016/107] Fix CI --- test/unit/core/UniswapV3UnitTest.t.sol | 158 ++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 14 deletions(-) diff --git a/test/unit/core/UniswapV3UnitTest.t.sol b/test/unit/core/UniswapV3UnitTest.t.sol index e2d4b0477..d7d86e3aa 100644 --- a/test/unit/core/UniswapV3UnitTest.t.sol +++ b/test/unit/core/UniswapV3UnitTest.t.sol @@ -2,24 +2,28 @@ pragma solidity ^0.8.25; import {IUniswapV3Pool, UniswapV3Fork} from "src/core/UniswapV3Fork.sol"; -import {Permit2PaymentTakerSubmitted} from "src/core/Permit2Payment.sol"; -import {Permit2PaymentAbstract} from "src/core/Permit2PaymentAbstract.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; import {AddressDerivation} from "src/utils/AddressDerivation.sol"; import {AllowanceHolderContext} from "src/allowanceholder/AllowanceHolderContext.sol"; import {uniswapV3InitHash, IUniswapV3Callback} from "src/core/univ3forks/UniswapV3.sol"; import {revertUnknownForkId} from "src/core/SettlerErrors.sol"; import {uint512} from "src/utils/512Math.sol"; +import {AbstractContext} from "src/Context.sol"; -import {IAllowanceHolder} from "src/allowanceholder/IAllowanceHolder.sol"; +import {IAllowanceHolder, ALLOWANCE_HOLDER} from "src/allowanceholder/IAllowanceHolder.sol"; import {Utils} from "../Utils.sol"; import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {Test} from "@forge-std/Test.sol"; -contract UniswapV3Dummy is Permit2PaymentTakerSubmitted, UniswapV3Fork { +ISignatureTransfer constant PERMIT2 = ISignatureTransfer(0x000000000022D473030F116dDEE9F6B43aC78BA3); + +contract UniswapV3Dummy is AllowanceHolderContext, UniswapV3Fork { address internal immutable uniFactory; + address private _payer; + address private _callbackCaller; + function(bytes calldata) internal returns (bytes memory) private _callback; constructor(address _uniFactory) { uniFactory = _uniFactory; @@ -29,6 +33,16 @@ contract UniswapV3Dummy is Permit2PaymentTakerSubmitted, UniswapV3Fork { revert("unimplemented"); } + fallback(bytes calldata) external returns (bytes memory) { + require(_operator() == _callbackCaller); + bytes calldata data = _msgData(); + require(uint32(bytes4(data)) == uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector)); + function(bytes calldata) internal returns (bytes memory) callback = _callback; + delete _callback; + delete _callbackCaller; + return callback(data[4:]); + } + function sellSelf(address recipient, uint256 bps, bytes memory encodedPath, uint256 minBuyAmount) external takerSubmitted @@ -51,6 +65,14 @@ contract UniswapV3Dummy is Permit2PaymentTakerSubmitted, UniswapV3Fork { return false; } + function _msgSender() internal view override(AbstractContext, AllowanceHolderContext) returns (address payer) { + require((payer = _payer) != address(0)); + } + + function _operator() internal view override returns (address) { + return super._msgSender(); + } + function _dispatch(uint256, uint256, bytes calldata, AllowedSlippage memory) internal pure override returns (bool) { revert("unimplemented"); } @@ -74,13 +96,121 @@ contract UniswapV3Dummy is Permit2PaymentTakerSubmitted, UniswapV3Fork { } } - function _isRestrictedTarget(address target) + function _isRestrictedTarget(address) internal pure override returns (bool) { + return false; + } + + function _permitToSellAmountCalldata(ISignatureTransfer.PermitTransferFrom calldata permit) internal - view - override(Permit2PaymentTakerSubmitted, Permit2PaymentAbstract) - returns (bool) + pure + override + returns (uint256) + { + return permit.permitted.amount; + } + + function _permitToSellAmount(ISignatureTransfer.PermitTransferFrom memory permit) + internal + pure + override + returns (uint256) + { + return permit.permitted.amount; + } + + function _permitToTransferDetails(ISignatureTransfer.PermitTransferFrom memory permit, address recipient) + internal + pure + override + returns (ISignatureTransfer.SignatureTransferDetails memory transferDetails, uint256 sellAmount) + { + transferDetails.to = recipient; + transferDetails.requestedAmount = sellAmount = permit.permitted.amount; + } + + function _transferFromIKnowWhatImDoing( + ISignatureTransfer.PermitTransferFrom memory, + ISignatureTransfer.SignatureTransferDetails memory, + address, + bytes32, + string memory, + bytes memory, + bool + ) internal pure override { + revert("unimplemented"); + } + + function _transferFromIKnowWhatImDoing( + ISignatureTransfer.PermitTransferFrom memory, + ISignatureTransfer.SignatureTransferDetails memory, + address, + bytes32, + string memory, + bytes memory + ) internal pure override { + revert("unimplemented"); + } + + function _transferFrom( + ISignatureTransfer.PermitTransferFrom memory permit, + ISignatureTransfer.SignatureTransferDetails memory transferDetails, + bytes memory sig, + bool isForwarded + ) internal override { + if (isForwarded) { + require(sig.length == 0); + require(permit.nonce == 0); + require(block.timestamp <= permit.deadline); + _allowanceHolderTransferFrom( + permit.permitted.token, _msgSender(), transferDetails.to, transferDetails.requestedAmount + ); + } else { + PERMIT2.permitTransferFrom(permit, transferDetails, _msgSender(), sig); + } + } + + function _transferFrom( + ISignatureTransfer.PermitTransferFrom memory permit, + ISignatureTransfer.SignatureTransferDetails memory transferDetails, + bytes memory sig + ) internal override { + _transferFrom(permit, transferDetails, sig, _isForwarded()); + } + + function _setOperatorAndCall( + address target, + bytes memory data, + uint32 selector, + function(bytes calldata) internal returns (bytes memory) callback + ) internal override returns (bytes memory) { + _callback = callback; + _callbackCaller = target; + require(selector == uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector)); + (bool success, bytes memory returndata) = target.call(data); + if (!success) { + assembly ("memory-safe") { + revert(add(0x20, returndata), mload(returndata)) + } + } + return returndata; + } + + modifier metaTx(address, bytes32) override { + revert("unimplemented"); + _; + } + + modifier takerSubmitted() override { + _payer = _operator(); + _; + delete _payer; + } + + function _allowanceHolderTransferFrom(address token, address owner, address recipient, uint256 amount) + internal + override { - return super._isRestrictedTarget(target); + require(ALLOWANCE_HOLDER.transferFrom(token, owner, recipient, amount)); } } @@ -126,8 +256,6 @@ contract UniswapV3PoolDirtyForwardedBoolDummy { contract UniswapV3UnitTest is Utils, Test { UniswapV3Dummy uni; address UNI_FACTORY = _createNamedRejectionDummy("UNI_FACTORY"); - address PERMIT2 = _etchNamedRejectionDummy("PERMIT2", 0x000000000022D473030F116dDEE9F6B43aC78BA3); - address ALLOWANCE_HOLDER = _etchNamedRejectionDummy("ALLOWANCE_HOLDER", 0x0000000000001fF3684f28c67538d4D072C22734); address TOKEN0 = _createNamedRejectionDummy("TOKEN0"); address TOKEN1 = _createNamedRejectionDummy("TOKEN1"); @@ -157,6 +285,8 @@ contract UniswapV3UnitTest is Utils, Test { } function setUp() public { + _etchNamedRejectionDummy("PERMIT2", address(PERMIT2)); + _etchNamedRejectionDummy("ALLOWANCE_HOLDER", address(ALLOWANCE_HOLDER)); uni = new UniswapV3Dummy(UNI_FACTORY); } @@ -252,7 +382,7 @@ contract UniswapV3UnitTest is Utils, Test { // permitTransferFrom(((address,uint256),uint256,uint256),(address,uint256),address,bytes) 30f28b7a // cannot use abi.encodeWithSelector due to the selector overload and ambiguity _mockExpectCall( - PERMIT2, + address(PERMIT2), bytes.concat( abi.encodeWithSelector( bytes4(0x30f28b7a), permitTransfer, transferDetails, address(this), uint256(0x100) @@ -284,12 +414,12 @@ contract UniswapV3UnitTest is Utils, Test { }); _mockExpectCall( - ALLOWANCE_HOLDER, + address(ALLOWANCE_HOLDER), abi.encodeCall(IAllowanceHolder.transferFrom, (TOKEN0, address(this), POOL, 1)), abi.encode(true) ); - vm.prank(ALLOWANCE_HOLDER); + vm.prank(address(ALLOWANCE_HOLDER)); address(uni) .call( abi.encodePacked( From 41e5a5bfbb5979e3fd4bb3a358079bad8a5fd70e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 16 Apr 2026 09:26:57 +0200 Subject: [PATCH 017/107] `forge fmt` --- test/unit/core/UniswapV3UnitTest.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/core/UniswapV3UnitTest.t.sol b/test/unit/core/UniswapV3UnitTest.t.sol index d7d86e3aa..a832c6f74 100644 --- a/test/unit/core/UniswapV3UnitTest.t.sol +++ b/test/unit/core/UniswapV3UnitTest.t.sol @@ -242,8 +242,8 @@ contract UniswapV3PoolDirtyForwardedBoolDummy { (,,,, bytes memory data) = abi.decode(msg.data[4:], (address, bool, int256, uint160, bytes)); data[0x88] = bytes1(uint8(2)); - (bool success, bytes memory returndata) = - msg.sender.call(abi.encodeWithSignature("uniswapV3SwapCallback(int256,int256,bytes)", int256(1), int256(1), data)); + (bool success, bytes memory returndata) = msg.sender + .call(abi.encodeWithSignature("uniswapV3SwapCallback(int256,int256,bytes)", int256(1), int256(1), data)); if (!success) { assembly ("memory-safe") { revert(add(0x20, returndata), mload(returndata)) From 600c2e835de6b269c7f8cb493465f0c86e414972 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 18 May 2026 15:32:34 +0200 Subject: [PATCH 018/107] Bug! `calls[i].target` may alias `calls[j].data`, resulting in malleability. Make 2 passes over `calls[]` to fix this. --- src/CrossChainReceiverFactory.sol | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index 1142d9e38..adbc9a9bf 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -811,8 +811,10 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte } calls := add(0x20, calls) + // Individual `calls[i]` may alias each other. To avoid malleability attacks, we mutate + // the sentinel `calls[i].target` first, then hash the whole array so that any + // `calls[i].data` aliasing results in an invalid hash. for { let i } xor(i, callsLengthBytes) { i := add(0x20, i) } { - let dst := add(i, scratch) let src := add(i, calls) // indirect `src` because it points to a dynamic type @@ -823,6 +825,20 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte err := or(lt(lastWord, add(0x60, src)), or(oom, err)) } + // replace `src.target` with `address(this)` if it is `_ADDRESS_THIS_SENTINEL` + let srcTarget := mload(src) + mstore(src, xor(srcTarget, mul(eq(_ADDRESS_THIS_SENTINEL, srcTarget), xor(address(), srcTarget)))) + } + + // now we can go through each of the `calls[i]`, hash each `calls[i].data`, hash each + // struct, and sum up `totalValue` + for { let i } xor(i, callsLengthBytes) { i := add(0x20, i) } { + let src := add(i, calls) + + // indirect `src` because it points to a dynamic type + src := add(calls, mload(src)) + // we already updated `err` appropriately for `src` indirection; skip doing it again + // indirect `src.data` because it also points to a dynamic type let srcData let srcDataWord @@ -843,18 +859,22 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte srcData := keccak256(add(0x20, srcData), srcDataLength) } + // if `src.target` is `address(this)`, temporarily replace it with + // `_ADDRESS_THIS_SENTINEL` for hashing + let srcTarget := mload(src) + mstore(src, xor(srcTarget, mul(eq(address(), srcTarget), xor(_ADDRESS_THIS_SENTINEL, srcTarget)))) + // EIP712-hash the `Call` object into the `Call[]` array at `scratch[i]` let typeHashWord := sub(src, 0x20) // not technically memory safe let typeHashWordValue := mload(typeHashWord) mstore(typeHashWord, _CALL_TYPEHASH) mstore(srcDataWord, srcData) - mstore(dst, keccak256(typeHashWord, 0xa0)) + mstore(add(i, scratch), keccak256(typeHashWord, 0xa0)) mstore(typeHashWord, typeHashWordValue) mstore(srcDataWord, srcDataWordValue) - // replace `src.target` with `address(this)` if it is `_ADDRESS_THIS_SENTINEL` - let srcTarget := mload(src) - mstore(src, xor(srcTarget, mul(eq(_ADDRESS_THIS_SENTINEL, srcTarget), xor(address(), srcTarget)))) + // restore `src.target` + mstore(src, srcTarget) // if this addition overflows, then the call will fail inside `MultiCall` because we // won't have enough value to send. depending on the value of `revertPolicy` this From b2ad52c788094699bc5d9f8abfbf6d0bfa082b17 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 19 May 2026 15:51:34 +0200 Subject: [PATCH 019/107] WIP: RobinHood chain --- api_secrets.json.template | 4 + chain_config.json | 35 ++++++++ src/chains/RobinHood/BridgeSettler.sol | 24 +++++ src/chains/RobinHood/Common.sol | 55 ++++++++++++ src/chains/RobinHood/Intent.sol | 111 ++++++++++++++++++++++++ src/chains/RobinHood/MetaTxn.sol | 68 +++++++++++++++ src/chains/RobinHood/TakerSubmitted.sol | 59 +++++++++++++ 7 files changed, 356 insertions(+) create mode 100644 src/chains/RobinHood/BridgeSettler.sol create mode 100644 src/chains/RobinHood/Common.sol create mode 100644 src/chains/RobinHood/Intent.sol create mode 100644 src/chains/RobinHood/MetaTxn.sol create mode 100644 src/chains/RobinHood/TakerSubmitted.sol diff --git a/api_secrets.json.template b/api_secrets.json.template index 0845e33ab..616f9f326 100644 --- a/api_secrets.json.template +++ b/api_secrets.json.template @@ -79,5 +79,9 @@ }, "tempo": { "rpcUrl": "" + }, + "robinhood": { + "blockscoutApi": "", + "rpcUrl": "" } } diff --git a/chain_config.json b/chain_config.json index ab6f47c0a..ca330f40d 100644 --- a/chain_config.json +++ b/chain_config.json @@ -769,5 +769,40 @@ "pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30" }, "sourcifyApi": "https://contracts.tempo.xyz/" + }, + "robinhood": { + "chainId": 4663, + "displayName": "RobinHood", + "hardfork": { + "shanghai": null, + "cancun": null, + "osaka": null, + "eraVm": false + }, + "extraFlags": "--legacy", + "extraScriptFlags": "--isolate --skip-simulation", + "gasMultiplierPercent": 1000, + "minGasPriceGwei": 1, + "wnative": null, + "safe": { + "toehold": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7", + "singleton": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA", + "factory": "0xC22834581EbC8527d974F8a1c97E1bEA4EF910BC", + "fallback": "0x017062a1dE2FE6b99BE3d9d37841FeD19F573804", + "multiCall": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "apiUrl": "NOT SUPPORTED" + }, + "governance": { + "upgradeSafe": null, + "deploymentSafe": null, + "pause": null, + "daoSafe": null + }, + "deployment": { + "deployer": null, + "allowanceHolder": null, + "forwardingMultiCall": null, + "crossChainFactory": null + } } } diff --git a/src/chains/RobinHood/BridgeSettler.sol b/src/chains/RobinHood/BridgeSettler.sol new file mode 100644 index 000000000..a7dac8edf --- /dev/null +++ b/src/chains/RobinHood/BridgeSettler.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.34; + +import {IBridgeSettlerActions} from "../../bridge/IBridgeSettlerActions.sol"; +import {BridgeSettler, BridgeSettlerBase} from "../../bridge/BridgeSettler.sol"; + +contract RobinHoodBridgeSettler is BridgeSettler, Across { + constructor(bytes20 gitCommit) BridgeSettlerBase(gitCommit) { + assert(true || block.chainid == 31337); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data) + internal + override(BridgeSettlerBase) + returns (bool) + { + if (super._dispatch(i, action, data)) { + return true; + } else { + return false; + } + return true; + } +} diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol new file mode 100644 index 000000000..5a4b6ead4 --- /dev/null +++ b/src/chains/RobinHood/Common.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.34; + +import {SettlerBase} from "../../SettlerBase.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {FreeMemory} from "../../utils/FreeMemory.sol"; + +import {ISettlerActions} from "../../ISettlerActions.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {revertUnknownForkId} from "../../core/SettlerErrors.sol"; + +// Solidity inheritance is stupid +import {SettlerSwapAbstract} from "../../SettlerAbstract.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; + +abstract contract RobinHoodMixin is FreeMemory, SettlerBase { + constructor() { + assert(true || block.chainid == 31337); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) + internal + virtual + override(SettlerSwapAbstract, SettlerBase) + DANGEROUS_freeMemory + returns (bool) + { + if (super._dispatch(i, action, data, slippage)) { + return true; + } else { + return false; + } + return true; + } + + function _uniV3ForkInfo(uint8 forkId) + internal + pure + override + returns (address factory, bytes32 initHash, uint32 callbackSelector) + { + revertUnknownForkId(forkId); + } + + // I hate Solidity inheritance + function _fallback(bytes calldata data) + internal + virtual + override(Permit2PaymentAbstract, UniswapV4) + returns (bool success, bytes memory returndata) + { + return super._fallback(data); + } +} diff --git a/src/chains/RobinHood/Intent.sol b/src/chains/RobinHood/Intent.sol new file mode 100644 index 000000000..61d268341 --- /dev/null +++ b/src/chains/RobinHood/Intent.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.34; + +import {RobinHoodSettlerMetaTxn} from "./MetaTxn.sol"; +import {SettlerIntent} from "../../SettlerIntent.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {ISettlerActions} from "../../ISettlerActions.sol"; + +// Solidity inheritance is stupid +import {SettlerAbstract} from "../../SettlerAbstract.sol"; +import {SettlerBase} from "../../SettlerBase.sol"; +import {SettlerMetaTxn} from "../../SettlerMetaTxn.sol"; +import {SettlerIntent} from "../../SettlerIntent.sol"; +import {AbstractContext, Context} from "../../Context.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {Permit2PaymentMetaTxn} from "../../core/Permit2Payment.sol"; + +/// @custom:security-contact security@0x.org +contract RobinHoodSettlerIntent is SettlerIntent, RobinHoodSettlerMetaTxn { + constructor(bytes20 gitCommit) RobinHoodSettlerMetaTxn(gitCommit) {} + + // Solidity inheritance is stupid + function executeMetaTxn( + AllowedSlippage memory slippage, + bytes[] calldata actions, + bytes32, /* zid & affiliate */ + address msgSender, + bytes calldata sig + ) public override(SettlerIntent, SettlerMetaTxn) returns (bool) { + return super.executeMetaTxn(slippage, actions, bytes32(0), msgSender, sig); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) + internal + override(RobinHoodSettlerMetaTxn, SettlerBase) + returns (bool) + { + return super._dispatch(i, action, data, slippage); + } + + function _isForwarded() internal view override(AbstractContext, Context, SettlerIntent) returns (bool) { + return super._isForwarded(); + } + + function _msgData() internal view override(AbstractContext, Context, SettlerIntent) returns (bytes calldata) { + return super._msgData(); + } + + function _msgSender() internal view override(SettlerIntent, RobinHoodSettlerMetaTxn) returns (address) { + return super._msgSender(); + } + + function _witnessTypeSuffix() internal pure override(SettlerIntent, Permit2PaymentMetaTxn) returns (string memory) { + return super._witnessTypeSuffix(); + } + + function _mandatorySlippageCheck() internal pure override(SettlerBase, SettlerIntent) returns (bool) { + return super._mandatorySlippageCheck(); + } + + function _tokenId() internal pure override(SettlerIntent, SettlerMetaTxn, SettlerAbstract) returns (uint256) { + return super._tokenId(); + } + + function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig) + internal + override(RobinHoodSettlerMetaTxn, SettlerMetaTxn) + returns (bool) + { + return super._dispatchVIP(action, data, sig); + } + + function _permitToSellAmountCalldata(ISignatureTransfer.PermitTransferFrom calldata permit) + internal + view + override(SettlerIntent, Permit2PaymentAbstract, Permit2PaymentMetaTxn) + returns (uint256) + { + return super._permitToSellAmountCalldata(permit); + } + + function _permitToSellAmount(ISignatureTransfer.PermitTransferFrom memory permit) + internal + view + override(SettlerIntent, Permit2PaymentAbstract, Permit2PaymentMetaTxn) + returns (uint256) + { + return super._permitToSellAmount(permit); + } + + function _isRestrictedTarget(address target) + internal + view + virtual + override(RobinHoodSettlerMetaTxn, SettlerIntent) + returns (bool) + { + return super._isRestrictedTarget(target); + } + + function _fallback(bytes calldata data) + internal + virtual + override(Permit2PaymentAbstract, RobinHoodSettlerMetaTxn) + returns (bool, bytes memory) + { + return super._fallback(data); + } +} diff --git a/src/chains/RobinHood/MetaTxn.sol b/src/chains/RobinHood/MetaTxn.sol new file mode 100644 index 000000000..819c9d9ff --- /dev/null +++ b/src/chains/RobinHood/MetaTxn.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.34; + +import {RobinHoodMixin} from "./Common.sol"; +import {SettlerMetaTxn} from "../../SettlerMetaTxn.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {ISettlerActions} from "../../ISettlerActions.sol"; + +// Solidity inheritance is stupid +import {SettlerBase} from "../../SettlerBase.sol"; +import {AbstractContext} from "../../Context.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {Permit2PaymentBase} from "../../core/Permit2Payment.sol"; + +/// @custom:security-contact security@0x.org +contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} + + function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig) + internal + virtual + override + DANGEROUS_freeMemory + returns (bool) + { + if (super._dispatchVIP(action, data, sig)) { + return true; + } else { + return false; + } + return true; + } + + // Solidity inheritance is stupid + function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) + internal + virtual + override(SettlerBase, RobinHoodMixin) + returns (bool) + { + return super._dispatch(i, action, data, slippage); + } + + function _msgSender() internal view virtual override(SettlerMetaTxn, AbstractContext) returns (address) { + return super._msgSender(); + } + + function _isRestrictedTarget(address target) + internal + view + virtual + override(SettlerMetaTxn, Permit2PaymentAbstract) + returns (bool) + { + return super._isRestrictedTarget(target); + } + + function _fallback(bytes calldata data) + internal + virtual + override(Permit2PaymentAbstract, RobinHoodMixin) + returns (bool, bytes memory) + { + return super._fallback(data); + } +} diff --git a/src/chains/RobinHood/TakerSubmitted.sol b/src/chains/RobinHood/TakerSubmitted.sol new file mode 100644 index 000000000..1f8a67578 --- /dev/null +++ b/src/chains/RobinHood/TakerSubmitted.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.34; + +import {RobinHoodMixin} from "./Common.sol"; +import {Settler} from "../../Settler.sol"; + +import {IERC20} from "@forge-std/interfaces/IERC20.sol"; +import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {ISettlerActions} from "../../ISettlerActions.sol"; + +// Solidity inheritance is stupid +import {SettlerBase} from "../../SettlerBase.sol"; +import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; +import {AbstractContext} from "../../Context.sol"; + +/// @custom:security-contact security@0x.org +contract RobinHoodSettler is Settler, RobinHoodMixin { + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} + + function _dispatchVIP(uint256 action, bytes calldata data) internal override DANGEROUS_freeMemory returns (bool) { + if (super._dispatchVIP(action, data)) { + return true; + } else { + return false; + } + return true; + } + + // Solidity inheritance is stupid + function _isRestrictedTarget(address target) + internal + view + override(Settler, Permit2PaymentAbstract) + returns (bool) + { + return super._isRestrictedTarget(target); + } + + function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) + internal + override(Settler, RobinHoodMixin) + returns (bool) + { + return super._dispatch(i, action, data, slippage); + } + + function _msgSender() internal view override(Settler, AbstractContext) returns (address) { + return super._msgSender(); + } + + function _fallback(bytes calldata data) + internal + virtual + override(Permit2PaymentAbstract, RobinHoodMixin) + returns (bool, bytes memory) + { + return super._fallback(data); + } +} From 1a4609c46a8ca805c56a1988dab9dc1c661c5d2e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 19 May 2026 15:52:18 +0200 Subject: [PATCH 020/107] WIP: RobinHood chain --- CHANGELOG.md | 4 +++- README.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05043cbd4..3f051b3c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,14 @@ * `BRIDGE_TO_LAYER_ZERO_OFT` modified to remove the `nativeFee` argument that is already included in `sendData` * `BRIDGE_ERC20_TO_MAYAN` and `BRIDGE_NATIVE_TO_MAYAN` modified to remove `forwarder` argument. It is now hardcoded. * Remove `BRIDGE_ERC20_TO_STARGATE_V2` and `BRIDGE_NATIVE_TO_STARGATE_V2` in favor of a unified - `BRIDGE_TO_STARGATE_V2`. + `BRIDGE_TO_STARGATE_V2`. * `nativeFee` is taken from `sendData` * `token` is used to differentiate between ERC20 and Native flows ### Non-breaking changes +* Deploy Settler to RobinHood chain + ## 2026-04-10 ### Breaking changes diff --git a/README.md b/README.md index a28d2a818..87c1f1ac4 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ your integration. * `0x0000000000001fF3684f28c67538d4D072C22734` on chains supporting the Cancun hardfork (Ethereum mainnet, Ethereum Sepolia testnet, Polygon, Base, Optimism, Arbitrum, Bnb, World Chain, Fantom Sonic, Ink, Avalanche, Unichain, Berachain, - Scroll, HyperEvm, Plasma, Monad mainnet, Abstract, Linea, Tempo) + Scroll, HyperEvm, Plasma, Monad mainnet, Abstract, Linea, Tempo, RobinHood) * `0x0000000000005E88410CcDFaDe4a5EfaE4b49562` on chains supporting the Shanghai hardfork (Mantle) From 34b4cd69a65b2c8c845fa586a9e1dd466d1f7242 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 19 May 2026 16:43:46 +0200 Subject: [PATCH 021/107] WIP: RobinHood chain -- add WETH address --- chain_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain_config.json b/chain_config.json index ca330f40d..8d8263390 100644 --- a/chain_config.json +++ b/chain_config.json @@ -783,7 +783,7 @@ "extraScriptFlags": "--isolate --skip-simulation", "gasMultiplierPercent": 1000, "minGasPriceGwei": 1, - "wnative": null, + "wnative": "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73", "safe": { "toehold": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7", "singleton": "0xfb1bffC9d739B8D520DaF37dF666da4C687191EA", From f43837c6d74f179673e04b696797e399a25cdcfe Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 21 May 2026 18:02:34 +0200 Subject: [PATCH 022/107] WIP: RobinHood chain -- add to SafeConfig.sol --- script/SafeConfig.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script/SafeConfig.sol b/script/SafeConfig.sol index 186dae267..ba3af18ef 100644 --- a/script/SafeConfig.sol +++ b/script/SafeConfig.sol @@ -22,6 +22,7 @@ library SafeConfig { || block.chainid == 999 // hyperevm || block.chainid == 2741 // abstract || block.chainid == 4217 // tempo + || block.chainid == 4663 // robinhood || block.chainid == 5000 // mantle || block.chainid == 8453 // base || block.chainid == 9745 // plasma @@ -52,6 +53,7 @@ library SafeConfig { || block.chainid == 999 // hyperevm || block.chainid == 2741 // abstract || block.chainid == 4217 // tempo + || block.chainid == 4663 // robinhood || block.chainid == 5000 // mantle || block.chainid == 8453 // base || block.chainid == 9745 // plasma @@ -85,6 +87,7 @@ library SafeConfig { || block.chainid == 480 // worldchain || block.chainid == 999 // hyperevm || block.chainid == 4217 // tempo + || block.chainid == 4663 // robinhood || block.chainid == 5000 // mantle || block.chainid == 8453 // base || block.chainid == 9745 // plasma From d3c03220b7ed0492040d7d2684d13edf157c1d12 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 21 May 2026 21:18:04 +0200 Subject: [PATCH 023/107] WIP: RobinHood chain -- test for hardfork support --- chain_config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chain_config.json b/chain_config.json index 8d8263390..5186c9bc1 100644 --- a/chain_config.json +++ b/chain_config.json @@ -774,9 +774,9 @@ "chainId": 4663, "displayName": "RobinHood", "hardfork": { - "shanghai": null, - "cancun": null, - "osaka": null, + "shanghai": true, + "cancun": true, + "osaka": true, "eraVm": false }, "extraFlags": "--legacy", From b1f8687bdb61f0ee91c4a6370a4e48cf6d5d481f Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 26 May 2026 17:39:07 +0200 Subject: [PATCH 024/107] WIP: RobinHood chain -- deploy MultiCall and CrossChainReceiverFactory --- chain_config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain_config.json b/chain_config.json index 5186c9bc1..fec71561f 100644 --- a/chain_config.json +++ b/chain_config.json @@ -801,8 +801,8 @@ "deployment": { "deployer": null, "allowanceHolder": null, - "forwardingMultiCall": null, - "crossChainFactory": null + "forwardingMultiCall": "0x00000000000000CF9E3c5A26621af382fA17f24f", + "crossChainFactory": "0x00000000000000304861c3aDfb80dd5ebeC96325" } } } From 3cac7fb8ced99637d526fcfb7e62569a53562bce Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 27 May 2026 09:58:09 +0200 Subject: [PATCH 025/107] WIP: RobinHood chain -- deploy AllowanceHolder --- chain_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain_config.json b/chain_config.json index fec71561f..fb8482a24 100644 --- a/chain_config.json +++ b/chain_config.json @@ -800,7 +800,7 @@ }, "deployment": { "deployer": null, - "allowanceHolder": null, + "allowanceHolder": "0x0000000000001fF3684f28c67538d4D072C22734", "forwardingMultiCall": "0x00000000000000CF9E3c5A26621af382fA17f24f", "crossChainFactory": "0x00000000000000304861c3aDfb80dd5ebeC96325" } From b0de7d2b817a9ac248b7a56590d9384dd55b2e36 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 27 May 2026 15:38:11 +0200 Subject: [PATCH 026/107] WIP: RobinHood chain -- compilation errors --- src/chains/RobinHood/BridgeSettler.sol | 2 +- src/chains/RobinHood/Common.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chains/RobinHood/BridgeSettler.sol b/src/chains/RobinHood/BridgeSettler.sol index a7dac8edf..927072683 100644 --- a/src/chains/RobinHood/BridgeSettler.sol +++ b/src/chains/RobinHood/BridgeSettler.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.34; import {IBridgeSettlerActions} from "../../bridge/IBridgeSettlerActions.sol"; import {BridgeSettler, BridgeSettlerBase} from "../../bridge/BridgeSettler.sol"; -contract RobinHoodBridgeSettler is BridgeSettler, Across { +contract RobinHoodBridgeSettler is BridgeSettler { constructor(bytes20 gitCommit) BridgeSettlerBase(gitCommit) { assert(true || block.chainid == 31337); } diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index 5a4b6ead4..d2b443796 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -22,7 +22,7 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase { function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) internal virtual - override(SettlerSwapAbstract, SettlerBase) + override(/* SettlerSwapAbstract, */ SettlerBase) DANGEROUS_freeMemory returns (bool) { @@ -47,7 +47,7 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase { function _fallback(bytes calldata data) internal virtual - override(Permit2PaymentAbstract, UniswapV4) + override(Permit2PaymentAbstract) returns (bool success, bytes memory returndata) { return super._fallback(data); From 84349ec259622cf253e5cd1bdd5128e3ba7ba079 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 27 May 2026 16:07:47 +0200 Subject: [PATCH 027/107] Finished: deploy Settler to RobinHood chain --- chain_config.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/chain_config.json b/chain_config.json index fb8482a24..768015c3d 100644 --- a/chain_config.json +++ b/chain_config.json @@ -793,13 +793,13 @@ "apiUrl": "NOT SUPPORTED" }, "governance": { - "upgradeSafe": null, - "deploymentSafe": null, - "pause": null, - "daoSafe": null + "upgradeSafe": "0xf36b9f50E59870A24F42F9Ba43b2aD0A4b8f2F51", + "deploymentSafe": "0x8E5DE7118a596E99B0563D3022039c11927f4827", + "pause": "0x1CeC01DC0fFEE5eB5aF47DbEc1809F2A7c601C30", + "daoSafe": "0x97A8620F5c88Cb4A1d9C2E18b0d3CA1eEF59d471" }, "deployment": { - "deployer": null, + "deployer": "0x00000000000004533Fe15556B1E086BB1A72cEae", "allowanceHolder": "0x0000000000001fF3684f28c67538d4D072C22734", "forwardingMultiCall": "0x00000000000000CF9E3c5A26621af382fA17f24f", "crossChainFactory": "0x00000000000000304861c3aDfb80dd5ebeC96325" From 73774785d40c4502ba4db8cb903aba526a23da5c Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 5 Jun 2026 09:45:20 +0200 Subject: [PATCH 028/107] Add STS URL for RobinHood Chain --- chain_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain_config.json b/chain_config.json index 768015c3d..4263b9731 100644 --- a/chain_config.json +++ b/chain_config.json @@ -790,7 +790,7 @@ "factory": "0xC22834581EbC8527d974F8a1c97E1bEA4EF910BC", "fallback": "0x017062a1dE2FE6b99BE3d9d37841FeD19F573804", "multiCall": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", - "apiUrl": "NOT SUPPORTED" + "apiUrl": "https://api.safe.global/tx-service/aeth/api" }, "governance": { "upgradeSafe": "0xf36b9f50E59870A24F42F9Ba43b2aD0A4b8f2F51", From 492c9c79278692d31738549bc1c343c1e5e262b8 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 5 Jun 2026 09:46:16 +0200 Subject: [PATCH 029/107] Put chainid back in initcode for RobinHood Chain --- src/chains/RobinHood/BridgeSettler.sol | 2 +- src/chains/RobinHood/Common.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chains/RobinHood/BridgeSettler.sol b/src/chains/RobinHood/BridgeSettler.sol index 927072683..3cf83e502 100644 --- a/src/chains/RobinHood/BridgeSettler.sol +++ b/src/chains/RobinHood/BridgeSettler.sol @@ -6,7 +6,7 @@ import {BridgeSettler, BridgeSettlerBase} from "../../bridge/BridgeSettler.sol"; contract RobinHoodBridgeSettler is BridgeSettler { constructor(bytes20 gitCommit) BridgeSettlerBase(gitCommit) { - assert(true || block.chainid == 31337); + assert(block.chainid == 4663 || block.chainid == 31337); } function _dispatch(uint256 i, uint256 action, bytes calldata data) diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index d2b443796..b0bd0019f 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -16,7 +16,7 @@ import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; abstract contract RobinHoodMixin is FreeMemory, SettlerBase { constructor() { - assert(true || block.chainid == 31337); + assert(block.chainid == 4663 || block.chainid == 31337); } function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) From 8da090ed80e319f9c349e1aac42d83aa1f60fe91 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 8 Jun 2026 14:48:20 +0200 Subject: [PATCH 030/107] Add UniswapV3 and UniswapV4 support on RobinHood chain --- src/chains/RobinHood/Common.sol | 41 ++++++++++++++++++++++--- src/chains/RobinHood/MetaTxn.sol | 14 +++++++++ src/chains/RobinHood/TakerSubmitted.sol | 15 +++++++++ src/core/UniswapV4Addresses.sol | 1 + src/core/univ3forks/UniswapV3.sol | 1 + 5 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index b0bd0019f..af0b8ade1 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -5,16 +5,26 @@ import {SettlerBase} from "../../SettlerBase.sol"; import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {FreeMemory} from "../../utils/FreeMemory.sol"; +import {UniswapV4} from "../../core/UniswapV4.sol"; +import {IPoolManager} from "../../core/UniswapV4Types.sol"; import {ISettlerActions} from "../../ISettlerActions.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; import {revertUnknownForkId} from "../../core/SettlerErrors.sol"; +import { + uniswapV3RobinhoodFactory, + uniswapV3InitHash, + uniswapV3ForkId, + IUniswapV3Callback +} from "../../core/univ3forks/UniswapV3.sol"; +import {ROBINHOOD_POOL_MANAGER} from "../../core/UniswapV4Addresses.sol"; + // Solidity inheritance is stupid import {SettlerSwapAbstract} from "../../SettlerAbstract.sol"; import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; -abstract contract RobinHoodMixin is FreeMemory, SettlerBase { +abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4 { constructor() { assert(block.chainid == 4663 || block.chainid == 31337); } @@ -22,12 +32,25 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase { function _dispatch(uint256 i, uint256 action, bytes calldata data, AllowedSlippage memory slippage) internal virtual - override(/* SettlerSwapAbstract, */ SettlerBase) + override(SettlerSwapAbstract, SettlerBase) DANGEROUS_freeMemory returns (bool) { if (super._dispatch(i, action, data, slippage)) { return true; + } else if (action == uint32(ISettlerActions.UNISWAPV4.selector)) { + ( + address recipient, + IERC20 sellToken, + uint256 bps, + bool feeOnTransfer, + uint256 hashMul, + uint256 hashMod, + bytes memory fills, + uint256 amountOutMin + ) = abi.decode(data, (address, IERC20, uint256, bool, uint256, uint256, bytes, uint256)); + + sellToUniswapV4(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); } else { return false; } @@ -40,14 +63,24 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase { override returns (address factory, bytes32 initHash, uint32 callbackSelector) { - revertUnknownForkId(forkId); + if (forkId == uniswapV3ForkId) { + factory = uniswapV3RobinhoodFactory; + initHash = uniswapV3InitHash; + callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); + } else { + revertUnknownForkId(forkId); + } + } + + function _POOL_MANAGER() internal pure override returns (IPoolManager) { + return ROBINHOOD_POOL_MANAGER; } // I hate Solidity inheritance function _fallback(bytes calldata data) internal virtual - override(Permit2PaymentAbstract) + override(Permit2PaymentAbstract, UniswapV4) returns (bool success, bytes memory returndata) { return super._fallback(data); diff --git a/src/chains/RobinHood/MetaTxn.sol b/src/chains/RobinHood/MetaTxn.sol index 819c9d9ff..ef5c56e58 100644 --- a/src/chains/RobinHood/MetaTxn.sol +++ b/src/chains/RobinHood/MetaTxn.sol @@ -27,6 +27,20 @@ contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { { if (super._dispatchVIP(action, data, sig)) { return true; + } else if (action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) { + ( + address recipient, + ISignatureTransfer.PermitTransferFrom memory permit, + bool feeOnTransfer, + uint256 hashMul, + uint256 hashMod, + bytes memory fills, + uint256 amountOutMin + ) = abi.decode( + data, (address, ISignatureTransfer.PermitTransferFrom, bool, uint256, uint256, bytes, uint256) + ); + + sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); } else { return false; } diff --git a/src/chains/RobinHood/TakerSubmitted.sol b/src/chains/RobinHood/TakerSubmitted.sol index 1f8a67578..96e036aeb 100644 --- a/src/chains/RobinHood/TakerSubmitted.sol +++ b/src/chains/RobinHood/TakerSubmitted.sol @@ -20,6 +20,21 @@ contract RobinHoodSettler is Settler, RobinHoodMixin { function _dispatchVIP(uint256 action, bytes calldata data) internal override DANGEROUS_freeMemory returns (bool) { if (super._dispatchVIP(action, data)) { return true; + } else if (action == uint32(ISettlerActions.UNISWAPV4_VIP.selector)) { + ( + address recipient, + ISignatureTransfer.PermitTransferFrom memory permit, + bool feeOnTransfer, + uint256 hashMul, + uint256 hashMod, + bytes memory fills, + bytes memory sig, + uint256 amountOutMin + ) = abi.decode( + data, (address, ISignatureTransfer.PermitTransferFrom, bool, uint256, uint256, bytes, bytes, uint256) + ); + + sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); } else { return false; } diff --git a/src/core/UniswapV4Addresses.sol b/src/core/UniswapV4Addresses.sol index 80629c8a6..212098f22 100644 --- a/src/core/UniswapV4Addresses.sol +++ b/src/core/UniswapV4Addresses.sol @@ -16,3 +16,4 @@ IPoolManager constant UNICHAIN_POOL_MANAGER = IPoolManager(0x1F98400000000000000 IPoolManager constant SEPOLIA_POOL_MANAGER = IPoolManager(0xE03A1074c86CFeDd5C142C4F04F1a1536e203543); IPoolManager constant MONAD_POOL_MANAGER = IPoolManager(0x188d586Ddcf52439676Ca21A244753fA19F9Ea8e); IPoolManager constant TEMPO_POOL_MANAGER = IPoolManager(0x33620f62C5b9B2086dD6b62F4A297A9f30347029); +IPoolManager constant ROBINHOOD_POOL_MANAGER = IPoolManager(0x8366a39CC670B4001A1121B8F6A443A643e40951); diff --git a/src/core/univ3forks/UniswapV3.sol b/src/core/univ3forks/UniswapV3.sol index ba2f67a97..a0be22321 100644 --- a/src/core/univ3forks/UniswapV3.sol +++ b/src/core/univ3forks/UniswapV3.sol @@ -17,6 +17,7 @@ address constant uniswapV3PlasmaFactory = 0xcb2436774C3e191c85056d248EF4260ce5f2 address constant uniswapV3MonadFactory = 0x204FAca1764B154221e35c0d20aBb3c525710498; address constant uniswapV3AbstractFactory = 0xA1160e73B63F322ae88cC2d8E700833e71D0b2a1; address constant uniswapV3TempoFactory = 0x24a3d4757E330890A8b8978028c9e58E04611fd6; +address constant uniswapV3RobinhoodFactory = 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA; bytes32 constant uniswapV3InitHash = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; // This isn't a "hash" inasmuch as it's a versioned discriminator From db2420d8c0fa6ad0eb2baefab2540ab58e2258d1 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 8 Jun 2026 14:49:53 +0200 Subject: [PATCH 031/107] `CHANGELOG.md` --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7a7f3c52..dbe9b5549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ ### Non-breaking changes +* Add UniswapV3 UniV3 fork on RobinHood chain +* Add UniswapV4 actions to RobinHood chain + ## 2026-06-03 ### Breaking changes From d08627c4859a97a3aa04f8682ec1c2d54eee445f Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 12 Jun 2026 12:55:00 +0200 Subject: [PATCH 032/107] Resolve Uniswap V3 unit test conflict Co-Authored-By: Codex --- test/unit/core/UniswapV3UnitTest.t.sol | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/test/unit/core/UniswapV3UnitTest.t.sol b/test/unit/core/UniswapV3UnitTest.t.sol index a832c6f74..712d8c80b 100644 --- a/test/unit/core/UniswapV3UnitTest.t.sol +++ b/test/unit/core/UniswapV3UnitTest.t.sol @@ -17,9 +17,9 @@ import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {Test} from "@forge-std/Test.sol"; -ISignatureTransfer constant PERMIT2 = ISignatureTransfer(0x000000000022D473030F116dDEE9F6B43aC78BA3); - contract UniswapV3Dummy is AllowanceHolderContext, UniswapV3Fork { + address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; + address internal immutable uniFactory; address private _payer; address private _callbackCaller; @@ -34,7 +34,7 @@ contract UniswapV3Dummy is AllowanceHolderContext, UniswapV3Fork { } fallback(bytes calldata) external returns (bytes memory) { - require(_operator() == _callbackCaller); + require(msg.sender == _callbackCaller); bytes calldata data = _msgData(); require(uint32(bytes4(data)) == uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector)); function(bytes calldata) internal returns (bytes memory) callback = _callback; @@ -65,12 +65,13 @@ contract UniswapV3Dummy is AllowanceHolderContext, UniswapV3Fork { return false; } - function _msgSender() internal view override(AbstractContext, AllowanceHolderContext) returns (address payer) { - require((payer = _payer) != address(0)); + function _msgSender() internal view override(AbstractContext, AllowanceHolderContext) returns (address) { + address payer = _payer; + return payer == address(0) ? AllowanceHolderContext._msgSender() : payer; } function _operator() internal view override returns (address) { - return super._msgSender(); + return _msgSender(); } function _dispatch(uint256, uint256, bytes calldata, AllowedSlippage memory) internal pure override returns (bool) { @@ -165,7 +166,13 @@ contract UniswapV3Dummy is AllowanceHolderContext, UniswapV3Fork { permit.permitted.token, _msgSender(), transferDetails.to, transferDetails.requestedAmount ); } else { - PERMIT2.permitTransferFrom(permit, transferDetails, _msgSender(), sig); + (bool success, bytes memory returndata) = + _PERMIT2.call(abi.encodeWithSelector(bytes4(0x30f28b7a), permit, transferDetails, _msgSender(), sig)); + if (!success) { + assembly ("memory-safe") { + revert(add(0x20, returndata), mload(returndata)) + } + } } } @@ -255,6 +262,7 @@ contract UniswapV3PoolDirtyForwardedBoolDummy { contract UniswapV3UnitTest is Utils, Test { UniswapV3Dummy uni; + address constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; address UNI_FACTORY = _createNamedRejectionDummy("UNI_FACTORY"); address TOKEN0 = _createNamedRejectionDummy("TOKEN0"); @@ -285,7 +293,7 @@ contract UniswapV3UnitTest is Utils, Test { } function setUp() public { - _etchNamedRejectionDummy("PERMIT2", address(PERMIT2)); + _etchNamedRejectionDummy("PERMIT2", PERMIT2); _etchNamedRejectionDummy("ALLOWANCE_HOLDER", address(ALLOWANCE_HOLDER)); uni = new UniswapV3Dummy(UNI_FACTORY); } From fd8aab3f2098a481d03277a3dec0d644ec6e2a6e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 12 Jun 2026 13:22:55 +0200 Subject: [PATCH 033/107] Use iszero masks for ternary swaps Co-Authored-By: Codex --- src/core/PancakeInfinity.sol | 73 +++++++++++++++++++----------------- src/utils/Ternary.sol | 24 ++++++------ 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/core/PancakeInfinity.sol b/src/core/PancakeInfinity.sol index 2b310be18..f1fa4c9fd 100644 --- a/src/core/PancakeInfinity.sol +++ b/src/core/PancakeInfinity.sol @@ -354,6 +354,22 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { return lockAcquired(data); } + function _pancakeInfinitySettleDelta(State state, BalanceDelta delta, bool zeroForOne) private pure { + (int256 settledSellAmount, int256 settledBuyAmount) = zeroForOne.maybeSwap(delta.amount1(), delta.amount0()); + // Some insane hooks may increase the sell amount, cause the sell amount to be + // credit, or cause the buy amount to be debt. We need to handle all these cases by + // reverting. + + NotePtr sell = state.sell(); + sell.setAmount(sell.amount() - settledSellAmount.asDebt(sell)); + // Since `settledBuyAmount` came from an `int128`, this addition cannot overflow a + // `uint256`. We still need to make sure it doesn't record a debt, though. + unchecked { + NotePtr buy = state.buy(); + buy.setAmount(buy.amount() + settledBuyAmount.asCredit(buy)); + } + } + // the mandatory fields are // 2 - sell bps // 20 - sqrtPriceLimitX96 @@ -458,15 +474,15 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { poolKey.hooks = hooks; } - uint8 poolManagerId; - assembly ("memory-safe") { - poolManagerId := shr(0xf8, calldataload(data.offset)) - data.offset := add(0x01, data.offset) - data.length := sub(data.length, 0x01) - // we don't check for array out-of-bounds here; we will check it later in `Decoder.overflowCheck` - } - { + uint8 poolManagerId; + assembly ("memory-safe") { + poolManagerId := shr(0xf8, calldataload(data.offset)) + data.offset := add(0x01, data.offset) + data.length := sub(data.length, 0x01) + // we don't check for array out-of-bounds here; we will check it later in `Decoder.overflowCheck` + } + uint24 fee; assembly ("memory-safe") { fee := shr(0xe8, calldataload(data.offset)) @@ -475,9 +491,7 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { // we don't check for array out-of-bounds here; we will check it later in `Decoder.overflowCheck` } poolKey.fee = fee; - } - { bytes32 parameters; assembly ("memory-safe") { parameters := calldataload(data.offset) @@ -486,27 +500,32 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { // we don't check for array out-of-bounds here; we will check it later in `Decoder.overflowCheck` } poolKey.parameters = parameters; - } - bytes calldata hookData; - (data, hookData) = Decoder.decodeBytes(data); + bytes calldata hookData; + (data, hookData) = Decoder.decodeBytes(data); - Decoder.overflowCheck(data); + Decoder.overflowCheck(data); - { - BalanceDelta delta; if (uint256(poolManagerId) == 0) { poolKey.poolManager = CL_MANAGER; - delta = IPancakeInfinityCLPoolManager(address(poolKey.poolManager)) - .unsafeSwap(poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData); + _pancakeInfinitySettleDelta( + state, + IPancakeInfinityCLPoolManager(address(poolKey.poolManager)) + .unsafeSwap(poolKey, zeroForOne, amountSpecified, sqrtPriceLimitX96, hookData), + zeroForOne + ); } else if (uint256(poolManagerId) == 1) { poolKey.poolManager = BIN_MANAGER; if (amountSpecified >> 127 != amountSpecified >> 128) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } - delta = IPancakeInfinityBinPoolManager(address(poolKey.poolManager)) - .unsafeSwap(poolKey, zeroForOne, int128(amountSpecified), hookData); + _pancakeInfinitySettleDelta( + state, + IPancakeInfinityBinPoolManager(address(poolKey.poolManager)) + .unsafeSwap(poolKey, zeroForOne, int128(amountSpecified), hookData), + zeroForOne + ); } else { assembly ("memory-safe") { mstore(0x00, 0x0a9a7da6) // selector for `UnknownPoolManagerId(uint8)` @@ -514,20 +533,6 @@ abstract contract PancakeInfinity is SettlerSwapAbstract { revert(0x1c, 0x24) } } - (int256 settledSellAmount, int256 settledBuyAmount) = - zeroForOne.maybeSwap(delta.amount1(), delta.amount0()); - // Some insane hooks may increase the sell amount, cause the sell amount to be - // credit, or cause the buy amount to be debt. We need to handle all these cases by - // reverting. - - NotePtr sell = state.sell(); - sell.setAmount(sell.amount() - settledSellAmount.asDebt(sell)); - // Since `settledBuyAmount` came from an `int128`, this addition cannot overflow a - // `uint256`. We still need to make sure it doesn't record a debt, though. - unchecked { - NotePtr buy = state.buy(); - buy.setAmount(buy.amount() + settledBuyAmount.asCredit(buy)); - } } } diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index e31e07eb7..ebfaa0ebc 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -40,33 +40,33 @@ library Ternary { function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { - let t := mul(lt(0x00, c), sub(y, x)) - a := add(x, t) - b := sub(y, t) + let t := mul(iszero(c), sub(y, x)) + a := sub(y, t) + b := add(x, t) } } function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { - let t := mul(lt(0x00, c), sub(y, x)) - a := add(x, t) - b := sub(y, t) + let t := mul(iszero(c), sub(y, x)) + a := sub(y, t) + b := add(x, t) } } function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { - let t := mul(lt(0x00, c), sub(y, x)) - a := add(x, t) - b := sub(y, t) + let t := mul(iszero(c), sub(y, x)) + a := sub(y, t) + b := add(x, t) } } function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { - let t := mul(lt(0x00, c), sub(y, x)) - a := add(x, t) - b := sub(y, t) + let t := mul(iszero(c), sub(y, x)) + a := sub(y, t) + b := add(x, t) } } } From b153a5a111b548cbe3c9b35346d262ac30190df7 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 12 Jun 2026 13:29:23 +0200 Subject: [PATCH 034/107] Clean up slop --- src/utils/Ternary.sol | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/utils/Ternary.sol b/src/utils/Ternary.sol index ebfaa0ebc..a55cf8d10 100644 --- a/src/utils/Ternary.sol +++ b/src/utils/Ternary.sol @@ -40,33 +40,33 @@ library Ternary { function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) { assembly ("memory-safe") { - let t := mul(iszero(c), sub(y, x)) - a := sub(y, t) - b := add(x, t) + let t := mul(iszero(c), xor(y, x)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, int256 x, int256 y) internal pure returns (int256 a, int256 b) { assembly ("memory-safe") { - let t := mul(iszero(c), sub(y, x)) - a := sub(y, t) - b := add(x, t) + let t := mul(iszero(c), xor(y, x)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, IERC20 x, IERC20 y) internal pure returns (IERC20 a, IERC20 b) { assembly ("memory-safe") { - let t := mul(iszero(c), sub(y, x)) - a := sub(y, t) - b := add(x, t) + let t := mul(iszero(c), xor(y, x)) + a := xor(y, t) + b := xor(x, t) } } function maybeSwap(bool c, address x, address y) internal pure returns (address a, address b) { assembly ("memory-safe") { - let t := mul(iszero(c), sub(y, x)) - a := sub(y, t) - b := add(x, t) + let t := mul(iszero(c), xor(y, x)) + a := xor(y, t) + b := xor(x, t) } } } From ec9976049ad035d6e23de17e4eea4dfbb0a3af8e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 15:29:27 +0200 Subject: [PATCH 035/107] Clean up useless/failing tests --- test/0.8.25/BoolBoundary.t.sol | 40 +--------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index fcbc96b3a..74e5a6515 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -11,7 +11,7 @@ import {UnsafeMath, Math} from "src/utils/UnsafeMath.sol"; import {FastPermit} from "src/utils/SafePermit.sol"; import {IDAIStylePermit} from "src/interfaces/IERC2612.sol"; -import {IEVC, FastEvc, IEulerSwap, FastEulerSwap} from "src/core/EulerSwap.sol"; +import {IEulerSwap, FastEulerSwap} from "src/core/EulerSwap.sol"; import {IUniV2Pair, fastUniswapV2Pool} from "src/core/UniswapV2.sol"; import {IHanjiPool, FastHanjiPool} from "src/core/Hanji.sol"; import {IMaverickV2Pool, FastMaverickV2Pool} from "src/core/MaverickV2.sol"; @@ -36,18 +36,6 @@ contract MockDaiPermitToken { } } -contract MockEvcBool { - bytes internal response; - - function setResponse(bytes memory newResponse) external { - response = newResponse; - } - - fallback(bytes calldata) external returns (bytes memory) { - return response; - } -} - contract MockUniswapV2Pair is IUniV2Pair { uint112 internal reserve0; uint112 internal reserve1; @@ -210,10 +198,6 @@ contract MockPancakeBinManager { } contract BoolBoundaryHarness { - function fastIsAuthorized(IEVC evc) external view returns (bool) { - return FastEvc.fastIsAccountOperatorAuthorized(evc, address(0x11), address(0x22)); - } - function fastDaiPermit(IDAIStylePermit token) external returns (bool success) { bool allowed; assembly ("memory-safe") { @@ -390,28 +374,6 @@ contract BoolBoundaryTest is Test { assertTrue(token.lastAllowed()); } - function testFastEvcAcceptsCanonicalBool() public { - MockEvcBool evc = new MockEvcBool(); - - evc.setResponse(abi.encode(true)); - assertTrue(harness.fastIsAuthorized(IEVC(address(evc)))); - - evc.setResponse(abi.encode(false)); - assertFalse(harness.fastIsAuthorized(IEVC(address(evc)))); - } - - function testFastEvcRejectsShortOrDirtyBool() public { - MockEvcBool evc = new MockEvcBool(); - - evc.setResponse(new bytes(31)); - vm.expectRevert(bytes("")); - harness.fastIsAuthorized(IEVC(address(evc))); - - evc.setResponse(abi.encode(uint256(2))); - vm.expectRevert(bytes("")); - harness.fastIsAuthorized(IEVC(address(evc))); - } - function testUniswapV2BoundaryUsesCanonicalBit() public { MockUniswapV2Pair pool = new MockUniswapV2Pair(); pool.setReserves(11, 22); From fbb0526a86c87168960a8d4045b8e003166fb338 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 15:31:25 +0200 Subject: [PATCH 036/107] Use `_mockExpectCall` instead of an explicit mock contract --- test/0.8.25/BoolBoundary.t.sol | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index 74e5a6515..c283f14f0 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -70,18 +70,6 @@ contract MockUniswapV2Pair is IUniV2Pair { } } -contract MockEulerSwap { - uint256 public amount0Out; - uint256 public amount1Out; - address public recipient; - - function swap(uint256 amount0Out_, uint256 amount1Out_, address to, bytes calldata) external { - amount0Out = amount0Out_; - amount1Out = amount1Out_; - recipient = to; - } -} - contract MockHanjiPool is IHanjiPool { bool public lastIsAsk; bytes4 public lastSelector; @@ -389,13 +377,11 @@ contract BoolBoundaryTest is Test { assertEq(pool.swapData().length, 0); } - function testEulerSwapBoundaryUsesCanonicalBit() public { - MockEulerSwap pool = new MockEulerSwap(); - harness.fastEulerSwap(IEulerSwap(address(pool)), 9, address(0x55)); - assertEq(pool.amount0Out(), 0); - assertEq(pool.amount1Out(), 9); - assertEq(pool.recipient(), address(0x55)); + function testEulerSwapBoundaryUsesCanonicalBit() public { + address pool = makeAddr("pool"); + _mockExpectCall(pool, abi.encodeCall(IEulerSwap.swap, (0, 9, address(0x55), bytes(""))), bytes("")); + harness.fastEulerSwap(IEulerSwap(pool), 9, address(0x55)); } function testHanjiBoundaryCanonicalizesDirtyBool() public { From 55ff3b82c44de16fc179454eaa57707b45dc4a68 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 15:33:27 +0200 Subject: [PATCH 037/107] Fix too-lax test --- test/0.8.25/BoolBoundary.t.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index c283f14f0..d293681a3 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -85,6 +85,7 @@ contract MockHanjiPool is IHanjiPool { function placeOrder(bool isAsk, uint128, uint72, uint128, bool, bool, bool, uint256) external payable + override returns (uint64, uint128, uint128, uint128) { lastSelector = msg.sig; @@ -95,6 +96,7 @@ contract MockHanjiPool is IHanjiPool { function placeMarketOrderWithTargetValue(bool isAsk, uint128, uint72, uint128, bool, uint256) external payable + override returns (uint128, uint128, uint128) { lastSelector = msg.sig; @@ -105,6 +107,7 @@ contract MockHanjiPool is IHanjiPool { function getConfig() external view + override returns (uint256, uint256, address, address, bool, bool, address, address, uint64, uint64, uint64, uint64, bool) { return (0, 0, tokenX, tokenY, false, false, address(0), address(0), 0, 0, 0, 0, false); @@ -389,10 +392,7 @@ contract BoolBoundaryTest is Test { harness.hanjiPlaceMarketOrder(IHanjiPool(address(pool))); assertTrue(pool.lastIsAsk()); - assertTrue( - pool.lastSelector() == IHanjiPool.placeOrder.selector - || pool.lastSelector() == IHanjiPool.placeMarketOrderWithTargetValue.selector - ); + assertTrue(pool.lastSelector() == IHanjiPool.placeOrder.selector); assertEq(address(harness.hanjiGetToken(IHanjiPool(address(pool)))), address(0x22)); } From 306bc60da768fb4cd5f1ba965ca3a371b255bc1f Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 15:48:41 +0200 Subject: [PATCH 038/107] Rename `fastUniswapV2Pool` => `FastUniswapV2Pool` --- src/core/UniswapV2.sol | 6 +++--- test/0.8.25/BoolBoundary.t.sol | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/UniswapV2.sol b/src/core/UniswapV2.sol index 92a5e5aa7..bf1817d4a 100644 --- a/src/core/UniswapV2.sol +++ b/src/core/UniswapV2.sol @@ -18,7 +18,7 @@ interface IUniV2Pair { function swap(uint256, uint256, address, bytes calldata) external; } -library fastUniswapV2Pool { +library FastUniswapV2Pool { using Ternary for bool; function fastGetReserves(address pool, bool zeroForOne) @@ -83,7 +83,7 @@ library fastUniswapV2Pool { abstract contract UniswapV2 is SettlerSwapAbstract { using SafeTransferLib for IERC20; - using fastUniswapV2Pool for address; + using FastUniswapV2Pool for address; /// @dev Sell a token for another token using UniswapV2. function sellToUniswapV2( @@ -119,7 +119,7 @@ abstract contract UniswapV2 is SettlerSwapAbstract { } IERC20(sellToken).safeTransfer(address(pool), sellAmount); } - (uint256 sellReserve, uint256 buyReserve) = fastUniswapV2Pool.fastGetReserves(pool, zeroForOne); + (uint256 sellReserve, uint256 buyReserve) = FastUniswapV2Pool.fastGetReserves(pool, zeroForOne); if (sellAmount == 0 || sellTokenHasFee) { uint256 bal = IERC20(sellToken).fastBalanceOf(pool); sellAmount = bal - sellReserve; diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index d293681a3..cbb08906c 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -12,7 +12,7 @@ import {FastPermit} from "src/utils/SafePermit.sol"; import {IDAIStylePermit} from "src/interfaces/IERC2612.sol"; import {IEulerSwap, FastEulerSwap} from "src/core/EulerSwap.sol"; -import {IUniV2Pair, fastUniswapV2Pool} from "src/core/UniswapV2.sol"; +import {IUniV2Pair, FastUniswapV2Pool} from "src/core/UniswapV2.sol"; import {IHanjiPool, FastHanjiPool} from "src/core/Hanji.sol"; import {IMaverickV2Pool, FastMaverickV2Pool} from "src/core/MaverickV2.sol"; import {IEkuboCore, PoolKey as EkuboPoolKey, Config, SqrtRatio, UnsafeEkuboCore} from "src/core/EkuboV2.sol"; @@ -203,7 +203,7 @@ contract BoolBoundaryHarness { assembly ("memory-safe") { zeroForOne := 0x02 } - return fastUniswapV2Pool.fastGetReserves(pool, zeroForOne); + return FastUniswapV2Pool.fastGetReserves(pool, zeroForOne); } function fastUniswapV2Swap(address pool, uint256 buyAmount, address recipient) external { @@ -211,7 +211,7 @@ contract BoolBoundaryHarness { assembly ("memory-safe") { zeroForOne := 0x02 } - fastUniswapV2Pool.fastSwap(pool, zeroForOne, buyAmount, recipient); + FastUniswapV2Pool.fastSwap(pool, zeroForOne, buyAmount, recipient); } function fastEulerSwap(IEulerSwap pool, uint256 amountOut, address recipient) external { From aa85e50e3319d48368d645970bc6567ac7005873 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 15:49:54 +0200 Subject: [PATCH 039/107] Remove unused `_HAS_WNATIVE` --- src/CrossChainReceiverFactory.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/CrossChainReceiverFactory.sol b/src/CrossChainReceiverFactory.sol index 203549be9..687bce42f 100644 --- a/src/CrossChainReceiverFactory.sol +++ b/src/CrossChainReceiverFactory.sol @@ -101,7 +101,6 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte bytes32 private constant _WNATIVE_STORAGE_SALT = keccak256("Wrapped Native Token Address"); IWrappedNative private immutable _WNATIVE; - bool private immutable _HAS_WNATIVE = true; bool private immutable _MISSING_WNATIVE = false; bytes32 private constant _MULTICALL_STORAGE_SALT = keccak256("ERC2771-forwarding MultiCall Address"); @@ -200,7 +199,6 @@ contract CrossChainReceiverFactory is ICrossChainReceiverFactory, MultiCallConte == 0xa4675c945174b9ec4e7010035cbc327beed918e1ea949cf630df20b201167a0c ); // `_WNATIVE` is deliberately unset - _HAS_WNATIVE = false; _MISSING_WNATIVE = true; } else { // do some behavioral checks on `_WNATIVE` From 3e4a7a11d42ff7916415c9bc20e61e325f2c8902 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 15:51:00 +0200 Subject: [PATCH 040/107] Relax `isForwarded` masking in `UniswapV3Fork` to canonicalization --- src/core/UniswapV3Fork.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index 8255e1910..ae7131267 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -365,7 +365,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // middle of `payer`, because `payer` is all zeroes, it's treated as padding for the // first word of `permit`, which is the sell token permit := sub(permit2Data.offset, 0x0c) - isForwarded := and(0x01, calldataload(add(0x55, permit2Data.offset))) + isForwarded := lt(0x00, calldataload(add(0x55, permit2Data.offset))) sig.offset := add(0x75, permit2Data.offset) sig.length := sub(permit2Data.length, 0x75) } From 2ab0f812eab4dccfc1059deb74b3eaf5f447d6e7 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 16:08:04 +0200 Subject: [PATCH 041/107] Address bool boundary review feedback Co-Authored-By: Codex --- test/0.8.25/BoolBoundary.t.sol | 370 +++++++++++-------------- test/unit/core/UniswapV3UnitTest.t.sol | 31 ++- 2 files changed, 190 insertions(+), 211 deletions(-) diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index cbb08906c..f017bf137 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -4,18 +4,26 @@ pragma solidity ^0.8.25; import {Test} from "@forge-std/Test.sol"; import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; +import {Utils} from "test/unit/Utils.sol"; import {FastLogic} from "src/utils/FastLogic.sol"; import {Ternary} from "src/utils/Ternary.sol"; import {UnsafeMath, Math} from "src/utils/UnsafeMath.sol"; -import {FastPermit} from "src/utils/SafePermit.sol"; -import {IDAIStylePermit} from "src/interfaces/IERC2612.sol"; +import {FastPermit, SafePermit} from "src/utils/SafePermit.sol"; +import {IERC20PermitCommon, IDAIStylePermit} from "src/interfaces/IERC2612.sol"; import {IEulerSwap, FastEulerSwap} from "src/core/EulerSwap.sol"; import {IUniV2Pair, FastUniswapV2Pool} from "src/core/UniswapV2.sol"; import {IHanjiPool, FastHanjiPool} from "src/core/Hanji.sol"; import {IMaverickV2Pool, FastMaverickV2Pool} from "src/core/MaverickV2.sol"; import {IEkuboCore, PoolKey as EkuboPoolKey, Config, SqrtRatio, UnsafeEkuboCore} from "src/core/EkuboV2.sol"; +import { + IEkuboCore as IEkuboCoreV3, + PoolKey as EkuboV3PoolKey, + Config as EkuboV3Config, + SqrtRatio as EkuboV3SqrtRatio, + UnsafeEkuboCore as UnsafeEkuboV3Core +} from "src/core/EkuboV3.sol"; import { IPancakeInfinityCLPoolManager, IPancakeInfinityBinPoolManager, @@ -27,168 +35,9 @@ import { import {Encoder} from "src/core/FlashAccountingCommon.sol"; import {BalanceDelta} from "src/core/UniswapV4Types.sol"; -contract MockDaiPermitToken { - bool public lastAllowed; - - function permit(address, address, uint256, uint256, bool allowed, uint8, bytes32, bytes32) external returns (bool) { - lastAllowed = allowed; - return true; - } -} - -contract MockUniswapV2Pair is IUniV2Pair { - uint112 internal reserve0; - uint112 internal reserve1; - - uint256 public amount0Out; - uint256 public amount1Out; - address public recipient; - bytes public swapData; - - function setReserves(uint112 reserve0_, uint112 reserve1_) external { - reserve0 = reserve0_; - reserve1 = reserve1_; - } - - function token0() external pure returns (address) { - return address(0); - } - - function token1() external pure returns (address) { - return address(0); - } - - function getReserves() external view returns (uint112, uint112, uint32) { - return (reserve0, reserve1, 0); - } - - function swap(uint256 amount0Out_, uint256 amount1Out_, address recipient_, bytes calldata data_) external { - amount0Out = amount0Out_; - amount1Out = amount1Out_; - recipient = recipient_; - swapData = data_; - } -} - -contract MockHanjiPool is IHanjiPool { - bool public lastIsAsk; - bytes4 public lastSelector; - - address internal tokenX; - address internal tokenY; - - constructor(address tokenX_, address tokenY_) { - tokenX = tokenX_; - tokenY = tokenY_; - } - - function placeOrder(bool isAsk, uint128, uint72, uint128, bool, bool, bool, uint256) - external - payable - override - returns (uint64, uint128, uint128, uint128) - { - lastSelector = msg.sig; - lastIsAsk = isAsk; - return (0, 0, 0, 0); - } - - function placeMarketOrderWithTargetValue(bool isAsk, uint128, uint72, uint128, bool, uint256) - external - payable - override - returns (uint128, uint128, uint128) - { - lastSelector = msg.sig; - lastIsAsk = isAsk; - return (0, 0, 0); - } - - function getConfig() - external - view - override - returns (uint256, uint256, address, address, bool, bool, address, address, uint64, uint64, uint64, uint64, bool) - { - return (0, 0, tokenX, tokenY, false, false, address(0), address(0), 0, 0, 0, 0, false); - } -} - -contract MockMaverickPool { - address public lastRecipient; - uint256 public lastAmount; - bool public lastTokenAIn; - bool public lastExactOutput; - int32 public lastTickLimit; - bytes public lastData; - - function swap(address recipient, IMaverickV2Pool.SwapParams calldata params, bytes calldata data) - external - returns (uint256 amountIn, uint256 amountOut) - { - lastRecipient = recipient; - lastAmount = params.amount; - lastTokenAIn = params.tokenAIn; - lastExactOutput = params.exactOutput; - lastTickLimit = params.tickLimit; - lastData = data; - return (0, 0); - } -} - -contract MockEkuboCore is IEkuboCore { - bool public lastIsToken1; - - function lock() external {} - - function swap_611415377(EkuboPoolKey memory, int128, bool isToken1, SqrtRatio, uint256) - external - payable - returns (int128 delta0, int128 delta1) - { - lastIsToken1 = isToken1; - return (0, 0); - } - - function forward(address) external {} - - function pay(address) external pure returns (uint128 payment) { - return 0; - } - - function withdraw(address, address, uint128) external {} -} - -contract MockPancakeClManager { - bool public lastZeroForOne; - bytes public lastHookData; - - function swap( - PancakePoolKey memory, - IPancakeInfinityCLPoolManager.SwapParams calldata params, - bytes calldata hookData - ) external returns (BalanceDelta delta) { - lastZeroForOne = params.zeroForOne; - lastHookData = hookData; - return BalanceDelta.wrap(0); - } -} - -contract MockPancakeBinManager { - bool public lastSwapForY; - bytes public lastHookData; - - function swap(PancakePoolKey memory, bool swapForY, int128, bytes calldata hookData) - external - returns (BalanceDelta delta) - { - lastSwapForY = swapForY; - lastHookData = hookData; - return BalanceDelta.wrap(0); - } -} - contract BoolBoundaryHarness { + using SafePermit for IDAIStylePermit; + function fastDaiPermit(IDAIStylePermit token) external returns (bool success) { bool allowed; assembly ("memory-safe") { @@ -198,6 +47,14 @@ contract BoolBoundaryHarness { FastPermit.fastDAIPermit(token, address(0x11), address(0x22), 0x33, 0x44, allowed, bytes32(0), bytes32(0)); } + function safeDaiPermit(IDAIStylePermit token, address owner, bytes32 vs, bytes32 r) external { + bool allowed; + assembly ("memory-safe") { + allowed := 0x02 + } + token.safePermit(owner, address(0x22), 0, 0, allowed, vs, r); + } + function fastUniswapV2GetReserves(address pool) external view returns (uint256 sellReserve, uint256 buyReserve) { bool zeroForOne; assembly ("memory-safe") { @@ -263,6 +120,19 @@ contract BoolBoundaryHarness { return UnsafeEkuboCore.unsafeSwap(core, poolKey, amount, isToken1, sqrtRatioLimit); } + function ekuboV3Swap( + IEkuboCoreV3 core, + EkuboV3PoolKey memory poolKey, + int256 amount, + EkuboV3SqrtRatio sqrtRatioLimit + ) external returns (int256 delta0, int256 delta1) { + bool isToken1; + assembly ("memory-safe") { + isToken1 := 0x02 + } + return UnsafeEkuboV3Core.unsafeSwap(core, poolKey, amount, isToken1, sqrtRatioLimit); + } + function pancakeClSwap( IPancakeInfinityCLPoolManager poolManager, PancakePoolKey memory key, @@ -314,7 +184,7 @@ contract BoolBoundaryHarness { } } -contract BoolBoundaryTest is Test { +contract BoolBoundaryTest is Utils, Test { using FastLogic for bool; using Ternary for bool; using UnsafeMath for uint256; @@ -359,85 +229,177 @@ contract BoolBoundaryTest is Test { } function testFastDaiPermitCanonicalizesDirtyBool() public { - MockDaiPermitToken token = new MockDaiPermitToken(); + address token = makeAddr("dai"); + _mockExpectCall( + token, + abi.encodeCall( + IDAIStylePermit.permit, + (address(0x11), address(0x22), uint256(0x33), uint256(0x44), true, uint8(27), bytes32(0), bytes32(0)) + ), + abi.encode(true) + ); + + assertTrue(harness.fastDaiPermit(IDAIStylePermit(token))); + } - assertTrue(harness.fastDaiPermit(IDAIStylePermit(address(token)))); - assertTrue(token.lastAllowed()); + function testSafeDaiPermitFallbackCanonicalizesDirtyBool() public { + uint256 ownerPrivateKey = 0xa11ce; + address owner = vm.addr(ownerPrivateKey); + address token = makeAddr("dai"); + bytes32 domainSeparator = keccak256("MockDaiPermitToken"); + + bytes32 structHash = keccak256( + abi.encode( + keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)"), + owner, + address(0x22), + uint256(0), + uint256(0), + true + ) + ); + bytes32 signingHash = keccak256(abi.encodePacked(hex"1901", domainSeparator, structHash)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, signingHash); + bytes32 vs = bytes32(uint256(s) | (uint256(v - 27) << 255)); + + _mockExpectCall( + token, + abi.encodeCall(IDAIStylePermit.permit, (owner, address(0x22), uint256(0), uint256(0), true, v, r, s)), + abi.encode(false) + ); + _mockExpectCall(token, abi.encodeCall(IERC20PermitCommon.nonces, (owner)), abi.encode(uint256(1))); + _mockExpectCall(token, abi.encodeCall(IERC20.allowance, (owner, address(0x22))), abi.encode(type(uint256).max)); + _mockExpectCall(token, abi.encodeCall(IERC20PermitCommon.DOMAIN_SEPARATOR, ()), abi.encode(domainSeparator)); + + harness.safeDaiPermit(IDAIStylePermit(token), owner, vs, r); } function testUniswapV2BoundaryUsesCanonicalBit() public { - MockUniswapV2Pair pool = new MockUniswapV2Pair(); - pool.setReserves(11, 22); + address pool = makeAddr("pool"); + _mockExpectCall( + pool, abi.encodeCall(IUniV2Pair.getReserves, ()), abi.encode(uint112(11), uint112(22), uint32(0)) + ); - (uint256 sellReserve, uint256 buyReserve) = harness.fastUniswapV2GetReserves(address(pool)); + (uint256 sellReserve, uint256 buyReserve) = harness.fastUniswapV2GetReserves(pool); assertEq(sellReserve, 11); assertEq(buyReserve, 22); - harness.fastUniswapV2Swap(address(pool), 7, address(0x44)); - assertEq(pool.amount0Out(), 0); - assertEq(pool.amount1Out(), 7); - assertEq(pool.recipient(), address(0x44)); - assertEq(pool.swapData().length, 0); + _mockExpectCall(pool, abi.encodeCall(IUniV2Pair.swap, (uint256(0), uint256(7), address(0x44), bytes(""))), ""); + harness.fastUniswapV2Swap(pool, 7, address(0x44)); } - function testEulerSwapBoundaryUsesCanonicalBit() public { address pool = makeAddr("pool"); - _mockExpectCall(pool, abi.encodeCall(IEulerSwap.swap, (0, 9, address(0x55), bytes(""))), bytes("")); + _mockExpectCall(pool, abi.encodeCall(IEulerSwap.swap, (0, 9, address(0x55), bytes(""))), bytes("")); harness.fastEulerSwap(IEulerSwap(pool), 9, address(0x55)); } function testHanjiBoundaryCanonicalizesDirtyBool() public { - MockHanjiPool pool = new MockHanjiPool(address(0x11), address(0x22)); + address pool = makeAddr("pool"); + _mockExpectCall( + pool, + abi.encodeCall( + IHanjiPool.placeOrder, + (true, uint128(7), uint72(11), type(uint128).max, true, false, true, type(uint256).max) + ), + abi.encode(uint64(0), uint128(0), uint128(0), uint128(0)) + ); - harness.hanjiPlaceMarketOrder(IHanjiPool(address(pool))); - assertTrue(pool.lastIsAsk()); - assertTrue(pool.lastSelector() == IHanjiPool.placeOrder.selector); + harness.hanjiPlaceMarketOrder(IHanjiPool(pool)); - assertEq(address(harness.hanjiGetToken(IHanjiPool(address(pool)))), address(0x22)); + _mockExpectCall( + pool, + abi.encodeCall(IHanjiPool.getConfig, ()), + abi.encode(uint256(0), uint256(0), address(0x11), address(0x22)) + ); + assertEq(address(harness.hanjiGetToken(IHanjiPool(pool))), address(0x22)); } function testMaverickEncodeCanonicalizesDirtyBool() public { - MockMaverickPool pool = new MockMaverickPool(); bytes memory data = harness.maverickEncode(address(0x66), 7, 9, hex"abcd"); - (bool success,) = address(pool).call(data); - assertTrue(success); - assertEq(pool.lastRecipient(), address(0x66)); - assertEq(pool.lastAmount(), 7); - assertTrue(pool.lastTokenAIn()); - assertFalse(pool.lastExactOutput()); - assertEq(pool.lastTickLimit(), 9); - assertEq(pool.lastData(), hex"abcd"); + assertEq( + data, + bytes.concat( + abi.encodeWithSelector( + IMaverickV2Pool.swap.selector, + address(0x66), + uint256(7), + true, + false, + int32(9), + uint256(0xc0), + uint256(2) + ), + hex"abcd" + ) + ); } function testEkuboV2SwapCanonicalizesDirtyBool() public { - MockEkuboCore core = new MockEkuboCore(); + address core = makeAddr("core"); EkuboPoolKey memory key = EkuboPoolKey({token0: address(0x11), token1: address(0x22), config: Config.wrap(0)}); + _mockExpectCall( + core, + abi.encodeCall(IEkuboCore.swap_611415377, (key, int128(7), true, SqrtRatio.wrap(9), uint256(0))), + abi.encode(int128(0), int128(0)) + ); - harness.ekuboV2Swap(IEkuboCore(address(core)), key, 7, SqrtRatio.wrap(9)); - assertTrue(core.lastIsToken1()); + harness.ekuboV2Swap(IEkuboCore(core), key, 7, SqrtRatio.wrap(9)); + } + + function testEkuboV3SwapCanonicalizesDirtyBool() public { + address core = makeAddr("core"); + EkuboV3PoolKey memory key = + EkuboV3PoolKey({token0: address(0x11), token1: address(0x22), config: EkuboV3Config.wrap(0)}); + bytes memory expectedCall = + bytes.concat(bytes4(0), abi.encode(key), abi.encodePacked(uint96(9), int128(7), uint32(0x80000000))); + _mockExpectCall(core, expectedCall, abi.encode(bytes32(0))); + + harness.ekuboV3Swap(IEkuboCoreV3(core), key, 7, EkuboV3SqrtRatio.wrap(9)); } function testPancakeInfinityCanonicalizesDirtyBool() public { - MockPancakeClManager cl = new MockPancakeClManager(); - MockPancakeBinManager bin = new MockPancakeBinManager(); + address cl = makeAddr("cl"); + address bin = makeAddr("bin"); PancakePoolKey memory key = PancakePoolKey({ currency0: IERC20(address(0x11)), currency1: IERC20(address(0x22)), hooks: IHooks.wrap(address(0x33)), - poolManager: IPancakeInfinityCLPoolManager(address(cl)), + poolManager: IPancakeInfinityCLPoolManager(cl), fee: 500, parameters: bytes32(uint256(7)) }); - harness.pancakeClSwap(IPancakeInfinityCLPoolManager(address(cl)), key, 1, 2, hex"ab"); - assertTrue(cl.lastZeroForOne()); - assertEq(cl.lastHookData(), hex"ab"); - - harness.pancakeBinSwap(IPancakeInfinityBinPoolManager(address(bin)), key, 3, hex"cd"); - assertTrue(bin.lastSwapForY()); - assertEq(bin.lastHookData(), hex"cd"); + _mockExpectCall( + cl, + bytes.concat( + abi.encodeWithSelector( + IPancakeInfinityCLPoolManager.swap.selector, + key, + true, + int256(1), + uint160(2), + uint256(0x140), + uint256(1) + ), + hex"ab" + ), + abi.encode(BalanceDelta.wrap(0)) + ); + harness.pancakeClSwap(IPancakeInfinityCLPoolManager(cl), key, 1, 2, hex"ab"); + + _mockExpectCall( + bin, + bytes.concat( + abi.encodeWithSelector( + IPancakeInfinityBinPoolManager.swap.selector, key, true, int128(3), uint256(0x120), uint256(1) + ), + hex"cd" + ), + abi.encode(BalanceDelta.wrap(0)) + ); + harness.pancakeBinSwap(IPancakeInfinityBinPoolManager(bin), key, 3, hex"cd"); } function testFlashEncoderCanonicalizesDirtyBoolBytes() public { diff --git a/test/unit/core/UniswapV3UnitTest.t.sol b/test/unit/core/UniswapV3UnitTest.t.sol index 712d8c80b..3741c34c0 100644 --- a/test/unit/core/UniswapV3UnitTest.t.sol +++ b/test/unit/core/UniswapV3UnitTest.t.sol @@ -438,7 +438,7 @@ contract UniswapV3UnitTest is Utils, Test { // uni.sell(RECIPIENT, encodedPath, minBuyAmount, permitTransfer, hex""); } - function testUniswapV3SellPermit2RejectsDirtyForwardedBool() public { + function testUniswapV3SellAllowanceHolderAcceptsDirtyForwardedBool() public { uint256 amount = 99999; deployCodeTo( @@ -447,12 +447,29 @@ contract UniswapV3UnitTest is Utils, Test { POOL ); - ISignatureTransfer.TokenPermissions memory permitted = - ISignatureTransfer.TokenPermissions({token: TOKEN0, amount: amount}); - ISignatureTransfer.PermitTransferFrom memory permitTransfer = - ISignatureTransfer.PermitTransferFrom({permitted: permitted, nonce: 0, deadline: 0}); + ISignatureTransfer.PermitTransferFrom memory permitTransfer = ISignatureTransfer.PermitTransferFrom({ + permitted: ISignatureTransfer.TokenPermissions({token: TOKEN0, amount: amount}), + nonce: 0, + deadline: block.timestamp + }); - vm.expectRevert(bytes("")); - uni.sell(RECIPIENT, encodedPath, permitTransfer, hex"deadbeef", amount); + _mockExpectCall( + address(ALLOWANCE_HOLDER), + abi.encodeCall(IAllowanceHolder.transferFrom, (TOKEN0, address(this), POOL, 1)), + abi.encode(true) + ); + + vm.prank(address(ALLOWANCE_HOLDER)); + (bool success, bytes memory returndata) = address(uni) + .call( + abi.encodePacked( + abi.encodeCall(uni.sell, (RECIPIENT, encodedPath, permitTransfer, hex"", amount)), address(this) + ) + ); + if (!success) { + assembly ("memory-safe") { + revert(add(0x20, returndata), mload(returndata)) + } + } } } From 528e5ed574704d54fcec1c3802a4bf9b16d505bf Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 16:23:03 +0200 Subject: [PATCH 042/107] Test dirty UniswapV3 swap direction encoding Co-Authored-By: Codex --- src/core/UniswapV3Fork.sol | 57 +++++++++++++++++++++------------- test/0.8.25/BoolBoundary.t.sol | 41 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index ae7131267..cf9aa7933 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -33,6 +33,39 @@ interface IUniswapV3Pool { ) external returns (int256 amount0, int256 amount1); } +library FastUniswapV3Pool { + function fastEncodeSwap( + address recipient, + bool zeroForOne, + uint256 sellAmount, + uint160 sqrtPriceLimitX96, + bytes memory swapCallbackData + ) internal pure returns (bytes memory data, uint256 freeMemPtr) { + // Equivalent to `abi.encodeCall(IUniswapV3Pool.swap, (..., swapCallbackData))`, + // but keeps the dynamic bytes tail tightly packed and canonicalizes `zeroForOne`. + assembly ("memory-safe") { + freeMemPtr := mload(0x40) + data := freeMemPtr + + // encode the call to pool.swap + let callbackLen := mload(swapCallbackData) + mcopy(add(0xc4, data), swapCallbackData, add(0x20, callbackLen)) + mstore(add(0xa4, data), 0xa0) + mstore(add(0x84, data), and(0xffffffffffffffffffffffffffffffffffffffff, sqrtPriceLimitX96)) + mstore(add(0x64, data), sellAmount) + mstore(add(0x44, data), lt(0x00, zeroForOne)) + mstore(add(0x24, data), recipient) + mstore(add(0x10, data), 0x128acb08000000000000000000000000) // selector for `swap(address,bool,int256,uint160,bytes)` with `recipient`'s padding + + // set data.length + mstore(data, add(0xc4, callbackLen)) + + // advance the free memory pointer (we'll put it back later) + mstore(0x40, add(add(0xe4, callbackLen), data)) + } + } +} + abstract contract UniswapV3Fork is SettlerSwapAbstract { using Ternary for bool; using UnsafeMath for uint256; @@ -146,28 +179,8 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // Intermediate tokens go to this contract. Final tokens go to `recipient`. address to = isPathMultiHop.ternary(address(this), recipient); - uint256 freeMemPtr; - bytes memory data; - assembly ("memory-safe") { - freeMemPtr := mload(0x40) - data := freeMemPtr - - // encode the call to pool.swap - let callbackLen := mload(swapCallbackData) - mcopy(add(0xc4, data), swapCallbackData, add(0x20, callbackLen)) - mstore(add(0xa4, data), 0xa0) - mstore(add(0x84, data), and(0xffffffffffffffffffffffffffffffffffffffff, sqrtPriceLimitX96)) - mstore(add(0x64, data), sellAmount) - mstore(add(0x44, data), lt(0x00, zeroForOne)) - mstore(add(0x24, data), to) - mstore(add(0x10, data), 0x128acb08000000000000000000000000) // selector for `swap(address,bool,int256,uint160,bytes)` with `to`'s padding - - // set data.length - mstore(data, add(0xc4, callbackLen)) - - // advance the free memory pointer (we'll put it back later) - mstore(0x40, add(add(0xe4, callbackLen), data)) - } + (bytes memory data, uint256 freeMemPtr) = + FastUniswapV3Pool.fastEncodeSwap(to, zeroForOne, sellAmount, sqrtPriceLimitX96, swapCallbackData); (int256 amount0, int256 amount1) = abi.decode( _setOperatorAndCall(address(pool), data, callbackSelector, _uniV3ForkCallback), (int256, int256) diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index f017bf137..de6f6d34f 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -14,6 +14,7 @@ import {IERC20PermitCommon, IDAIStylePermit} from "src/interfaces/IERC2612.sol"; import {IEulerSwap, FastEulerSwap} from "src/core/EulerSwap.sol"; import {IUniV2Pair, FastUniswapV2Pool} from "src/core/UniswapV2.sol"; +import {IUniswapV3Pool, FastUniswapV3Pool} from "src/core/UniswapV3Fork.sol"; import {IHanjiPool, FastHanjiPool} from "src/core/Hanji.sol"; import {IMaverickV2Pool, FastMaverickV2Pool} from "src/core/MaverickV2.sol"; import {IEkuboCore, PoolKey as EkuboPoolKey, Config, SqrtRatio, UnsafeEkuboCore} from "src/core/EkuboV2.sol"; @@ -79,6 +80,25 @@ contract BoolBoundaryHarness { FastEulerSwap.fastSwap(pool, zeroForOne, amountOut, recipient); } + function uniswapV3Swap( + IUniswapV3Pool pool, + address recipient, + uint256 sellAmount, + uint160 sqrtPriceLimitX96, + bytes memory callbackData + ) external returns (bytes memory returndata) { + bool zeroForOne; + // Force a dirty true bool before calling the production encoder. + assembly ("memory-safe") { + zeroForOne := 0x02 + } + (bytes memory data,) = + FastUniswapV3Pool.fastEncodeSwap(recipient, zeroForOne, sellAmount, sqrtPriceLimitX96, callbackData); + bool success; + (success, returndata) = address(pool).call(data); + require(success); + } + function hanjiPlaceMarketOrder(IHanjiPool pool) external returns (uint256 executed) { bool isAsk; assembly ("memory-safe") { @@ -294,6 +314,27 @@ contract BoolBoundaryTest is Utils, Test { harness.fastEulerSwap(IEulerSwap(pool), 9, address(0x55)); } + function testUniswapV3SwapCanonicalizesDirtyZeroForOne() public { + address pool = makeAddr("pool"); + bytes memory callbackData = abi.encodePacked(address(0x55), address(0x66)); + bytes memory returnData = abi.encode(int256(0), int256(-7)); + bytes memory expectedCall = bytes.concat( + abi.encodeWithSelector(IUniswapV3Pool.swap.selector, address(0x44), true, uint256(7), uint160(9)), + bytes32(uint256(0xa0)), + bytes32(callbackData.length), + callbackData + ); + uint256 zeroForOneWord; + // Verify the expected calldata uses a canonical ABI bool word for `zeroForOne`. + assembly ("memory-safe") { + zeroForOneWord := mload(add(expectedCall, 0x44)) + } + assertEq(zeroForOneWord, 1); + + _mockExpectCall(pool, expectedCall, returnData); + assertEq(harness.uniswapV3Swap(IUniswapV3Pool(pool), address(0x44), 7, 9, callbackData), returnData); + } + function testHanjiBoundaryCanonicalizesDirtyBool() public { address pool = makeAddr("pool"); _mockExpectCall( From b156ec53c15fb609467c4c6f3d5783c9051dbaef Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 16:40:23 +0200 Subject: [PATCH 043/107] Fix mock DAI permit domain separator Co-Authored-By: Codex --- test/0.8.25/BoolBoundary.t.sol | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/0.8.25/BoolBoundary.t.sol b/test/0.8.25/BoolBoundary.t.sol index de6f6d34f..4e845cfcc 100644 --- a/test/0.8.25/BoolBoundary.t.sol +++ b/test/0.8.25/BoolBoundary.t.sol @@ -266,7 +266,15 @@ contract BoolBoundaryTest is Utils, Test { uint256 ownerPrivateKey = 0xa11ce; address owner = vm.addr(ownerPrivateKey); address token = makeAddr("dai"); - bytes32 domainSeparator = keccak256("MockDaiPermitToken"); + bytes32 domainSeparator = keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256("MockDaiPermitToken"), + keccak256("1"), + block.chainid, + token + ) + ); bytes32 structHash = keccak256( abi.encode( From c138946767bd21a416e17af7023b8696a9d207b6 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 16:44:02 +0200 Subject: [PATCH 044/107] Add directions for agents around commenting and code archaeology --- AGENTS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 6b9563a67..c97391b19 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -411,9 +411,15 @@ IERC20 internal constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeee ## Critical Reminders +Comments, notes, commit messages, PR descriptions, and docs must describe only +the current implementation unless historical context is required for present +correctness. Archaeology is forbidden. + ### DO NOT - Create documentation files unless explicitly requested +- Write notes, comments, docs, commit messages, or PR descriptions that describe historical evolution instead of the current system unless the history is required for current correctness +- Use comments to explain what used to be true, what changed, why something was once necessary, or that a workaround/kludge existed previously - Make up performance numbers or generic justifications for changes - Add features beyond what was asked (no over-engineering) - Modify the `_dispatch` copy/paste pattern without updating all locations @@ -422,6 +428,7 @@ IERC20 internal constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeee ### ALWAYS - Read relevant existing code before making changes +- Write comments as current-state documentation only - Check gas impact with `npm run diff:main` - Follow existing patterns in chain-specific code - Mark assembly blocks `memory-safe` when appropriate From 803fe15ef27f6c7aa50fd1f96c5589e66c22e415 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 8 May 2026 17:44:28 +0200 Subject: [PATCH 045/107] Require that AI agents add a `Co-Authored-By:` to each commit message --- AGENTS.md | 4 +++- CONTRIBUTING.md | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index c97391b19..eb3a3aaed 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -359,9 +359,11 @@ Key settings in `foundry.toml`: # ✅ Stage specific files and review git add src/core/MyFeature.sol test/unit/MyFeatureTest.t.sol git diff --staged -git commit -m "Fix bug in MyFeature" +git commit -m "Fix bug in MyFeature" -m 'Co-Authored-By: AI Agent ' ``` +You MUST add a `Co-Authored-By:` line at the end of each commit message explicitly referencing yourself as the coauthor. Refer to yourself using the name that best describes your identity as a model, harness, or agentic system. If this is ambiguous, add multiple `Co-Authored-By:` lines. + ### Before Committing ```bash diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b85650b3c..01238c283 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,10 @@ that appears to be majority AI-authored without human review. Any contributor who opens majority AI-authored pull requests may be banned from opening pull requests against this repository. +All AI-assisted commits must include one or more `Co-Authored-By:` lines +attributing which AI models, harnesses, and/or agents were used in the +production of those commits. + # Documentation We do not accept pull requests that only modify documentation, correct spelling, From 0fe01eb597d916cd72a2de6684eeae526c3fa3ab Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 8 May 2026 17:59:58 +0200 Subject: [PATCH 046/107] More AGENTS.md instructions for coauthorship --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index eb3a3aaed..7c52cc48b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -362,7 +362,7 @@ git diff --staged git commit -m "Fix bug in MyFeature" -m 'Co-Authored-By: AI Agent ' ``` -You MUST add a `Co-Authored-By:` line at the end of each commit message explicitly referencing yourself as the coauthor. Refer to yourself using the name that best describes your identity as a model, harness, or agentic system. If this is ambiguous, add multiple `Co-Authored-By:` lines. +You MUST add a `Co-Authored-By:` line at the end of each commit message explicitly referencing yourself as the coauthor. Refer to yourself using the name that best describes your identity as a model, harness, or agentic system, and use an email address that is reflective of your creator(s). If this is ambiguous, add multiple `Co-Authored-By:` lines. ### Before Committing From 66585e3b52f7986e828cc1c701391a8e87623054 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 17:15:16 +0200 Subject: [PATCH 047/107] Fix UniV3 forwarded flag decoding Co-Authored-By: OpenAI Codex --- src/core/UniswapV3Fork.sol | 2 +- test/unit/core/UniswapV3UnitTest.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/UniswapV3Fork.sol b/src/core/UniswapV3Fork.sol index cf9aa7933..d9f6cc845 100644 --- a/src/core/UniswapV3Fork.sol +++ b/src/core/UniswapV3Fork.sol @@ -378,7 +378,7 @@ abstract contract UniswapV3Fork is SettlerSwapAbstract { // middle of `payer`, because `payer` is all zeroes, it's treated as padding for the // first word of `permit`, which is the sell token permit := sub(permit2Data.offset, 0x0c) - isForwarded := lt(0x00, calldataload(add(0x55, permit2Data.offset))) + isForwarded := lt(0x00, shr(0xf8, calldataload(add(0x74, permit2Data.offset)))) sig.offset := add(0x75, permit2Data.offset) sig.length := sub(permit2Data.length, 0x75) } diff --git a/test/unit/core/UniswapV3UnitTest.t.sol b/test/unit/core/UniswapV3UnitTest.t.sol index 3741c34c0..4a3bdb6d5 100644 --- a/test/unit/core/UniswapV3UnitTest.t.sol +++ b/test/unit/core/UniswapV3UnitTest.t.sol @@ -383,7 +383,7 @@ contract UniswapV3UnitTest is Utils, Test { ISignatureTransfer.TokenPermissions memory permitted = ISignatureTransfer.TokenPermissions({token: TOKEN0, amount: amount}); ISignatureTransfer.PermitTransferFrom memory permitTransfer = - ISignatureTransfer.PermitTransferFrom({permitted: permitted, nonce: 0, deadline: 0}); + ISignatureTransfer.PermitTransferFrom({permitted: permitted, nonce: 0, deadline: block.timestamp + 1}); ISignatureTransfer.SignatureTransferDetails memory transferDetails = ISignatureTransfer.SignatureTransferDetails({to: POOL, requestedAmount: 1}); From b260967179e3b2737b5388af4b5e3b453efa2aab Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 19 Jun 2026 17:50:09 +0200 Subject: [PATCH 048/107] Regenerate integration gas snapshots Update integration gas snapshots and regenerated README gas tables. Co-Authored-By: OpenAI Codex --- .../DAIPermit_transfer-from-with-permit.snap | 2 +- .../ERC2612_transfer-from-with-permit.snap | 2 +- ...Transaction_transfer-from-with-permit.snap | 2 +- ...lowanceHolder_balancerV3VIP_USDC-USDT.snap | 2 +- .../allowanceHolder_bebop_USDC-WETH.snap | 2 +- .../allowanceHolder_bebop_WETH-USDC.snap | 2 +- ...lowanceHolder_bebop_partial_USDC-WETH.snap | 2 +- ...lowanceHolder_bebop_partial_WETH-USDC.snap | 2 +- ...owanceHolder_bebop_slippage_USDC-WETH.snap | 2 +- ...owanceHolder_bebop_slippage_WETH-USDC.snap | 2 +- .../allowanceHolder_ekuboVIP_USDC-USDT.snap | 2 +- .../allowanceHolder_ekuboVIP_USDC-WETH.snap | 2 +- .../allowanceHolder_empty_DAI-WETH.snap | 2 +- .../allowanceHolder_empty_USDC-USDT.snap | 2 +- .../allowanceHolder_empty_USDC-WETH.snap | 2 +- .../allowanceHolder_empty_USDT-CAKE.snap | 2 +- .../allowanceHolder_empty_USDT-WBNB.snap | 2 +- .../allowanceHolder_empty_USDT-WETH.snap | 2 +- ...owanceHolder_empty_hanji_usdc_to_wmon.snap | 2 +- ...owanceHolder_empty_hanji_wmon_to_usdc.snap | 2 +- ...ceHolder_pancakeInfinityVIP_USDT-CAKE.snap | 2 +- ...ceHolder_pancakeInfinityVIP_USDT-WBNB.snap | 2 +- ...fq_proportionalFee_sellToken_DAI-WETH.snap | 2 +- ...q_proportionalFee_sellToken_USDC-USDT.snap | 2 +- ...q_proportionalFee_sellToken_USDC-WETH.snap | 2 +- ...q_proportionalFee_sellToken_USDT-CAKE.snap | 2 +- ...q_proportionalFee_sellToken_USDT-WBNB.snap | 2 +- ...q_proportionalFee_sellToken_USDT-WETH.snap | 2 +- ...ionalFee_sellToken_hanji_usdc_to_wmon.snap | 2 +- ...ionalFee_sellToken_hanji_wmon_to_usdc.snap | 2 +- ...older_uniswapV2_single_chain_DAI-WETH.snap | 2 +- ...lder_uniswapV2_single_chain_USDC-WETH.snap | 2 +- ...lder_uniswapV2_single_chain_USDT-WETH.snap | 2 +- ...allowanceHolder_uniswapV3VIP_DAI-WETH.snap | 2 +- ...llowanceHolder_uniswapV3VIP_USDC-USDT.snap | 2 +- ...llowanceHolder_uniswapV3VIP_USDC-WETH.snap | 2 +- ...llowanceHolder_uniswapV3VIP_USDT-WETH.snap | 2 +- ...Holder_uniswapV3VIP_contract_DAI-WETH.snap | 2 +- ...older_uniswapV3VIP_contract_USDC-USDT.snap | 2 +- ...older_uniswapV3VIP_contract_USDC-WETH.snap | 2 +- ...older_uniswapV3VIP_contract_USDT-WETH.snap | 2 +- .../allowanceHolder_uniswapV3_DAI-WETH.snap | 2 +- .../allowanceHolder_uniswapV3_USDC-USDT.snap | 2 +- .../allowanceHolder_uniswapV3_USDC-WETH.snap | 2 +- .../allowanceHolder_uniswapV3_USDT-WETH.snap | 2 +- .forge-snapshots/curveV2Pool_USDT-WETH.snap | 2 +- ..._sellNativeForUsdc_hanji_wmon_to_usdc.snap | 2 +- ...ji_sellUsdcForWmon_hanji_usdc_to_wmon.snap | 2 +- ...ji_sellWmonForUsdc_hanji_wmon_to_usdc.snap | 2 +- .../settler_balancerV3VIP_USDC-USDT.snap | 2 +- .../settler_balancerV3_USDC-USDT.snap | 2 +- .../settler_basic_curve_USDT-WETH.snap | 2 +- .../settler_curveV2_fee_USDT-WETH.snap | 2 +- .../settler_dodoV1_USDC-WETH.snap | 2 +- .forge-snapshots/settler_dodov2_USDT-DAI.snap | 2 +- .../settler_dodov2_custody_USDT-DAI.snap | 2 +- .../settler_ekuboExtension_USDT-WETH.snap | 2 +- .../settler_ekuboV2Extension_USDC-WETH.snap | 2 +- .../settler_ekuboV2_USDC-USDT.snap | 2 +- .../settler_ekuboV2_USDC-WETH.snap | 2 +- .../settler_ekuboVIP_USDC-USDT.snap | 2 +- .../settler_ekuboVIP_USDC-WETH.snap | 2 +- .forge-snapshots/settler_ekubo_USDC-USDT.snap | 2 +- .forge-snapshots/settler_ekubo_USDC-WETH.snap | 2 +- .../settler_eulerSwapCustody_USDC-USDT.snap | 2 +- .../settler_eulerSwap_USDC-USDT.snap | 2 +- .../settler_eulerSwap_USDT-USDC.snap | 2 +- ...xternalMoveExecute_uniswapV3_DAI-WETH.snap | 2 +- ...ternalMoveExecute_uniswapV3_USDC-USDT.snap | 2 +- ...ternalMoveExecute_uniswapV3_USDC-WETH.snap | 2 +- ...ternalMoveExecute_uniswapV3_USDT-WETH.snap | 2 +- ...ternalMoveExecute_uniswapV3_WETH-USDC.snap | 2 +- .../settler_makerPsmLite_buyGem_DAI-USDC.snap | 2 +- ...settler_makerPsmLite_buyGem_USDD-USDT.snap | 2 +- ...settler_makerPsmLite_buyGem_USDS-USDC.snap | 2 +- ...settler_makerPsmLite_sellGem_USDC-DAI.snap | 2 +- ...ettler_makerPsmLite_sellGem_USDC-USDS.snap | 2 +- ...ettler_makerPsmLite_sellGem_USDT-USDD.snap | 2 +- .../settler_maverickV2_USDC-WETH.snap | 2 +- .../settler_maverickV2_custody_USDC-WETH.snap | 2 +- .../settler_metaTxn_balancerV3_USDC-USDT.snap | 2 +- .../settler_metaTxn_ekubo_USDC-USDT.snap | 2 +- .../settler_metaTxn_ekubo_USDC-WETH.snap | 2 +- ..._metaTxn_makerPsmLite_buyGem_DAI-USDC.snap | 2 +- ...metaTxn_makerPsmLite_buyGem_USDD-USDT.snap | 2 +- ...metaTxn_makerPsmLite_buyGem_USDS-USDC.snap | 2 +- ...metaTxn_makerPsmLite_sellGem_USDC-DAI.snap | 2 +- ...etaTxn_makerPsmLite_sellGem_USDC-USDS.snap | 2 +- ...etaTxn_makerPsmLite_sellGem_USDT-USDD.snap | 2 +- ...ler_metaTxn_pancakeInfinity_USDT-CAKE.snap | 2 +- ...ler_metaTxn_pancakeInfinity_USDT-WBNB.snap | 2 +- ...settler_metaTxn_uniswapV3VIP_DAI-WETH.snap | 2 +- ...ettler_metaTxn_uniswapV3VIP_USDC-USDT.snap | 2 +- ...ettler_metaTxn_uniswapV3VIP_USDC-WETH.snap | 2 +- ...ettler_metaTxn_uniswapV3VIP_USDT-WETH.snap | 2 +- .../settler_metaTxn_uniswapV3_DAI-WETH.snap | 2 +- .../settler_metaTxn_uniswapV3_USDC-USDT.snap | 2 +- .../settler_metaTxn_uniswapV3_USDC-WETH.snap | 2 +- .../settler_metaTxn_uniswapV3_USDT-WETH.snap | 2 +- .../settler_pancakeInfinityVIP_USDT-CAKE.snap | 2 +- .../settler_pancakeInfinityVIP_USDT-WBNB.snap | 2 +- .../settler_pancakeInfinity_USDT-CAKE.snap | 2 +- .../settler_pancakeInfinity_USDT-WBNB.snap | 2 +- ...settler_rfq_fee_full_custody_DAI-USDC.snap | 2 +- ...settler_rfq_fee_full_custody_DAI-WETH.snap | 2 +- ...settler_rfq_fee_full_custody_USDC-DAI.snap | 2 +- ...ettler_rfq_fee_full_custody_USDC-USDS.snap | 2 +- ...ettler_rfq_fee_full_custody_USDC-USDT.snap | 2 +- ...ettler_rfq_fee_full_custody_USDC-WETH.snap | 2 +- ...ettler_rfq_fee_full_custody_USDD-USDT.snap | 2 +- ...ettler_rfq_fee_full_custody_USDS-USDC.snap | 2 +- ...ettler_rfq_fee_full_custody_USDT-CAKE.snap | 2 +- ...ettler_rfq_fee_full_custody_USDT-USDD.snap | 2 +- ...ettler_rfq_fee_full_custody_USDT-WBNB.snap | 2 +- ...ettler_rfq_fee_full_custody_USDT-WETH.snap | 2 +- .../settler_squadSwapV3VIP_USDT-WBNB.snap | 1 + .../settler_uniswapV2_DAI-WETH.snap | 2 +- .../settler_uniswapV2_USDC-WETH.snap | 2 +- .../settler_uniswapV2_USDT-WETH.snap | 2 +- .../settler_uniswapV2_WETH-USDC.snap | 2 +- ...ettler_uniswapV2_fromNative_WETH-USDC.snap | 2 +- .../settler_uniswapV2_multihop_DAI-WETH.snap | 2 +- .../settler_uniswapV2_multihop_USDC-WETH.snap | 2 +- .../settler_uniswapV2_multihop_USDT-WETH.snap | 2 +- ...swapV2_multihop_single_chain_DAI-WETH.snap | 2 +- ...wapV2_multihop_single_chain_USDC-WETH.snap | 2 +- ...wapV2_multihop_single_chain_USDT-WETH.snap | 2 +- ...ttler_uniswapV2_single_chain_DAI-WETH.snap | 2 +- ...tler_uniswapV2_single_chain_USDC-WETH.snap | 2 +- ...tler_uniswapV2_single_chain_USDT-WETH.snap | 2 +- ...tler_uniswapV2_single_chain_WETH-USDC.snap | 2 +- .../settler_uniswapV2_toNative_DAI-WETH.snap | 2 +- .../settler_uniswapV2_toNative_USDC-WETH.snap | 2 +- .../settler_uniswapV2_toNative_USDT-WETH.snap | 2 +- .../settler_uniswapV3VIP_DAI-WETH.snap | 2 +- .../settler_uniswapV3VIP_USDC-USDT.snap | 2 +- .../settler_uniswapV3VIP_USDC-WETH.snap | 2 +- .../settler_uniswapV3VIP_USDT-WETH.snap | 2 +- .../settler_uniswapV3VIP_WETH-USDC.snap | 2 +- ...ettler_uniswapV3VIP_toNative_DAI-WETH.snap | 2 +- ...ttler_uniswapV3VIP_toNative_USDC-WETH.snap | 2 +- ...ttler_uniswapV3VIP_toNative_USDT-WETH.snap | 2 +- .../settler_uniswapV3_DAI-WETH.snap | 2 +- .../settler_uniswapV3_USDC-USDT.snap | 2 +- .../settler_uniswapV3_USDC-WETH.snap | 2 +- .../settler_uniswapV3_USDT-WETH.snap | 2 +- .../settler_uniswapV3_WETH-USDC.snap | 2 +- ...V3_buyToken_fee_full_custody_DAI-WETH.snap | 2 +- ...3_buyToken_fee_full_custody_USDC-USDT.snap | 2 +- ...3_buyToken_fee_full_custody_USDC-WETH.snap | 2 +- ...3_buyToken_fee_full_custody_USDT-WETH.snap | 2 +- ...3_buyToken_fee_full_custody_WETH-USDC.snap | 2 +- ..._buyToken_fee_single_custody_DAI-WETH.snap | 2 +- ...buyToken_fee_single_custody_USDC-USDT.snap | 2 +- ...buyToken_fee_single_custody_USDC-WETH.snap | 2 +- ...buyToken_fee_single_custody_USDT-WETH.snap | 2 +- ...buyToken_fee_single_custody_WETH-USDC.snap | 2 +- ...ettler_uniswapV3_fromNative_WETH-USDC.snap | 2 +- ...settler_uniswapV3_multiplex2_DAI-WETH.snap | 2 +- ...ettler_uniswapV3_multiplex2_USDC-USDT.snap | 2 +- ...ettler_uniswapV3_multiplex2_USDC-WETH.snap | 2 +- ...ettler_uniswapV3_multiplex2_USDT-WETH.snap | 2 +- ...ettler_uniswapV3_multiplex2_WETH-USDC.snap | 2 +- ...3_sellToken_fee_full_custody_DAI-WETH.snap | 2 +- ..._sellToken_fee_full_custody_USDC-USDT.snap | 2 +- ..._sellToken_fee_full_custody_USDC-WETH.snap | 2 +- ..._sellToken_fee_full_custody_USDT-WETH.snap | 2 +- ..._sellToken_fee_full_custody_WETH-USDC.snap | 2 +- ...ettler_uniswapV4VIP_toNative_DAI-WETH.snap | 2 +- ...ttler_uniswapV4VIP_toNative_USDC-WETH.snap | 2 +- ...ttler_uniswapV4VIP_toNative_USDT-WETH.snap | 2 +- ...ettler_uniswapV4_fromNative_WETH-USDC.snap | 2 +- .../settler_velodrome_USDT-USDC.snap | 2 +- .../settler_zeroExOtc_DAI-WETH.snap | 2 +- .../settler_zeroExOtc_USDC-USDT.snap | 2 +- .../settler_zeroExOtc_USDC-WETH.snap | 2 +- .../settler_zeroExOtc_USDT-WETH.snap | 2 +- .../settler_zeroExOtc_WETH-USDC.snap | 2 +- ...ettler_zeroExOtc_partialFill_DAI-WETH.snap | 2 +- ...ttler_zeroExOtc_partialFill_USDC-USDT.snap | 2 +- ...ttler_zeroExOtc_partialFill_USDC-WETH.snap | 2 +- ...ttler_zeroExOtc_partialFill_USDT-WETH.snap | 2 +- ...ttler_zeroExOtc_partialFill_WETH-USDC.snap | 2 +- .forge-snapshots/wethDeposit.snap | 2 +- .forge-snapshots/wethWithdraw.snap | 2 +- ...roEx_curveV2_transformERC20_USDT-WETH.snap | 2 +- ...Ex_uniswapV3_transformERC20_USDT-WETH.snap | 2 +- README.md | 126 +++++++++--------- 188 files changed, 250 insertions(+), 249 deletions(-) create mode 100644 .forge-snapshots/settler_squadSwapV3VIP_USDT-WBNB.snap diff --git a/.forge-snapshots/DAIPermit_transfer-from-with-permit.snap b/.forge-snapshots/DAIPermit_transfer-from-with-permit.snap index 4833d44f8..205275a8b 100644 --- a/.forge-snapshots/DAIPermit_transfer-from-with-permit.snap +++ b/.forge-snapshots/DAIPermit_transfer-from-with-permit.snap @@ -1 +1 @@ -97240 \ No newline at end of file +97493 \ No newline at end of file diff --git a/.forge-snapshots/ERC2612_transfer-from-with-permit.snap b/.forge-snapshots/ERC2612_transfer-from-with-permit.snap index 699d86689..28714e81e 100644 --- a/.forge-snapshots/ERC2612_transfer-from-with-permit.snap +++ b/.forge-snapshots/ERC2612_transfer-from-with-permit.snap @@ -1 +1 @@ -111044 \ No newline at end of file +111283 \ No newline at end of file diff --git a/.forge-snapshots/NativeMetaTransaction_transfer-from-with-permit.snap b/.forge-snapshots/NativeMetaTransaction_transfer-from-with-permit.snap index f959f4ac0..264142c3f 100644 --- a/.forge-snapshots/NativeMetaTransaction_transfer-from-with-permit.snap +++ b/.forge-snapshots/NativeMetaTransaction_transfer-from-with-permit.snap @@ -1 +1 @@ -110042 \ No newline at end of file +110269 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_balancerV3VIP_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_balancerV3VIP_USDC-USDT.snap index a824cee8f..c69c98050 100644 --- a/.forge-snapshots/allowanceHolder_balancerV3VIP_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_balancerV3VIP_USDC-USDT.snap @@ -1 +1 @@ -279341 \ No newline at end of file +279569 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_bebop_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_bebop_USDC-WETH.snap index ffbc2a292..8c209e3db 100644 --- a/.forge-snapshots/allowanceHolder_bebop_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_bebop_USDC-WETH.snap @@ -1 +1 @@ -182690 \ No newline at end of file +182666 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_bebop_WETH-USDC.snap b/.forge-snapshots/allowanceHolder_bebop_WETH-USDC.snap index 35f4d3018..c5161f84d 100644 --- a/.forge-snapshots/allowanceHolder_bebop_WETH-USDC.snap +++ b/.forge-snapshots/allowanceHolder_bebop_WETH-USDC.snap @@ -1 +1 @@ -174959 \ No newline at end of file +174964 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_bebop_partial_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_bebop_partial_USDC-WETH.snap index 8be055721..e4c139dd0 100644 --- a/.forge-snapshots/allowanceHolder_bebop_partial_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_bebop_partial_USDC-WETH.snap @@ -1 +1 @@ -182817 \ No newline at end of file +182793 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_bebop_partial_WETH-USDC.snap b/.forge-snapshots/allowanceHolder_bebop_partial_WETH-USDC.snap index 8fb679bad..86bc331e6 100644 --- a/.forge-snapshots/allowanceHolder_bebop_partial_WETH-USDC.snap +++ b/.forge-snapshots/allowanceHolder_bebop_partial_WETH-USDC.snap @@ -1 +1 @@ -175086 \ No newline at end of file +175091 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_bebop_slippage_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_bebop_slippage_USDC-WETH.snap index 9fd4498ef..601844183 100644 --- a/.forge-snapshots/allowanceHolder_bebop_slippage_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_bebop_slippage_USDC-WETH.snap @@ -1 +1 @@ -182685 \ No newline at end of file +182661 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_bebop_slippage_WETH-USDC.snap b/.forge-snapshots/allowanceHolder_bebop_slippage_WETH-USDC.snap index 6df76e3e9..35f4d3018 100644 --- a/.forge-snapshots/allowanceHolder_bebop_slippage_WETH-USDC.snap +++ b/.forge-snapshots/allowanceHolder_bebop_slippage_WETH-USDC.snap @@ -1 +1 @@ -174954 \ No newline at end of file +174959 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-USDT.snap index 93710623e..073cbed8e 100644 --- a/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-USDT.snap @@ -1 +1 @@ -113732 \ No newline at end of file +113880 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-WETH.snap index 8227a6804..42f32f4c0 100644 --- a/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_ekuboVIP_USDC-WETH.snap @@ -1 +1 @@ -1835539 \ No newline at end of file +1835703 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_DAI-WETH.snap b/.forge-snapshots/allowanceHolder_empty_DAI-WETH.snap index 9eef83b4e..9c2bbe002 100644 --- a/.forge-snapshots/allowanceHolder_empty_DAI-WETH.snap +++ b/.forge-snapshots/allowanceHolder_empty_DAI-WETH.snap @@ -1 +1 @@ -8778 \ No newline at end of file +8975 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_empty_USDC-USDT.snap index 9827fc18c..8633efb3b 100644 --- a/.forge-snapshots/allowanceHolder_empty_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_empty_USDC-USDT.snap @@ -1 +1 @@ -8787 \ No newline at end of file +8984 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_empty_USDC-WETH.snap index 9eef83b4e..9c2bbe002 100644 --- a/.forge-snapshots/allowanceHolder_empty_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_empty_USDC-WETH.snap @@ -1 +1 @@ -8778 \ No newline at end of file +8975 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_USDT-CAKE.snap b/.forge-snapshots/allowanceHolder_empty_USDT-CAKE.snap index 02a6db759..e147f61e1 100644 --- a/.forge-snapshots/allowanceHolder_empty_USDT-CAKE.snap +++ b/.forge-snapshots/allowanceHolder_empty_USDT-CAKE.snap @@ -1 +1 @@ -8781 \ No newline at end of file +8987 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_USDT-WBNB.snap b/.forge-snapshots/allowanceHolder_empty_USDT-WBNB.snap index 02a6db759..e147f61e1 100644 --- a/.forge-snapshots/allowanceHolder_empty_USDT-WBNB.snap +++ b/.forge-snapshots/allowanceHolder_empty_USDT-WBNB.snap @@ -1 +1 @@ -8781 \ No newline at end of file +8987 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_USDT-WETH.snap b/.forge-snapshots/allowanceHolder_empty_USDT-WETH.snap index 9eef83b4e..9c2bbe002 100644 --- a/.forge-snapshots/allowanceHolder_empty_USDT-WETH.snap +++ b/.forge-snapshots/allowanceHolder_empty_USDT-WETH.snap @@ -1 +1 @@ -8778 \ No newline at end of file +8975 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_hanji_usdc_to_wmon.snap b/.forge-snapshots/allowanceHolder_empty_hanji_usdc_to_wmon.snap index 22dac05be..e147f61e1 100644 --- a/.forge-snapshots/allowanceHolder_empty_hanji_usdc_to_wmon.snap +++ b/.forge-snapshots/allowanceHolder_empty_hanji_usdc_to_wmon.snap @@ -1 +1 @@ -8784 \ No newline at end of file +8987 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_empty_hanji_wmon_to_usdc.snap b/.forge-snapshots/allowanceHolder_empty_hanji_wmon_to_usdc.snap index 22dac05be..e147f61e1 100644 --- a/.forge-snapshots/allowanceHolder_empty_hanji_wmon_to_usdc.snap +++ b/.forge-snapshots/allowanceHolder_empty_hanji_wmon_to_usdc.snap @@ -1 +1 @@ -8784 \ No newline at end of file +8987 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-CAKE.snap b/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-CAKE.snap index 1c86764ad..619e621ba 100644 --- a/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-CAKE.snap +++ b/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-CAKE.snap @@ -1 +1 @@ -584864 \ No newline at end of file +585030 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-WBNB.snap b/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-WBNB.snap index 7bc64539c..214edc36f 100644 --- a/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-WBNB.snap +++ b/.forge-snapshots/allowanceHolder_pancakeInfinityVIP_USDT-WBNB.snap @@ -1 +1 @@ -171476 \ No newline at end of file +171654 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_DAI-WETH.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_DAI-WETH.snap index 494c8113f..08a1218ab 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_DAI-WETH.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_DAI-WETH.snap @@ -1 +1 @@ -125264 \ No newline at end of file +125510 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-USDT.snap index 9aa815cf6..80e633163 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-USDT.snap @@ -1 +1 @@ -147264 \ No newline at end of file +147510 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-WETH.snap index 6f1b5a2e3..a8ca3c8ac 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDC-WETH.snap @@ -1 +1 @@ -146725 \ No newline at end of file +146971 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-CAKE.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-CAKE.snap index 41c17e4ce..0f0233b4d 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-CAKE.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-CAKE.snap @@ -1 +1 @@ -135202 \ No newline at end of file +135462 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WBNB.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WBNB.snap index 8220e3cca..e2ca93613 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WBNB.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WBNB.snap @@ -1 +1 @@ -129833 \ No newline at end of file +130093 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WETH.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WETH.snap index 0a2e08279..140fed9de 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WETH.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_USDT-WETH.snap @@ -1 +1 @@ -142008 \ No newline at end of file +142254 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_usdc_to_wmon.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_usdc_to_wmon.snap index 1d8c2c7e1..e40fa3e30 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_usdc_to_wmon.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_usdc_to_wmon.snap @@ -1 +1 @@ -163472 \ No newline at end of file +163747 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_wmon_to_usdc.snap b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_wmon_to_usdc.snap index 6a3d456a3..c1180ea65 100644 --- a/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_wmon_to_usdc.snap +++ b/.forge-snapshots/allowanceHolder_rfq_proportionalFee_sellToken_hanji_wmon_to_usdc.snap @@ -1 +1 @@ -157669 \ No newline at end of file +157944 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_DAI-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_DAI-WETH.snap index b831b72ec..b3a7efbcf 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_DAI-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_DAI-WETH.snap @@ -1 +1 @@ -103510 \ No newline at end of file +103735 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDC-WETH.snap index b51552f6a..da483f56e 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDC-WETH.snap @@ -1 +1 @@ -121015 \ No newline at end of file +121240 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDT-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDT-WETH.snap index 9ae5644ac..b523837b9 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDT-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV2_single_chain_USDT-WETH.snap @@ -1 +1 @@ -115480 \ No newline at end of file +115705 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_DAI-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_DAI-WETH.snap index 9d4c6ba45..98b305ca5 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_DAI-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_DAI-WETH.snap @@ -1 +1 @@ -112825 \ No newline at end of file +113034 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-USDT.snap index d26084518..5f6c60e41 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-USDT.snap @@ -1 +1 @@ -119129 \ No newline at end of file +119338 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-WETH.snap index b8ecebb29..eefc850d5 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDC-WETH.snap @@ -1 +1 @@ -122154 \ No newline at end of file +122363 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDT-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDT-WETH.snap index bd59add52..9170e2c98 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDT-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_USDT-WETH.snap @@ -1 +1 @@ -124350 \ No newline at end of file +124559 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_DAI-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_DAI-WETH.snap index 596a45c0d..56293012f 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_DAI-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_DAI-WETH.snap @@ -1 +1 @@ -112939 \ No newline at end of file +113148 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-USDT.snap index e62743cd6..32add3487 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-USDT.snap @@ -1 +1 @@ -119243 \ No newline at end of file +119452 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-WETH.snap index 16804232f..acfab7e7b 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDC-WETH.snap @@ -1 +1 @@ -122268 \ No newline at end of file +122477 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDT-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDT-WETH.snap index 6cbb8cf08..7fe9327a3 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDT-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3VIP_contract_USDT-WETH.snap @@ -1 +1 @@ -124464 \ No newline at end of file +124673 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3_DAI-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3_DAI-WETH.snap index cd0013729..3912b1da9 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3_DAI-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3_DAI-WETH.snap @@ -1 +1 @@ -139045 \ No newline at end of file +139256 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3_USDC-USDT.snap b/.forge-snapshots/allowanceHolder_uniswapV3_USDC-USDT.snap index 60640978d..0b973bec6 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3_USDC-USDT.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3_USDC-USDT.snap @@ -1 +1 @@ -149405 \ No newline at end of file +149616 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3_USDC-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3_USDC-WETH.snap index a10274778..8c8427254 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3_USDC-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3_USDC-WETH.snap @@ -1 +1 @@ -151089 \ No newline at end of file +151300 \ No newline at end of file diff --git a/.forge-snapshots/allowanceHolder_uniswapV3_USDT-WETH.snap b/.forge-snapshots/allowanceHolder_uniswapV3_USDT-WETH.snap index b1cd61153..4c00c7999 100644 --- a/.forge-snapshots/allowanceHolder_uniswapV3_USDT-WETH.snap +++ b/.forge-snapshots/allowanceHolder_uniswapV3_USDT-WETH.snap @@ -1 +1 @@ -154426 \ No newline at end of file +154637 \ No newline at end of file diff --git a/.forge-snapshots/curveV2Pool_USDT-WETH.snap b/.forge-snapshots/curveV2Pool_USDT-WETH.snap index 538296db6..c6636c688 100644 --- a/.forge-snapshots/curveV2Pool_USDT-WETH.snap +++ b/.forge-snapshots/curveV2Pool_USDT-WETH.snap @@ -1 +1 @@ -289673 \ No newline at end of file +287171 \ No newline at end of file diff --git a/.forge-snapshots/hanji_sellNativeForUsdc_hanji_wmon_to_usdc.snap b/.forge-snapshots/hanji_sellNativeForUsdc_hanji_wmon_to_usdc.snap index 7cdf8fdfe..3f8872a9e 100644 --- a/.forge-snapshots/hanji_sellNativeForUsdc_hanji_wmon_to_usdc.snap +++ b/.forge-snapshots/hanji_sellNativeForUsdc_hanji_wmon_to_usdc.snap @@ -1 +1 @@ -848696 \ No newline at end of file +849064 \ No newline at end of file diff --git a/.forge-snapshots/hanji_sellUsdcForWmon_hanji_usdc_to_wmon.snap b/.forge-snapshots/hanji_sellUsdcForWmon_hanji_usdc_to_wmon.snap index a61e48073..8db401bfd 100644 --- a/.forge-snapshots/hanji_sellUsdcForWmon_hanji_usdc_to_wmon.snap +++ b/.forge-snapshots/hanji_sellUsdcForWmon_hanji_usdc_to_wmon.snap @@ -1 +1 @@ -847802 \ No newline at end of file +847908 \ No newline at end of file diff --git a/.forge-snapshots/hanji_sellWmonForUsdc_hanji_wmon_to_usdc.snap b/.forge-snapshots/hanji_sellWmonForUsdc_hanji_wmon_to_usdc.snap index 795af30ee..a13a2fe11 100644 --- a/.forge-snapshots/hanji_sellWmonForUsdc_hanji_wmon_to_usdc.snap +++ b/.forge-snapshots/hanji_sellWmonForUsdc_hanji_wmon_to_usdc.snap @@ -1 +1 @@ -851155 \ No newline at end of file +851273 \ No newline at end of file diff --git a/.forge-snapshots/settler_balancerV3VIP_USDC-USDT.snap b/.forge-snapshots/settler_balancerV3VIP_USDC-USDT.snap index c36bcbd5c..b0a789cc5 100644 --- a/.forge-snapshots/settler_balancerV3VIP_USDC-USDT.snap +++ b/.forge-snapshots/settler_balancerV3VIP_USDC-USDT.snap @@ -1 +1 @@ -287827 \ No newline at end of file +288054 \ No newline at end of file diff --git a/.forge-snapshots/settler_balancerV3_USDC-USDT.snap b/.forge-snapshots/settler_balancerV3_USDC-USDT.snap index c26c7239b..e41262be1 100644 --- a/.forge-snapshots/settler_balancerV3_USDC-USDT.snap +++ b/.forge-snapshots/settler_balancerV3_USDC-USDT.snap @@ -1 +1 @@ -318276 \ No newline at end of file +318463 \ No newline at end of file diff --git a/.forge-snapshots/settler_basic_curve_USDT-WETH.snap b/.forge-snapshots/settler_basic_curve_USDT-WETH.snap index 80551ca66..4e460b508 100644 --- a/.forge-snapshots/settler_basic_curve_USDT-WETH.snap +++ b/.forge-snapshots/settler_basic_curve_USDT-WETH.snap @@ -1 +1 @@ -366974 \ No newline at end of file +367024 \ No newline at end of file diff --git a/.forge-snapshots/settler_curveV2_fee_USDT-WETH.snap b/.forge-snapshots/settler_curveV2_fee_USDT-WETH.snap index 52c3b6a80..6b6f34cfb 100644 --- a/.forge-snapshots/settler_curveV2_fee_USDT-WETH.snap +++ b/.forge-snapshots/settler_curveV2_fee_USDT-WETH.snap @@ -1 +1 @@ -378106 \ No newline at end of file +378164 \ No newline at end of file diff --git a/.forge-snapshots/settler_dodoV1_USDC-WETH.snap b/.forge-snapshots/settler_dodoV1_USDC-WETH.snap index e05e91f42..60e5586e3 100644 --- a/.forge-snapshots/settler_dodoV1_USDC-WETH.snap +++ b/.forge-snapshots/settler_dodoV1_USDC-WETH.snap @@ -1 +1 @@ -293116 \ No newline at end of file +293194 \ No newline at end of file diff --git a/.forge-snapshots/settler_dodov2_USDT-DAI.snap b/.forge-snapshots/settler_dodov2_USDT-DAI.snap index 4a48fe9aa..124d5c687 100644 --- a/.forge-snapshots/settler_dodov2_USDT-DAI.snap +++ b/.forge-snapshots/settler_dodov2_USDT-DAI.snap @@ -1 +1 @@ -192260 \ No newline at end of file +192489 \ No newline at end of file diff --git a/.forge-snapshots/settler_dodov2_custody_USDT-DAI.snap b/.forge-snapshots/settler_dodov2_custody_USDT-DAI.snap index ec24a8465..feb78d4b5 100644 --- a/.forge-snapshots/settler_dodov2_custody_USDT-DAI.snap +++ b/.forge-snapshots/settler_dodov2_custody_USDT-DAI.snap @@ -1 +1 @@ -161938 \ No newline at end of file +162167 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekuboExtension_USDT-WETH.snap b/.forge-snapshots/settler_ekuboExtension_USDT-WETH.snap index a88edb58e..4f9b14282 100644 --- a/.forge-snapshots/settler_ekuboExtension_USDT-WETH.snap +++ b/.forge-snapshots/settler_ekuboExtension_USDT-WETH.snap @@ -1 +1 @@ -219975 \ No newline at end of file +220121 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekuboV2Extension_USDC-WETH.snap b/.forge-snapshots/settler_ekuboV2Extension_USDC-WETH.snap index ae522425a..65b9d82b6 100644 --- a/.forge-snapshots/settler_ekuboV2Extension_USDC-WETH.snap +++ b/.forge-snapshots/settler_ekuboV2Extension_USDC-WETH.snap @@ -1 +1 @@ -252401 \ No newline at end of file +252125 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekuboV2_USDC-USDT.snap b/.forge-snapshots/settler_ekuboV2_USDC-USDT.snap index 067f8d21d..db78c6cad 100644 --- a/.forge-snapshots/settler_ekuboV2_USDC-USDT.snap +++ b/.forge-snapshots/settler_ekuboV2_USDC-USDT.snap @@ -1 +1 @@ -159973 \ No newline at end of file +159697 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekuboV2_USDC-WETH.snap b/.forge-snapshots/settler_ekuboV2_USDC-WETH.snap index a50ed13b7..323b4ec30 100644 --- a/.forge-snapshots/settler_ekuboV2_USDC-WETH.snap +++ b/.forge-snapshots/settler_ekuboV2_USDC-WETH.snap @@ -1 +1 @@ -197165 \ No newline at end of file +196889 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekuboVIP_USDC-USDT.snap b/.forge-snapshots/settler_ekuboVIP_USDC-USDT.snap index 8facb38fd..f965907ac 100644 --- a/.forge-snapshots/settler_ekuboVIP_USDC-USDT.snap +++ b/.forge-snapshots/settler_ekuboVIP_USDC-USDT.snap @@ -1 +1 @@ -122217 \ No newline at end of file +122364 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekuboVIP_USDC-WETH.snap b/.forge-snapshots/settler_ekuboVIP_USDC-WETH.snap index db4238278..1b0706f2b 100644 --- a/.forge-snapshots/settler_ekuboVIP_USDC-WETH.snap +++ b/.forge-snapshots/settler_ekuboVIP_USDC-WETH.snap @@ -1 +1 @@ -1844359 \ No newline at end of file +1844522 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekubo_USDC-USDT.snap b/.forge-snapshots/settler_ekubo_USDC-USDT.snap index cc8dac6d8..87e1c6b20 100644 --- a/.forge-snapshots/settler_ekubo_USDC-USDT.snap +++ b/.forge-snapshots/settler_ekubo_USDC-USDT.snap @@ -1 +1 @@ -152733 \ No newline at end of file +152863 \ No newline at end of file diff --git a/.forge-snapshots/settler_ekubo_USDC-WETH.snap b/.forge-snapshots/settler_ekubo_USDC-WETH.snap index 708a01b46..8c0d16cd5 100644 --- a/.forge-snapshots/settler_ekubo_USDC-WETH.snap +++ b/.forge-snapshots/settler_ekubo_USDC-WETH.snap @@ -1 +1 @@ -1873536 \ No newline at end of file +1873682 \ No newline at end of file diff --git a/.forge-snapshots/settler_eulerSwapCustody_USDC-USDT.snap b/.forge-snapshots/settler_eulerSwapCustody_USDC-USDT.snap index 546394e92..b50c3f847 100644 --- a/.forge-snapshots/settler_eulerSwapCustody_USDC-USDT.snap +++ b/.forge-snapshots/settler_eulerSwapCustody_USDC-USDT.snap @@ -1 +1 @@ -503126 \ No newline at end of file +503453 \ No newline at end of file diff --git a/.forge-snapshots/settler_eulerSwap_USDC-USDT.snap b/.forge-snapshots/settler_eulerSwap_USDC-USDT.snap index dfa52eb9b..73fe3a0c1 100644 --- a/.forge-snapshots/settler_eulerSwap_USDC-USDT.snap +++ b/.forge-snapshots/settler_eulerSwap_USDC-USDT.snap @@ -1 +1 @@ -532104 \ No newline at end of file +532437 \ No newline at end of file diff --git a/.forge-snapshots/settler_eulerSwap_USDT-USDC.snap b/.forge-snapshots/settler_eulerSwap_USDT-USDC.snap index 4bd36f43a..395813452 100644 --- a/.forge-snapshots/settler_eulerSwap_USDT-USDC.snap +++ b/.forge-snapshots/settler_eulerSwap_USDT-USDC.snap @@ -1 +1 @@ -538713 \ No newline at end of file +539046 \ No newline at end of file diff --git a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_DAI-WETH.snap b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_DAI-WETH.snap index 34ac35324..7c55cd537 100644 --- a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_DAI-WETH.snap +++ b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_DAI-WETH.snap @@ -1 +1 @@ -129043 \ No newline at end of file +129239 \ No newline at end of file diff --git a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-USDT.snap b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-USDT.snap index 70c5c490a..8e767d9a0 100644 --- a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-USDT.snap +++ b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-USDT.snap @@ -1 +1 @@ -133772 \ No newline at end of file +133968 \ No newline at end of file diff --git a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-WETH.snap b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-WETH.snap index 9cf798089..a5cfe9b25 100644 --- a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-WETH.snap +++ b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDC-WETH.snap @@ -1 +1 @@ -135534 \ No newline at end of file +135730 \ No newline at end of file diff --git a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDT-WETH.snap b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDT-WETH.snap index 7181a3eca..c8c85841b 100644 --- a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDT-WETH.snap +++ b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_USDT-WETH.snap @@ -1 +1 @@ -144739 \ No newline at end of file +144935 \ No newline at end of file diff --git a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_WETH-USDC.snap b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_WETH-USDC.snap index 7a846de14..f7e1eab95 100644 --- a/.forge-snapshots/settler_externalMoveExecute_uniswapV3_WETH-USDC.snap +++ b/.forge-snapshots/settler_externalMoveExecute_uniswapV3_WETH-USDC.snap @@ -1 +1 @@ -138669 \ No newline at end of file +138894 \ No newline at end of file diff --git a/.forge-snapshots/settler_makerPsmLite_buyGem_DAI-USDC.snap b/.forge-snapshots/settler_makerPsmLite_buyGem_DAI-USDC.snap index 33e68d888..2187e7f19 100644 --- a/.forge-snapshots/settler_makerPsmLite_buyGem_DAI-USDC.snap +++ b/.forge-snapshots/settler_makerPsmLite_buyGem_DAI-USDC.snap @@ -1 +1 @@ -145674 \ No newline at end of file +145980 \ No newline at end of file diff --git a/.forge-snapshots/settler_makerPsmLite_buyGem_USDD-USDT.snap b/.forge-snapshots/settler_makerPsmLite_buyGem_USDD-USDT.snap index 958f6b393..27597b2a1 100644 --- a/.forge-snapshots/settler_makerPsmLite_buyGem_USDD-USDT.snap +++ b/.forge-snapshots/settler_makerPsmLite_buyGem_USDD-USDT.snap @@ -1 +1 @@ -293496 \ No newline at end of file +293814 \ No newline at end of file diff --git a/.forge-snapshots/settler_makerPsmLite_buyGem_USDS-USDC.snap b/.forge-snapshots/settler_makerPsmLite_buyGem_USDS-USDC.snap index d59fe2319..012e0eb65 100644 --- a/.forge-snapshots/settler_makerPsmLite_buyGem_USDS-USDC.snap +++ b/.forge-snapshots/settler_makerPsmLite_buyGem_USDS-USDC.snap @@ -1 +1 @@ -279229 \ No newline at end of file +279535 \ No newline at end of file diff --git a/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-DAI.snap b/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-DAI.snap index 38d593515..264495286 100644 --- a/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-DAI.snap +++ b/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-DAI.snap @@ -1 +1 @@ -152525 \ No newline at end of file +153313 \ No newline at end of file diff --git a/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-USDS.snap b/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-USDS.snap index 498fbdc84..a347c9d1c 100644 --- a/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-USDS.snap +++ b/.forge-snapshots/settler_makerPsmLite_sellGem_USDC-USDS.snap @@ -1 +1 @@ -285932 \ No newline at end of file +287346 \ No newline at end of file diff --git a/.forge-snapshots/settler_makerPsmLite_sellGem_USDT-USDD.snap b/.forge-snapshots/settler_makerPsmLite_sellGem_USDT-USDD.snap index 82adcd3a2..4ac46a570 100644 --- a/.forge-snapshots/settler_makerPsmLite_sellGem_USDT-USDD.snap +++ b/.forge-snapshots/settler_makerPsmLite_sellGem_USDT-USDD.snap @@ -1 +1 @@ -280608 \ No newline at end of file +280847 \ No newline at end of file diff --git a/.forge-snapshots/settler_maverickV2_USDC-WETH.snap b/.forge-snapshots/settler_maverickV2_USDC-WETH.snap index c250d2cee..1c506bdae 100644 --- a/.forge-snapshots/settler_maverickV2_USDC-WETH.snap +++ b/.forge-snapshots/settler_maverickV2_USDC-WETH.snap @@ -1 +1 @@ -155704 \ No newline at end of file +155611 \ No newline at end of file diff --git a/.forge-snapshots/settler_maverickV2_custody_USDC-WETH.snap b/.forge-snapshots/settler_maverickV2_custody_USDC-WETH.snap index 76e6dfdfb..7a2cd1882 100644 --- a/.forge-snapshots/settler_maverickV2_custody_USDC-WETH.snap +++ b/.forge-snapshots/settler_maverickV2_custody_USDC-WETH.snap @@ -1 +1 @@ -129687 \ No newline at end of file +129591 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_balancerV3_USDC-USDT.snap b/.forge-snapshots/settler_metaTxn_balancerV3_USDC-USDT.snap index 83ee0388e..746eb37e5 100644 --- a/.forge-snapshots/settler_metaTxn_balancerV3_USDC-USDT.snap +++ b/.forge-snapshots/settler_metaTxn_balancerV3_USDC-USDT.snap @@ -1 +1 @@ -292759 \ No newline at end of file +292951 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_ekubo_USDC-USDT.snap b/.forge-snapshots/settler_metaTxn_ekubo_USDC-USDT.snap index 741902e07..bc6671ba1 100644 --- a/.forge-snapshots/settler_metaTxn_ekubo_USDC-USDT.snap +++ b/.forge-snapshots/settler_metaTxn_ekubo_USDC-USDT.snap @@ -1 +1 @@ -127255 \ No newline at end of file +127367 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_ekubo_USDC-WETH.snap b/.forge-snapshots/settler_metaTxn_ekubo_USDC-WETH.snap index 5b8c6b842..6e3ae9c0f 100644 --- a/.forge-snapshots/settler_metaTxn_ekubo_USDC-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_ekubo_USDC-WETH.snap @@ -1 +1 @@ -1849662 \ No newline at end of file +1849800 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_DAI-USDC.snap b/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_DAI-USDC.snap index 0cce3ab4c..40ef586c2 100644 --- a/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_DAI-USDC.snap +++ b/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_DAI-USDC.snap @@ -1 +1 @@ -151430 \ No newline at end of file +151704 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDD-USDT.snap b/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDD-USDT.snap index de8349c8a..89917f11e 100644 --- a/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDD-USDT.snap +++ b/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDD-USDT.snap @@ -1 +1 @@ -299252 \ No newline at end of file +299538 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDS-USDC.snap b/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDS-USDC.snap index 5ea3bf62c..d87c17553 100644 --- a/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDS-USDC.snap +++ b/.forge-snapshots/settler_metaTxn_makerPsmLite_buyGem_USDS-USDC.snap @@ -1 +1 @@ -284985 \ No newline at end of file +285259 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-DAI.snap b/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-DAI.snap index 9534e7491..d9e293e22 100644 --- a/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-DAI.snap +++ b/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-DAI.snap @@ -1 +1 @@ -158285 \ No newline at end of file +159041 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-USDS.snap b/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-USDS.snap index 25ca2192d..65518140e 100644 --- a/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-USDS.snap +++ b/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDC-USDS.snap @@ -1 +1 @@ -291692 \ No newline at end of file +293074 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDT-USDD.snap b/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDT-USDD.snap index 05e221070..b50c0287a 100644 --- a/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDT-USDD.snap +++ b/.forge-snapshots/settler_metaTxn_makerPsmLite_sellGem_USDT-USDD.snap @@ -1 +1 @@ -286368 \ No newline at end of file +286575 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-CAKE.snap b/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-CAKE.snap index 740a09e65..ef23caa9c 100644 --- a/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-CAKE.snap +++ b/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-CAKE.snap @@ -1 +1 @@ -598344 \ No newline at end of file +598543 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-WBNB.snap b/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-WBNB.snap index 75d9309c8..64b4b9c0c 100644 --- a/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-WBNB.snap +++ b/.forge-snapshots/settler_metaTxn_pancakeInfinity_USDT-WBNB.snap @@ -1 +1 @@ -185603 \ No newline at end of file +185828 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_DAI-WETH.snap b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_DAI-WETH.snap index ac7d33e2d..83e7e9902 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_DAI-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_DAI-WETH.snap @@ -1 +1 @@ -125593 \ No newline at end of file +125773 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-USDT.snap b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-USDT.snap index d7207de69..7e1ba4aa3 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-USDT.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-USDT.snap @@ -1 +1 @@ -131902 \ No newline at end of file +132076 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-WETH.snap b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-WETH.snap index 3ab41278d..11024edb8 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDC-WETH.snap @@ -1 +1 @@ -134928 \ No newline at end of file +135102 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDT-WETH.snap b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDT-WETH.snap index 41e4ce681..cc843fdcf 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDT-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3VIP_USDT-WETH.snap @@ -1 +1 @@ -137118 \ No newline at end of file +137298 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3_DAI-WETH.snap b/.forge-snapshots/settler_metaTxn_uniswapV3_DAI-WETH.snap index 5ff767c74..93ff8116f 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3_DAI-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3_DAI-WETH.snap @@ -1 +1 @@ -151743 \ No newline at end of file +151930 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-USDT.snap b/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-USDT.snap index b633b4ba0..968491e26 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-USDT.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-USDT.snap @@ -1 +1 @@ -162109 \ No newline at end of file +162290 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-WETH.snap b/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-WETH.snap index e71d71e71..779824f09 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3_USDC-WETH.snap @@ -1 +1 @@ -163793 \ No newline at end of file +163974 \ No newline at end of file diff --git a/.forge-snapshots/settler_metaTxn_uniswapV3_USDT-WETH.snap b/.forge-snapshots/settler_metaTxn_uniswapV3_USDT-WETH.snap index 072c89786..f6cbbde8b 100644 --- a/.forge-snapshots/settler_metaTxn_uniswapV3_USDT-WETH.snap +++ b/.forge-snapshots/settler_metaTxn_uniswapV3_USDT-WETH.snap @@ -1 +1 @@ -167124 \ No newline at end of file +167311 \ No newline at end of file diff --git a/.forge-snapshots/settler_pancakeInfinityVIP_USDT-CAKE.snap b/.forge-snapshots/settler_pancakeInfinityVIP_USDT-CAKE.snap index f742d18e1..8249207a9 100644 --- a/.forge-snapshots/settler_pancakeInfinityVIP_USDT-CAKE.snap +++ b/.forge-snapshots/settler_pancakeInfinityVIP_USDT-CAKE.snap @@ -1 +1 @@ -593377 \ No newline at end of file +593537 \ No newline at end of file diff --git a/.forge-snapshots/settler_pancakeInfinityVIP_USDT-WBNB.snap b/.forge-snapshots/settler_pancakeInfinityVIP_USDT-WBNB.snap index edeac2163..dcb9e6d6e 100644 --- a/.forge-snapshots/settler_pancakeInfinityVIP_USDT-WBNB.snap +++ b/.forge-snapshots/settler_pancakeInfinityVIP_USDT-WBNB.snap @@ -1 +1 @@ -180325 \ No newline at end of file +180498 \ No newline at end of file diff --git a/.forge-snapshots/settler_pancakeInfinity_USDT-CAKE.snap b/.forge-snapshots/settler_pancakeInfinity_USDT-CAKE.snap index f2a73bdca..55dc926ce 100644 --- a/.forge-snapshots/settler_pancakeInfinity_USDT-CAKE.snap +++ b/.forge-snapshots/settler_pancakeInfinity_USDT-CAKE.snap @@ -1 +1 @@ -619647 \ No newline at end of file +619881 \ No newline at end of file diff --git a/.forge-snapshots/settler_pancakeInfinity_USDT-WBNB.snap b/.forge-snapshots/settler_pancakeInfinity_USDT-WBNB.snap index 85a8bd6fb..0b0e81433 100644 --- a/.forge-snapshots/settler_pancakeInfinity_USDT-WBNB.snap +++ b/.forge-snapshots/settler_pancakeInfinity_USDT-WBNB.snap @@ -1 +1 @@ -206598 \ No newline at end of file +206841 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_DAI-USDC.snap b/.forge-snapshots/settler_rfq_fee_full_custody_DAI-USDC.snap index d78292965..c1a9034b1 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_DAI-USDC.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_DAI-USDC.snap @@ -1 +1 @@ -218899 \ No newline at end of file +219214 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_DAI-WETH.snap b/.forge-snapshots/settler_rfq_fee_full_custody_DAI-WETH.snap index b48c89501..7ac7d5a63 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_DAI-WETH.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_DAI-WETH.snap @@ -1 +1 @@ -156166 \ No newline at end of file +156475 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-DAI.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-DAI.snap index edcd4509c..b40ddd3f5 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-DAI.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-DAI.snap @@ -1 +1 @@ -214843 \ No newline at end of file +215158 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDS.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDS.snap index d1bbc2e68..7f823b5d2 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDS.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDS.snap @@ -1 +1 @@ -215402 \ No newline at end of file +215717 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDT.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDT.snap index 65bb393d6..dc43a88aa 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDT.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-USDT.snap @@ -1 +1 @@ -180302 \ No newline at end of file +180611 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-WETH.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-WETH.snap index 8905d4960..360b16efe 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDC-WETH.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDC-WETH.snap @@ -1 +1 @@ -174941 \ No newline at end of file +175250 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDD-USDT.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDD-USDT.snap index 2a832854a..bac8adffc 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDD-USDT.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDD-USDT.snap @@ -1 +1 @@ -207789 \ No newline at end of file +208104 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDS-USDC.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDS-USDC.snap index 72b7ecb09..5594d1df4 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDS-USDC.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDS-USDC.snap @@ -1 +1 @@ -217778 \ No newline at end of file +218093 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-CAKE.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-CAKE.snap index 5e6a386b3..19cac2ce2 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-CAKE.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-CAKE.snap @@ -1 +1 @@ -166448 \ No newline at end of file +166765 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-USDD.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-USDD.snap index 9f3e1432f..e954efe68 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-USDD.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-USDD.snap @@ -1 +1 @@ -205867 \ No newline at end of file +206182 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WBNB.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WBNB.snap index a196cbedb..d30f152dc 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WBNB.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WBNB.snap @@ -1 +1 @@ -161043 \ No newline at end of file +161360 \ No newline at end of file diff --git a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WETH.snap b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WETH.snap index a03d7e385..8fde3a6f0 100644 --- a/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WETH.snap +++ b/.forge-snapshots/settler_rfq_fee_full_custody_USDT-WETH.snap @@ -1 +1 @@ -171163 \ No newline at end of file +171472 \ No newline at end of file diff --git a/.forge-snapshots/settler_squadSwapV3VIP_USDT-WBNB.snap b/.forge-snapshots/settler_squadSwapV3VIP_USDT-WBNB.snap new file mode 100644 index 000000000..d9a4492cd --- /dev/null +++ b/.forge-snapshots/settler_squadSwapV3VIP_USDT-WBNB.snap @@ -0,0 +1 @@ +620350 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV2_DAI-WETH.snap index aac57da5b..3a91d1b7d 100644 --- a/.forge-snapshots/settler_uniswapV2_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_DAI-WETH.snap @@ -1 +1 @@ -136507 \ No newline at end of file +136732 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV2_USDC-WETH.snap index 2844c054f..c57ab2a2a 100644 --- a/.forge-snapshots/settler_uniswapV2_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_USDC-WETH.snap @@ -1 +1 @@ -155990 \ No newline at end of file +156215 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV2_USDT-WETH.snap index 92d594dd4..5a695e104 100644 --- a/.forge-snapshots/settler_uniswapV2_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_USDT-WETH.snap @@ -1 +1 @@ -151904 \ No newline at end of file +152129 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV2_WETH-USDC.snap index 2fa9d25aa..1bfb01ca1 100644 --- a/.forge-snapshots/settler_uniswapV2_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV2_WETH-USDC.snap @@ -1 +1 @@ -147275 \ No newline at end of file +147500 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_fromNative_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV2_fromNative_WETH-USDC.snap index ced1e812e..2c270ba2b 100644 --- a/.forge-snapshots/settler_uniswapV2_fromNative_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV2_fromNative_WETH-USDC.snap @@ -1 +1 @@ -138845 \ No newline at end of file +139063 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_multihop_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV2_multihop_DAI-WETH.snap index af52d3542..560b58904 100644 --- a/.forge-snapshots/settler_uniswapV2_multihop_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_multihop_DAI-WETH.snap @@ -1 +1 @@ -194903 \ No newline at end of file +195135 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_multihop_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV2_multihop_USDC-WETH.snap index 3e49e457b..0d1fc636e 100644 --- a/.forge-snapshots/settler_uniswapV2_multihop_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_multihop_USDC-WETH.snap @@ -1 +1 @@ -214386 \ No newline at end of file +214618 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_multihop_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV2_multihop_USDT-WETH.snap index 114de5207..b637ac918 100644 --- a/.forge-snapshots/settler_uniswapV2_multihop_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_multihop_USDT-WETH.snap @@ -1 +1 @@ -210300 \ No newline at end of file +210532 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_multihop_single_chain_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV2_multihop_single_chain_DAI-WETH.snap index 89e621df3..993527906 100644 --- a/.forge-snapshots/settler_uniswapV2_multihop_single_chain_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_multihop_single_chain_DAI-WETH.snap @@ -1 +1 @@ -169306 \ No newline at end of file +169538 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDC-WETH.snap index 7fbf35f4d..0e80e666d 100644 --- a/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDC-WETH.snap @@ -1 +1 @@ -186811 \ No newline at end of file +187043 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDT-WETH.snap index 5828d83bc..379f5163d 100644 --- a/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_multihop_single_chain_USDT-WETH.snap @@ -1 +1 @@ -181276 \ No newline at end of file +181508 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_single_chain_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV2_single_chain_DAI-WETH.snap index 7c1d30dfb..0d73c8afc 100644 --- a/.forge-snapshots/settler_uniswapV2_single_chain_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_single_chain_DAI-WETH.snap @@ -1 +1 @@ -110910 \ No newline at end of file +111135 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_single_chain_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV2_single_chain_USDC-WETH.snap index 193afdc37..36623562d 100644 --- a/.forge-snapshots/settler_uniswapV2_single_chain_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_single_chain_USDC-WETH.snap @@ -1 +1 @@ -128415 \ No newline at end of file +128640 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_single_chain_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV2_single_chain_USDT-WETH.snap index e211cb432..aec543b60 100644 --- a/.forge-snapshots/settler_uniswapV2_single_chain_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_single_chain_USDT-WETH.snap @@ -1 +1 @@ -122880 \ No newline at end of file +123105 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_single_chain_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV2_single_chain_WETH-USDC.snap index 70996f518..bd44127dc 100644 --- a/.forge-snapshots/settler_uniswapV2_single_chain_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV2_single_chain_WETH-USDC.snap @@ -1 +1 @@ -121890 \ No newline at end of file +122115 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_toNative_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV2_toNative_DAI-WETH.snap index 4ed1ff9f7..d899a6e4b 100644 --- a/.forge-snapshots/settler_uniswapV2_toNative_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_toNative_DAI-WETH.snap @@ -1 +1 @@ -154855 \ No newline at end of file +155139 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_toNative_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV2_toNative_USDC-WETH.snap index 68bd63543..df8624bb9 100644 --- a/.forge-snapshots/settler_uniswapV2_toNative_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_toNative_USDC-WETH.snap @@ -1 +1 @@ -172360 \ No newline at end of file +172644 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV2_toNative_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV2_toNative_USDT-WETH.snap index 606855d01..9ba5032aa 100644 --- a/.forge-snapshots/settler_uniswapV2_toNative_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV2_toNative_USDT-WETH.snap @@ -1 +1 @@ -166825 \ No newline at end of file +167109 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3VIP_DAI-WETH.snap index a4138a155..9463b024c 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_DAI-WETH.snap @@ -1 +1 @@ -120437 \ No newline at end of file +120646 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_USDC-USDT.snap b/.forge-snapshots/settler_uniswapV3VIP_USDC-USDT.snap index ada585a3f..31d438748 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_USDC-USDT.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_USDC-USDT.snap @@ -1 +1 @@ -126740 \ No newline at end of file +126949 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3VIP_USDC-WETH.snap index 04abe97ed..9e8d7143d 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_USDC-WETH.snap @@ -1 +1 @@ -129766 \ No newline at end of file +129975 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3VIP_USDT-WETH.snap index 89db91012..71b7f01de 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_USDT-WETH.snap @@ -1 +1 @@ -131962 \ No newline at end of file +132171 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3VIP_WETH-USDC.snap index 8174efd37..c35fbfe1b 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_WETH-USDC.snap @@ -1 +1 @@ -130197 \ No newline at end of file +130406 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_toNative_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3VIP_toNative_DAI-WETH.snap index ee6192fbc..bc1f47080 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_toNative_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_toNative_DAI-WETH.snap @@ -1 +1 @@ -164521 \ No newline at end of file +164789 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_toNative_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3VIP_toNative_USDC-WETH.snap index 55326afeb..1e6574557 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_toNative_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_toNative_USDC-WETH.snap @@ -1 +1 @@ -173850 \ No newline at end of file +174118 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3VIP_toNative_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3VIP_toNative_USDT-WETH.snap index 51032d145..48cb03099 100644 --- a/.forge-snapshots/settler_uniswapV3VIP_toNative_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3VIP_toNative_USDT-WETH.snap @@ -1 +1 @@ -176046 \ No newline at end of file +176314 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3_DAI-WETH.snap index 7bdc9af12..ecc6dc509 100644 --- a/.forge-snapshots/settler_uniswapV3_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_DAI-WETH.snap @@ -1 +1 @@ -146654 \ No newline at end of file +146864 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_USDC-USDT.snap b/.forge-snapshots/settler_uniswapV3_USDC-USDT.snap index ced4be6ae..26da52a51 100644 --- a/.forge-snapshots/settler_uniswapV3_USDC-USDT.snap +++ b/.forge-snapshots/settler_uniswapV3_USDC-USDT.snap @@ -1 +1 @@ -157014 \ No newline at end of file +157224 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3_USDC-WETH.snap index 0539dd348..4675e7356 100644 --- a/.forge-snapshots/settler_uniswapV3_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_USDC-WETH.snap @@ -1 +1 @@ -158698 \ No newline at end of file +158908 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3_USDT-WETH.snap index b2bce9cd5..d4e1b2df4 100644 --- a/.forge-snapshots/settler_uniswapV3_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_USDT-WETH.snap @@ -1 +1 @@ -162035 \ No newline at end of file +162245 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3_WETH-USDC.snap index 602496e2c..022ddd705 100644 --- a/.forge-snapshots/settler_uniswapV3_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3_WETH-USDC.snap @@ -1 +1 @@ -156128 \ No newline at end of file +156338 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_DAI-WETH.snap index 92b9a5964..d40b0138c 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_DAI-WETH.snap @@ -1 +1 @@ -184119 \ No newline at end of file +184380 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-USDT.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-USDT.snap index 03b8ceef5..7e0e3d24f 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-USDT.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-USDT.snap @@ -1 +1 @@ -200671 \ No newline at end of file +200932 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-WETH.snap index 8bdcd6476..d3e27078d 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDC-WETH.snap @@ -1 +1 @@ -196192 \ No newline at end of file +196453 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDT-WETH.snap index 9009031f5..bf8070b52 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_USDT-WETH.snap @@ -1 +1 @@ -199529 \ No newline at end of file +199790 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_WETH-USDC.snap index edfac4a2b..3d14283f8 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_full_custody_WETH-USDC.snap @@ -1 +1 @@ -199583 \ No newline at end of file +199844 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_DAI-WETH.snap index b4bdc6d57..08ac50bdb 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_DAI-WETH.snap @@ -1 +1 @@ -158043 \ No newline at end of file +158303 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-USDT.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-USDT.snap index bdb484785..f38e70759 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-USDT.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-USDT.snap @@ -1 +1 @@ -170538 \ No newline at end of file +170798 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-WETH.snap index ba5d574e5..51be611fe 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDC-WETH.snap @@ -1 +1 @@ -167401 \ No newline at end of file +167661 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDT-WETH.snap index 4aa788c3d..bd62605ed 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_USDT-WETH.snap @@ -1 +1 @@ -169597 \ No newline at end of file +169857 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_WETH-USDC.snap index 293122d51..1bbedff29 100644 --- a/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3_buyToken_fee_single_custody_WETH-USDC.snap @@ -1 +1 @@ -173787 \ No newline at end of file +174047 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_fromNative_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3_fromNative_WETH-USDC.snap index 60ffe0728..b065664d6 100644 --- a/.forge-snapshots/settler_uniswapV3_fromNative_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3_fromNative_WETH-USDC.snap @@ -1 +1 @@ -147734 \ No newline at end of file +147938 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_multiplex2_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3_multiplex2_DAI-WETH.snap index b13886ef6..a56fd9a5d 100644 --- a/.forge-snapshots/settler_uniswapV3_multiplex2_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_multiplex2_DAI-WETH.snap @@ -1 +1 @@ -179060 \ No newline at end of file +179262 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-USDT.snap b/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-USDT.snap index 6c0425463..a6712db0f 100644 --- a/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-USDT.snap +++ b/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-USDT.snap @@ -1 +1 @@ -194069 \ No newline at end of file +194271 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-WETH.snap index f17d56d89..3b79c8b2a 100644 --- a/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_multiplex2_USDC-WETH.snap @@ -1 +1 @@ -195789 \ No newline at end of file +195991 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_multiplex2_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3_multiplex2_USDT-WETH.snap index 13d343c79..c68a4ca6d 100644 --- a/.forge-snapshots/settler_uniswapV3_multiplex2_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_multiplex2_USDT-WETH.snap @@ -1 +1 @@ -196720 \ No newline at end of file +196922 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_multiplex2_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3_multiplex2_WETH-USDC.snap index 6777f12b3..6fdb7637e 100644 --- a/.forge-snapshots/settler_uniswapV3_multiplex2_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3_multiplex2_WETH-USDC.snap @@ -1 +1 @@ -189897 \ No newline at end of file +190099 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_DAI-WETH.snap index 85228e967..1f0ee5431 100644 --- a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_DAI-WETH.snap @@ -1 +1 @@ -158055 \ No newline at end of file +158273 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-USDT.snap b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-USDT.snap index fb2dbbd3e..61c14fec2 100644 --- a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-USDT.snap +++ b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-USDT.snap @@ -1 +1 @@ -172471 \ No newline at end of file +172689 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-WETH.snap index ce4847abf..dab9f4e5a 100644 --- a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDC-WETH.snap @@ -1 +1 @@ -172814 \ No newline at end of file +173032 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDT-WETH.snap index 4710f452f..b01d458c7 100644 --- a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_USDT-WETH.snap @@ -1 +1 @@ -175212 \ No newline at end of file +175430 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_WETH-USDC.snap index 44642ba4b..d22e0c02f 100644 --- a/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV3_sellToken_fee_full_custody_WETH-USDC.snap @@ -1 +1 @@ -167249 \ No newline at end of file +167467 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV4VIP_toNative_DAI-WETH.snap b/.forge-snapshots/settler_uniswapV4VIP_toNative_DAI-WETH.snap index ac5956c43..112d4a20e 100644 --- a/.forge-snapshots/settler_uniswapV4VIP_toNative_DAI-WETH.snap +++ b/.forge-snapshots/settler_uniswapV4VIP_toNative_DAI-WETH.snap @@ -1 +1 @@ -117806 \ No newline at end of file +118029 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV4VIP_toNative_USDC-WETH.snap b/.forge-snapshots/settler_uniswapV4VIP_toNative_USDC-WETH.snap index 69ea08eb4..193b1f2c6 100644 --- a/.forge-snapshots/settler_uniswapV4VIP_toNative_USDC-WETH.snap +++ b/.forge-snapshots/settler_uniswapV4VIP_toNative_USDC-WETH.snap @@ -1 +1 @@ -135139 \ No newline at end of file +135362 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV4VIP_toNative_USDT-WETH.snap b/.forge-snapshots/settler_uniswapV4VIP_toNative_USDT-WETH.snap index 3b41ed50a..75b82d5a5 100644 --- a/.forge-snapshots/settler_uniswapV4VIP_toNative_USDT-WETH.snap +++ b/.forge-snapshots/settler_uniswapV4VIP_toNative_USDT-WETH.snap @@ -1 +1 @@ -129536 \ No newline at end of file +129759 \ No newline at end of file diff --git a/.forge-snapshots/settler_uniswapV4_fromNative_WETH-USDC.snap b/.forge-snapshots/settler_uniswapV4_fromNative_WETH-USDC.snap index cac1e1251..c9e1326f9 100644 --- a/.forge-snapshots/settler_uniswapV4_fromNative_WETH-USDC.snap +++ b/.forge-snapshots/settler_uniswapV4_fromNative_WETH-USDC.snap @@ -1 +1 @@ -106904 \ No newline at end of file +107136 \ No newline at end of file diff --git a/.forge-snapshots/settler_velodrome_USDT-USDC.snap b/.forge-snapshots/settler_velodrome_USDT-USDC.snap index 94f5b957e..ea2309a41 100644 --- a/.forge-snapshots/settler_velodrome_USDT-USDC.snap +++ b/.forge-snapshots/settler_velodrome_USDT-USDC.snap @@ -1 +1 @@ -283967 \ No newline at end of file +284225 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_DAI-WETH.snap b/.forge-snapshots/settler_zeroExOtc_DAI-WETH.snap index eed2d878f..3f4ff669b 100644 --- a/.forge-snapshots/settler_zeroExOtc_DAI-WETH.snap +++ b/.forge-snapshots/settler_zeroExOtc_DAI-WETH.snap @@ -1 +1 @@ -173092 \ No newline at end of file +173162 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_USDC-USDT.snap b/.forge-snapshots/settler_zeroExOtc_USDC-USDT.snap index e4af85d79..6e9bcbd48 100644 --- a/.forge-snapshots/settler_zeroExOtc_USDC-USDT.snap +++ b/.forge-snapshots/settler_zeroExOtc_USDC-USDT.snap @@ -1 +1 @@ -201552 \ No newline at end of file +201622 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_USDC-WETH.snap b/.forge-snapshots/settler_zeroExOtc_USDC-WETH.snap index 04f2bac2d..e17a29ad2 100644 --- a/.forge-snapshots/settler_zeroExOtc_USDC-WETH.snap +++ b/.forge-snapshots/settler_zeroExOtc_USDC-WETH.snap @@ -1 +1 @@ -198162 \ No newline at end of file +198232 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_USDT-WETH.snap b/.forge-snapshots/settler_zeroExOtc_USDT-WETH.snap index e48b21c05..3b389fc87 100644 --- a/.forge-snapshots/settler_zeroExOtc_USDT-WETH.snap +++ b/.forge-snapshots/settler_zeroExOtc_USDT-WETH.snap @@ -1 +1 @@ -188424 \ No newline at end of file +188494 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_WETH-USDC.snap b/.forge-snapshots/settler_zeroExOtc_WETH-USDC.snap index b25f72337..647298c76 100644 --- a/.forge-snapshots/settler_zeroExOtc_WETH-USDC.snap +++ b/.forge-snapshots/settler_zeroExOtc_WETH-USDC.snap @@ -1 +1 @@ -191717 \ No newline at end of file +191787 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_partialFill_DAI-WETH.snap b/.forge-snapshots/settler_zeroExOtc_partialFill_DAI-WETH.snap index e8102f5b2..ed9ba46b4 100644 --- a/.forge-snapshots/settler_zeroExOtc_partialFill_DAI-WETH.snap +++ b/.forge-snapshots/settler_zeroExOtc_partialFill_DAI-WETH.snap @@ -1 +1 @@ -180067 \ No newline at end of file +180145 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-USDT.snap b/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-USDT.snap index 600995151..8daeafc98 100644 --- a/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-USDT.snap +++ b/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-USDT.snap @@ -1 +1 @@ -210583 \ No newline at end of file +210661 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-WETH.snap b/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-WETH.snap index 98a2ac052..54af1e4e3 100644 --- a/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-WETH.snap +++ b/.forge-snapshots/settler_zeroExOtc_partialFill_USDC-WETH.snap @@ -1 +1 @@ -207852 \ No newline at end of file +207930 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_partialFill_USDT-WETH.snap b/.forge-snapshots/settler_zeroExOtc_partialFill_USDT-WETH.snap index 7eeecde56..613df9708 100644 --- a/.forge-snapshots/settler_zeroExOtc_partialFill_USDT-WETH.snap +++ b/.forge-snapshots/settler_zeroExOtc_partialFill_USDT-WETH.snap @@ -1 +1 @@ -197175 \ No newline at end of file +197253 \ No newline at end of file diff --git a/.forge-snapshots/settler_zeroExOtc_partialFill_WETH-USDC.snap b/.forge-snapshots/settler_zeroExOtc_partialFill_WETH-USDC.snap index 46a14586d..404c1dcaf 100644 --- a/.forge-snapshots/settler_zeroExOtc_partialFill_WETH-USDC.snap +++ b/.forge-snapshots/settler_zeroExOtc_partialFill_WETH-USDC.snap @@ -1 +1 @@ -198412 \ No newline at end of file +198490 \ No newline at end of file diff --git a/.forge-snapshots/wethDeposit.snap b/.forge-snapshots/wethDeposit.snap index cc91b3198..5d898ecf1 100644 --- a/.forge-snapshots/wethDeposit.snap +++ b/.forge-snapshots/wethDeposit.snap @@ -1 +1 @@ -63245 \ No newline at end of file +63519 \ No newline at end of file diff --git a/.forge-snapshots/wethWithdraw.snap b/.forge-snapshots/wethWithdraw.snap index 84760a881..b92addfdb 100644 --- a/.forge-snapshots/wethWithdraw.snap +++ b/.forge-snapshots/wethWithdraw.snap @@ -1 +1 @@ -24027 \ No newline at end of file +24289 \ No newline at end of file diff --git a/.forge-snapshots/zeroEx_curveV2_transformERC20_USDT-WETH.snap b/.forge-snapshots/zeroEx_curveV2_transformERC20_USDT-WETH.snap index 63db608c9..4f920bb1e 100644 --- a/.forge-snapshots/zeroEx_curveV2_transformERC20_USDT-WETH.snap +++ b/.forge-snapshots/zeroEx_curveV2_transformERC20_USDT-WETH.snap @@ -1 +1 @@ -404143 \ No newline at end of file +404148 \ No newline at end of file diff --git a/.forge-snapshots/zeroEx_uniswapV3_transformERC20_USDT-WETH.snap b/.forge-snapshots/zeroEx_uniswapV3_transformERC20_USDT-WETH.snap index 748b13069..d3e9fe635 100644 --- a/.forge-snapshots/zeroEx_uniswapV3_transformERC20_USDT-WETH.snap +++ b/.forge-snapshots/zeroEx_uniswapV3_transformERC20_USDT-WETH.snap @@ -1 +1 @@ -237174 \ No newline at end of file +237179 \ No newline at end of file diff --git a/README.md b/README.md index a28d2a818..f88aa9d91 100644 --- a/README.md +++ b/README.md @@ -618,53 +618,53 @@ comparison. | ------------------- | ---------- | --------- | ------ | ------ | | 0x V4 VIP | Uniswap V3 | USDC/WETH | 121309 | 0.00% | | 0x V4 Multiplex | Uniswap V3 | USDC/WETH | 135211 | 11.46% | -| Settler VIP (warm) | Uniswap V3 | USDC/WETH | 129558 | 6.80% | -| AllowanceHolder VIP | Uniswap V3 | USDC/WETH | 121966 | 0.54% | +| Settler VIP (warm) | Uniswap V3 | USDC/WETH | 129975 | 7.14% | +| AllowanceHolder VIP | Uniswap V3 | USDC/WETH | 122363 | 0.87% | | UniswapRouter V3 | Uniswap V3 | USDC/WETH | 117706 | -2.97% | | | | | | | | 0x V4 VIP | Uniswap V3 | DAI/WETH | 111980 | 0.00% | | 0x V4 Multiplex | Uniswap V3 | DAI/WETH | 125853 | 12.39% | -| Settler VIP (warm) | Uniswap V3 | DAI/WETH | 120229 | 7.37% | -| AllowanceHolder VIP | Uniswap V3 | DAI/WETH | 112637 | 0.59% | +| Settler VIP (warm) | Uniswap V3 | DAI/WETH | 120646 | 7.74% | +| AllowanceHolder VIP | Uniswap V3 | DAI/WETH | 113034 | 0.94% | | UniswapRouter V3 | Uniswap V3 | DAI/WETH | 108377 | -3.22% | | | | | | | | 0x V4 VIP | Uniswap V3 | USDT/WETH | 123571 | 0.00% | -| 0x V4 Multiplex | Uniswap V3 | USDT/WETH | 137444 | 11.23% | -| Settler VIP (warm) | Uniswap V3 | USDT/WETH | 131754 | 6.62% | -| AllowanceHolder VIP | Uniswap V3 | USDT/WETH | 124162 | 0.48% | +| 0x V4 Multiplex | Uniswap V3 | USDT/WETH | 137473 | 11.25% | +| Settler VIP (warm) | Uniswap V3 | USDT/WETH | 132171 | 6.96% | +| AllowanceHolder VIP | Uniswap V3 | USDT/WETH | 124559 | 0.80% | | UniswapRouter V3 | Uniswap V3 | USDT/WETH | 119840 | -3.02% | | | | | | | -| Settler VIP (warm) | Uniswap V3 | WETH/USDC | 129989 | NaN% | +| Settler VIP (warm) | Uniswap V3 | WETH/USDC | 130406 | NaN% | | UniswapRouter V3 | Uniswap V3 | WETH/USDC | 118192 | NaN% | | | | | | | | Custody | DEX | Pair | Gas | % | | -------------------- | ---------- | --------- | ------ | ------- | | 0x V4 TransformERC20 | Uniswap V3 | USDC/WETH | 239864 | 0.00% | -| Settler | Uniswap V3 | USDC/WETH | 158503 | -33.92% | -| AllowanceHolder | Uniswap V3 | USDC/WETH | 150914 | -37.08% | +| Settler | Uniswap V3 | USDC/WETH | 158908 | -33.75% | +| AllowanceHolder | Uniswap V3 | USDC/WETH | 151300 | -36.92% | | | | | | | | 0x V4 TransformERC20 | Uniswap V3 | DAI/WETH | 221467 | 0.00% | -| Settler | Uniswap V3 | DAI/WETH | 146459 | -33.87% | -| AllowanceHolder | Uniswap V3 | DAI/WETH | 138870 | -37.30% | +| Settler | Uniswap V3 | DAI/WETH | 146864 | -33.69% | +| AllowanceHolder | Uniswap V3 | DAI/WETH | 139256 | -37.12% | | | | | | | -| 0x V4 TransformERC20 | Uniswap V3 | USDT/WETH | 237150 | 0.00% | -| Settler | Uniswap V3 | USDT/WETH | 161840 | -31.76% | -| AllowanceHolder | Uniswap V3 | USDT/WETH | 154251 | -34.96% | +| 0x V4 TransformERC20 | Uniswap V3 | USDT/WETH | 237179 | 0.00% | +| Settler | Uniswap V3 | USDT/WETH | 162245 | -31.59% | +| AllowanceHolder | Uniswap V3 | USDT/WETH | 154637 | -34.80% | | | | | | | -| Settler | Uniswap V3 | WETH/USDC | 155933 | NaN% | +| Settler | Uniswap V3 | WETH/USDC | 156338 | NaN% | | | | | | | | MetaTransactions | DEX | Pair | Gas | % | | ---------------- | ---------- | --------- | ------ | ------- | | 0x V4 Multiplex | Uniswap V3 | USDC/WETH | 204706 | 0.00% | -| Settler | Uniswap V3 | USDC/WETH | 163807 | -19.98% | +| Settler | Uniswap V3 | USDC/WETH | 163974 | -19.90% | | | | | | | | 0x V4 Multiplex | Uniswap V3 | DAI/WETH | 195377 | 0.00% | -| Settler | Uniswap V3 | DAI/WETH | 151757 | -22.33% | +| Settler | Uniswap V3 | DAI/WETH | 151930 | -22.24% | | | | | | | | 0x V4 Multiplex | Uniswap V3 | USDT/WETH | 206968 | 0.00% | -| Settler | Uniswap V3 | USDT/WETH | 167138 | -19.24% | +| Settler | Uniswap V3 | USDT/WETH | 167311 | -19.16% | | | | | | | | | | | | | @@ -672,51 +672,51 @@ comparison. | --------------- | ------- | --------- | ------ | ------- | | 0x V4 | 0x V4 | USDC/WETH | 111684 | 0.00% | | Settler | Settler | USDC/WETH | 114418 | 2.45% | -| Settler | 0x V4 | USDC/WETH | 197968 | 77.26% | +| Settler | 0x V4 | USDC/WETH | 198232 | 77.49% | | AllowanceHolder | Settler | USDC/WETH | 106575 | -4.57% | | | | | | | | 0x V4 | 0x V4 | DAI/WETH | 78553 | 0.00% | | Settler | Settler | DAI/WETH | 94944 | 20.87% | -| Settler | 0x V4 | DAI/WETH | 172898 | 120.10% | +| Settler | 0x V4 | DAI/WETH | 173162 | 120.44% | | AllowanceHolder | Settler | DAI/WETH | 87101 | 10.88% | | | | | | | | 0x V4 | 0x V4 | USDT/WETH | 89665 | 0.00% | | Settler | Settler | USDT/WETH | 106056 | 18.28% | -| Settler | 0x V4 | USDT/WETH | 188230 | 109.93% | +| Settler | 0x V4 | USDT/WETH | 188494 | 110.22% | | AllowanceHolder | Settler | USDT/WETH | 98213 | 9.53% | | | | | | | -| Settler | 0x V4 | WETH/USDC | 191523 | NaN% | +| Settler | 0x V4 | WETH/USDC | 191787 | NaN% | | | | | | | | UniversalRouter | DEX | Pair | Gas | % | | --------------- | --------- | --------- | ------ | ------- | | UniversalRouter | UniswapV2 | USDC/WETH | 181544 | 0.00% | -| Settler | UniswapV2 | USDC/WETH | 172179 | -5.16% | +| Settler | UniswapV2 | USDC/WETH | 172644 | -4.90% | | UniversalRouter | UniswapV3 | USDC/WETH | 177838 | -2.04% | -| Settler | UniswapV3 | USDC/WETH | 173600 | -4.38% | +| Settler | UniswapV3 | USDC/WETH | 174118 | -4.09% | | UniversalRouter | UniswapV4 | USDC/WETH | 142787 | -21.35% | -| Settler | UniswapV4 | USDC/WETH | 134918 | -25.68% | +| Settler | UniswapV4 | USDC/WETH | 135362 | -25.44% | | | | | | | | UniversalRouter | UniswapV2 | DAI/WETH | 164039 | 0.00% | -| Settler | UniswapV2 | DAI/WETH | 154674 | -5.71% | +| Settler | UniswapV2 | DAI/WETH | 155139 | -5.43% | | UniversalRouter | UniswapV3 | DAI/WETH | 168508 | 2.72% | -| Settler | UniswapV3 | DAI/WETH | 164271 | 0.14% | +| Settler | UniswapV3 | DAI/WETH | 164789 | 0.46% | | UniversalRouter | UniswapV4 | DAI/WETH | 125454 | -23.52% | -| Settler | UniswapV4 | DAI/WETH | 117585 | -28.32% | +| Settler | UniswapV4 | DAI/WETH | 118029 | -28.05% | | | | | | | | UniversalRouter | UniswapV2 | USDT/WETH | 176035 | 0.00% | -| Settler | UniswapV2 | USDT/WETH | 166644 | -5.33% | +| Settler | UniswapV2 | USDT/WETH | 167109 | -5.07% | | UniversalRouter | UniswapV3 | USDT/WETH | 180131 | 2.33% | -| Settler | UniswapV3 | USDT/WETH | 175796 | -0.14% | +| Settler | UniswapV3 | USDT/WETH | 176314 | 0.16% | | UniversalRouter | UniswapV4 | USDT/WETH | 137184 | -22.07% | -| Settler | UniswapV4 | USDT/WETH | 129315 | -26.54% | +| Settler | UniswapV4 | USDT/WETH | 129759 | -26.29% | | | | | | | | UniversalRouter | UniswapV2 | WETH/USDC | 145094 | 0.00% | -| Settler | UniswapV2 | WETH/USDC | 138711 | -4.40% | +| Settler | UniswapV2 | WETH/USDC | 139063 | -4.16% | | UniversalRouter | UniswapV3 | WETH/USDC | 147774 | 1.85% | -| Settler | UniswapV3 | WETH/USDC | 147544 | 1.69% | +| Settler | UniswapV3 | WETH/USDC | 147938 | 1.96% | | UniversalRouter | UniswapV4 | WETH/USDC | 109943 | -24.23% | -| Settler | UniswapV4 | WETH/USDC | 106701 | -26.46% | +| Settler | UniswapV4 | WETH/USDC | 107136 | -26.16% | | | | | | | | Curve | DEX | Pair | Gas | % | @@ -724,17 +724,17 @@ comparison. | Settler | CurveV2 Tricrypto VIP | USDC/WETH | 231504 | NaN% | | | | | | | | | | | | | -| 0x V4 | Curve | USDT/WETH | 400453 | 0.00% | -| Settler | Curve | USDT/WETH | 366751 | -8.42% | -| Settler | CurveV2 Tricrypto VIP | USDT/WETH | 243871 | -39.10% | -| Curve | Curve | USDT/WETH | 289673 | -27.66% | -| Curve Swap Router | Curve | USDT/WETH | 359811 | -10.15% | +| 0x V4 | Curve | USDT/WETH | 400482 | 0.00% | +| Settler | Curve | USDT/WETH | 367024 | -8.35% | +| Settler | CurveV2 Tricrypto VIP | USDT/WETH | 243871 | -39.11% | +| Curve | Curve | USDT/WETH | 287171 | -28.29% | +| Curve Swap Router | Curve | USDT/WETH | 359811 | -10.16% | | | | | | | | | | | | | | DODO V1 | DEX | Pair | Gas | % | | ------- | ------- | --------- | ------ | ----- | -| Settler | DODO V1 | USDC/WETH | 292803 | 0.00% | +| Settler | DODO V1 | USDC/WETH | 293194 | 0.00% | | | | | | | | | | | | | | | | | | | @@ -742,56 +742,56 @@ comparison. | Buy token fee | DEX | Pair | Gas | % | | ----------------- | ---------- | --------- | ------ | ----- | -| Settler - custody | Uniswap V3 | USDC/WETH | 167146 | 0.00% | +| Settler - custody | Uniswap V3 | USDC/WETH | 167661 | 0.00% | | | | | | | -| Settler - custody | Uniswap V3 | DAI/WETH | 157788 | 0.00% | +| Settler - custody | Uniswap V3 | DAI/WETH | 158303 | 0.00% | | | | | | | -| Settler - custody | Uniswap V3 | USDT/WETH | 169313 | 0.00% | +| Settler - custody | Uniswap V3 | USDT/WETH | 169857 | 0.00% | | | | | | | -| Settler - custody | Uniswap V3 | WETH/USDC | 173532 | 0.00% | +| Settler - custody | Uniswap V3 | WETH/USDC | 174047 | 0.00% | | | | | | | | Sell token fee | DEX | Pair | Gas | % | | -------------- | ---------- | --------- | ------ | ------- | -| Settler | Uniswap V3 | USDC/WETH | 172572 | 0.00% | +| Settler | Uniswap V3 | USDC/WETH | 173032 | 0.00% | | | | | | | -| Settler | Uniswap V3 | DAI/WETH | 157813 | 0.00% | +| Settler | Uniswap V3 | DAI/WETH | 158273 | 0.00% | | | | | | | -| Settler | Uniswap V3 | USDT/WETH | 174970 | 0.00% | -| Settler | Curve | USDT/WETH | 377836 | 115.94% | +| Settler | Uniswap V3 | USDT/WETH | 175430 | 0.00% | +| Settler | Curve | USDT/WETH | 378164 | 115.56% | | | | | | | -| Settler | Uniswap V3 | WETH/USDC | 167007 | 0.00% | +| Settler | Uniswap V3 | WETH/USDC | 167467 | 0.00% | | | | | | | | AllowanceHolder | DEX | Pair | Gas | % | | ------------------------------------ | -------------- | --------- | ------ | ------- | -| execute | Uniswap V3 VIP | USDC/WETH | 121966 | 0.00% | -| Settler - external move then execute | Uniswap V3 | USDC/WETH | 135342 | 10.97% | -| execute | RFQ | USDC/WETH | 106575 | -12.62% | +| execute | Uniswap V3 VIP | USDC/WETH | 122363 | 0.00% | +| Settler - external move then execute | Uniswap V3 | USDC/WETH | 135730 | 10.92% | +| execute | RFQ | USDC/WETH | 106575 | -12.90% | | | | | | | -| execute | Uniswap V3 VIP | DAI/WETH | 112637 | 0.00% | -| Settler - external move then execute | Uniswap V3 | DAI/WETH | 128851 | 14.39% | -| execute | RFQ | DAI/WETH | 87101 | -22.67% | +| execute | Uniswap V3 VIP | DAI/WETH | 113034 | 0.00% | +| Settler - external move then execute | Uniswap V3 | DAI/WETH | 129239 | 14.34% | +| execute | RFQ | DAI/WETH | 87101 | -22.94% | | | | | | | -| execute | Uniswap V3 VIP | USDT/WETH | 124162 | 0.00% | -| Settler - external move then execute | Uniswap V3 | USDT/WETH | 144547 | 16.42% | -| execute | RFQ | USDT/WETH | 98213 | -20.90% | +| execute | Uniswap V3 VIP | USDT/WETH | 124559 | 0.00% | +| Settler - external move then execute | Uniswap V3 | USDT/WETH | 144935 | 16.36% | +| execute | RFQ | USDT/WETH | 98213 | -21.15% | | | | | | | -| Settler - external move then execute | Uniswap V3 | WETH/USDC | 138477 | NaN% | +| Settler - external move then execute | Uniswap V3 | WETH/USDC | 138894 | NaN% | | | | | | | | AllowanceHolder sell token fees | DEX | Pair | Gas | % | | ------------------------------- | --- | --------- | ------ | ------ | | no fee | RFQ | USDC/WETH | 106575 | 0.00% | -| proportional fee | RFQ | USDC/WETH | 146678 | 37.63% | +| proportional fee | RFQ | USDC/WETH | 146971 | 37.90% | | fixed fee | RFQ | USDC/WETH | 122824 | 15.25% | | | | | | | | no fee | RFQ | DAI/WETH | 87101 | 0.00% | -| proportional fee | RFQ | DAI/WETH | 125217 | 43.76% | +| proportional fee | RFQ | DAI/WETH | 125510 | 44.10% | | fixed fee | RFQ | DAI/WETH | 99176 | 13.86% | | | | | | | | no fee | RFQ | USDT/WETH | 98213 | 0.00% | -| proportional fee | RFQ | USDT/WETH | 141961 | 44.54% | +| proportional fee | RFQ | USDT/WETH | 142254 | 44.84% | | fixed fee | RFQ | USDT/WETH | 111400 | 13.43% | | | | | | | | | | | | | From 626583596e7bc7a7a932b94533043f33a324734a Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 26 Jun 2026 14:46:10 +0200 Subject: [PATCH 049/107] Add EkuboV3 actions on RobinHood chain --- CHANGELOG.md | 1 + src/chains/RobinHood/Common.sol | 16 +++++++++++++--- src/chains/RobinHood/MetaTxn.sol | 14 +++++++++++--- src/chains/RobinHood/TakerSubmitted.sol | 13 +++++++++++-- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbe9b5549..72d88f054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Add UniswapV3 UniV3 fork on RobinHood chain * Add UniswapV4 actions to RobinHood chain +* Add EkuboV3 actions on RobinHood chain ## 2026-06-03 diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index af0b8ade1..bfaa11fec 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -7,6 +7,7 @@ import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {FreeMemory} from "../../utils/FreeMemory.sol"; import {UniswapV4} from "../../core/UniswapV4.sol"; import {IPoolManager} from "../../core/UniswapV4Types.sol"; +import {EkuboV3} from "../../core/EkuboV3.sol"; import {ISettlerActions} from "../../ISettlerActions.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; @@ -20,11 +21,15 @@ import { } from "../../core/univ3forks/UniswapV3.sol"; import {ROBINHOOD_POOL_MANAGER} from "../../core/UniswapV4Addresses.sol"; +import {FastLogic} from "../../utils/FastLogic.sol"; + // Solidity inheritance is stupid import {SettlerSwapAbstract} from "../../SettlerAbstract.sol"; import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; -abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4 { +abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3 { + using FastLogic for bool; + constructor() { assert(block.chainid == 4663 || block.chainid == 31337); } @@ -38,7 +43,8 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4 { { if (super._dispatch(i, action, data, slippage)) { return true; - } else if (action == uint32(ISettlerActions.UNISWAPV4.selector)) { + } else if ((action == uint32(ISettlerActions.UNISWAPV4.selector)) + .or(action == uint32(ISettlerActions.EKUBOV3.selector))) { ( address recipient, IERC20 sellToken, @@ -50,7 +56,11 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4 { uint256 amountOutMin ) = abi.decode(data, (address, IERC20, uint256, bool, uint256, uint256, bytes, uint256)); - sellToUniswapV4(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); + if (action == uint32(ISettlerActions.UNISWAPV4.selector)) { + sellToUniswapV4(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); + } else { // if (action == uint32(ISettlerActions.EKUBOV3.selector)) + sellToEkuboV3(recipient, sellToken, bps, feeOnTransfer, hashMul, hashMod, fills, amountOutMin); + } } else { return false; } diff --git a/src/chains/RobinHood/MetaTxn.sol b/src/chains/RobinHood/MetaTxn.sol index ef5c56e58..e4b791c61 100644 --- a/src/chains/RobinHood/MetaTxn.sol +++ b/src/chains/RobinHood/MetaTxn.sol @@ -8,6 +8,8 @@ import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; import {ISettlerActions} from "../../ISettlerActions.sol"; +import {FastLogic} from "../../utils/FastLogic.sol"; + // Solidity inheritance is stupid import {SettlerBase} from "../../SettlerBase.sol"; import {AbstractContext} from "../../Context.sol"; @@ -16,6 +18,8 @@ import {Permit2PaymentBase} from "../../core/Permit2Payment.sol"; /// @custom:security-contact security@0x.org contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { + using FastLogic for bool; + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} function _dispatchVIP(uint256 action, bytes calldata data, bytes calldata sig) @@ -27,7 +31,8 @@ contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { { if (super._dispatchVIP(action, data, sig)) { return true; - } else if (action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) { + } else if ((action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) + .or(action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector))) { ( address recipient, ISignatureTransfer.PermitTransferFrom memory permit, @@ -39,8 +44,11 @@ contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { ) = abi.decode( data, (address, ISignatureTransfer.PermitTransferFrom, bool, uint256, uint256, bytes, uint256) ); - - sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + if (action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) { + sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + } else { // if (action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector)) + sellToEkuboV3VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + } } else { return false; } diff --git a/src/chains/RobinHood/TakerSubmitted.sol b/src/chains/RobinHood/TakerSubmitted.sol index 96e036aeb..04de48c4c 100644 --- a/src/chains/RobinHood/TakerSubmitted.sol +++ b/src/chains/RobinHood/TakerSubmitted.sol @@ -8,6 +8,8 @@ import {IERC20} from "@forge-std/interfaces/IERC20.sol"; import {ISignatureTransfer} from "@permit2/interfaces/ISignatureTransfer.sol"; import {ISettlerActions} from "../../ISettlerActions.sol"; +import {FastLogic} from "../../utils/FastLogic.sol"; + // Solidity inheritance is stupid import {SettlerBase} from "../../SettlerBase.sol"; import {Permit2PaymentAbstract} from "../../core/Permit2PaymentAbstract.sol"; @@ -15,12 +17,15 @@ import {AbstractContext} from "../../Context.sol"; /// @custom:security-contact security@0x.org contract RobinHoodSettler is Settler, RobinHoodMixin { + using FastLogic for bool; + constructor(bytes20 gitCommit) SettlerBase(gitCommit) {} function _dispatchVIP(uint256 action, bytes calldata data) internal override DANGEROUS_freeMemory returns (bool) { if (super._dispatchVIP(action, data)) { return true; - } else if (action == uint32(ISettlerActions.UNISWAPV4_VIP.selector)) { + } else if ((action == uint32(ISettlerActions.UNISWAPV4_VIP.selector)) + .or(action == uint32(ISettlerActions.EKUBOV3_VIP.selector))) { ( address recipient, ISignatureTransfer.PermitTransferFrom memory permit, @@ -34,7 +39,11 @@ contract RobinHoodSettler is Settler, RobinHoodMixin { data, (address, ISignatureTransfer.PermitTransferFrom, bool, uint256, uint256, bytes, bytes, uint256) ); - sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + if (action == uint32(ISettlerActions.UNISWAPV4_VIP.selector)) { + sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + } else { // if (action == uint32(ISettlerActions.EKUBOV3_VIP.selector)) + sellToEkuboV3VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); + } } else { return false; } From 3c22d9c78eb3888d419cb3832eb904c0cc6fd6e9 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 26 Jun 2026 15:10:05 +0200 Subject: [PATCH 050/107] Formatting --- src/chains/RobinHood/MetaTxn.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chains/RobinHood/MetaTxn.sol b/src/chains/RobinHood/MetaTxn.sol index e4b791c61..26ee0e61f 100644 --- a/src/chains/RobinHood/MetaTxn.sol +++ b/src/chains/RobinHood/MetaTxn.sol @@ -44,6 +44,7 @@ contract RobinHoodSettlerMetaTxn is SettlerMetaTxn, RobinHoodMixin { ) = abi.decode( data, (address, ISignatureTransfer.PermitTransferFrom, bool, uint256, uint256, bytes, uint256) ); + if (action == uint32(ISettlerActions.METATXN_UNISWAPV4_VIP.selector)) { sellToUniswapV4VIP(recipient, feeOnTransfer, hashMul, hashMod, fills, permit, sig, amountOutMin); } else { // if (action == uint32(ISettlerActions.METATXN_EKUBOV3_VIP.selector)) From 68e6d69f52c37701d4e1f76ef5421dcb77e21280 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 30 Jun 2026 13:43:59 +0200 Subject: [PATCH 051/107] Add PancakeSwapV3 UniV3 fork on RobinHood chain --- CHANGELOG.md | 1 + src/chains/RobinHood/Common.sol | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72d88f054..54acd4e16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Add UniswapV3 UniV3 fork on RobinHood chain * Add UniswapV4 actions to RobinHood chain * Add EkuboV3 actions on RobinHood chain +* Add PancakeSwapV3 UniV3 fork on RobinHood chain ## 2026-06-03 diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index bfaa11fec..75489a07c 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -19,6 +19,12 @@ import { uniswapV3ForkId, IUniswapV3Callback } from "../../core/univ3forks/UniswapV3.sol"; +import { + pancakeSwapV3Factory, + pancakeSwapV3InitHash, + pancakeSwapV3ForkId, + IPancakeSwapV3Callback +} from "../../core/univ3forks/PancakeSwapV3.sol"; import {ROBINHOOD_POOL_MANAGER} from "../../core/UniswapV4Addresses.sol"; import {FastLogic} from "../../utils/FastLogic.sol"; @@ -77,6 +83,10 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3 factory = uniswapV3RobinhoodFactory; initHash = uniswapV3InitHash; callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); + } else if (forkId == pancakeSwapV3ForkId) { + factory = pancakeSwapV3Factory; + initHash = pancakeSwapV3InitHash; + callbackSelector = uint32(IPancakeSwapV3Callback.pancakeV3SwapCallback.selector); } else { revertUnknownForkId(forkId); } From 8eb5ac2401812710c2c7f5f29d5b541b57a46022 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Jul 2026 07:54:43 +0000 Subject: [PATCH 052/107] Add PrjxV3 (Project X) UniV3 fork to HyperEVM with fork ID 39 Project X (prjx.com) is a vanilla UniswapV3 fork on HyperEVM (chain 999). Factory 0xFf7B3e8C00e57ea31477c32A5B52a58Eea47b072 deploys pools directly via CREATE2 with the standard abi.encode(token0, token1, fee) salt and pool init code hash 0x7ef2b01a451cbf890790278981756372e549443802ece149dc0b592cbc114ee9. Pools use the canonical uniswapV3SwapCallback selector. --- CHANGELOG.md | 1 + UNISWAPV3_FORKS.md | 2 ++ src/chains/HyperEvm/Common.sol | 5 +++++ src/core/univ3forks/PrjxV3.sol | 6 ++++++ 4 files changed, 14 insertions(+) create mode 100644 src/core/univ3forks/PrjxV3.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index b521e7090..d2b10a5a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Non-breaking changes * Add SquadSwapV3 UniV3 fork to Bnb with fork ID 38 +* Add PrjxV3 (Project X) UniV3 fork to HyperEVM with fork ID 39 * Add `BRIDGE_ERC20_TO_ACROSS` and `BRIDGE_NATIVE_TO_ACROSS` to Base * Fix several bugs reported by Nethermind * SettlerMetaTxn now reverts on short actions diff --git a/UNISWAPV3_FORKS.md b/UNISWAPV3_FORKS.md index b3e33480d..40b3ba28b 100644 --- a/UNISWAPV3_FORKS.md +++ b/UNISWAPV3_FORKS.md @@ -47,3 +47,5 @@ 37. Thena (Algebra-like) 38. SquadSwapV3 + + 39. PrjxV3 (Project X) diff --git a/src/chains/HyperEvm/Common.sol b/src/chains/HyperEvm/Common.sol index 84970c812..e5ce8fee8 100644 --- a/src/chains/HyperEvm/Common.sol +++ b/src/chains/HyperEvm/Common.sol @@ -20,6 +20,7 @@ import { hyperSwapForkId, IHyperswapV3SwapCallback } from "../../core/univ3forks/HyperSwap.sol"; +import {prjxV3Factory, prjxV3InitHash, prjxV3ForkId} from "../../core/univ3forks/PrjxV3.sol"; // Solidity inheritance is stupid import {SettlerSwapAbstract} from "../../SettlerAbstract.sol"; @@ -75,6 +76,10 @@ abstract contract HyperEvmMixin is FreeMemory, SettlerBase, Bebop { factory = hyperSwapFactory; initHash = hyperSwapInitHash; callbackSelector = uint32(IHyperswapV3SwapCallback.hyperswapV3SwapCallback.selector); + } else if (forkId == prjxV3ForkId) { + factory = prjxV3Factory; + initHash = prjxV3InitHash; + callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); } else { revertUnknownForkId(forkId); } diff --git a/src/core/univ3forks/PrjxV3.sol b/src/core/univ3forks/PrjxV3.sol new file mode 100644 index 000000000..16427a130 --- /dev/null +++ b/src/core/univ3forks/PrjxV3.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +address constant prjxV3Factory = 0xFf7B3e8C00e57ea31477c32A5B52a58Eea47b072; +bytes32 constant prjxV3InitHash = 0x7ef2b01a451cbf890790278981756372e549443802ece149dc0b592cbc114ee9; +uint8 constant prjxV3ForkId = 39; From 469bccf0ed92a0b6546e295ad8a409a3adb03deb Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 11:52:30 +0200 Subject: [PATCH 053/107] Add scaled exp ray multiplication Co-Authored-By: Codex --- formal/yul/YulImporter.lean | 27 ++++- formal/yul/generate_from_forge.sh | 2 +- src/vendor/Exp.sol | 161 ++++++++++++++++++++++-------- src/wrappers/ExpWrapper.sol | 4 + test/0.8.34/Exp.t.sol | 102 +++++++++++++++++++ 5 files changed, 247 insertions(+), 49 deletions(-) diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index baa218d5d..6a2c33ad5 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -40,7 +40,7 @@ def selectorCases : ModelKind → List String | .cbrt => ["0x56df2b56", "0x29f2f4f1"] | .cbrt512 => ["0xa83a5c08", "0x7c0352fc"] | .ln => ["0xef102248", "0x31d42abd"] - | .exp => ["0x4187462b"] + | .exp => ["0x4187462b", "0x79abc089"] def functionPrefixes : ModelKind → List String | .sqrt => @@ -68,7 +68,11 @@ def functionPrefixes : ModelKind → List String "fun_wrap_lnWad_", "fun_wrap_lnWadToRay_", "fun_lnWad_", "fun_lnWadToRay_"] | .exp => ["external_fun_wrap_expRayToWad_", - "fun_wrap_expRayToWad_", "fun_expRayToWad_", "fun__expRayToWad_"] + "external_fun_wrap_mulExpRay_", + "fun_wrap_expRayToWad_", "fun_wrap_mulExpRay_", + "fun_expRayToWad_", "fun_mulExpRay_", + "fun__absSign_", "fun__scaleShift_", "fun__octave_", "fun__expRayKernel_", + "fun_or_", "fun_and_", "fun_clz_"] def requiredCalls : ModelKind → List String | .sqrt => ["clz"] @@ -76,7 +80,7 @@ def requiredCalls : ModelKind → List String | .cbrt => ["clz"] | .cbrt512 => ["clz", "mulmod"] | .ln => ["clz", "sdiv"] - | .exp => ["div"] + | .exp => ["clz", "div"] end ModelKind @@ -504,8 +508,14 @@ contractDef ++ " def selector_expRayToWad : ByteArray := FormalYul.bytes [0x41, 0x87, 0x46, 0x2b] +def selector_mulExpRay : ByteArray := + FormalYul.bytes [0x79, 0xab, 0xc0, 0x89] + def run_exp_ray_to_wad_evm (x : Nat) : Except String Nat := FormalYul.callWord yulContract selector_expRayToWad [x] + +def run_mul_exp_ray_evm (y x : Nat) : Except String Nat := + FormalYul.callWord yulContract selector_mulExpRay [y, x] " def runHelpers : ModelKind → String → String @@ -721,9 +731,18 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : | .exp => sequence [ aliasByPrefix functions "external_fun_wrap_expRayToWad" "external_fun_wrap_expRayToWad_", + aliasByPrefix functions "external_fun_wrap_mulExpRay" "external_fun_wrap_mulExpRay_", aliasByPrefix functions "fun_wrap_expRayToWad" "fun_wrap_expRayToWad_", + aliasByPrefix functions "fun_wrap_mulExpRay" "fun_wrap_mulExpRay_", aliasByPrefix functions "fun_expRayToWad" "fun_expRayToWad_", - aliasByPrefix functions "fun__expRayToWad" "fun__expRayToWad_" + aliasByPrefix functions "fun_mulExpRay" "fun_mulExpRay_", + aliasByPrefix functions "fun__absSign" "fun__absSign_", + aliasByPrefix functions "fun__scaleShift" "fun__scaleShift_", + aliasByPrefix functions "fun__octave" "fun__octave_", + aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", + aliasByPrefix functions "fun_or" "fun_or_", + aliasByPrefix functions "fun_and" "fun_and_", + aliasByPrefix functions "fun_clz" "fun_clz_" ] def renderProof (kind : ModelKind) (contract : ParsedContract) (output : String) : Except String String := do diff --git a/formal/yul/generate_from_forge.sh b/formal/yul/generate_from_forge.sh index 9a633b185..eee3d1d2f 100755 --- a/formal/yul/generate_from_forge.sh +++ b/formal/yul/generate_from_forge.sh @@ -21,7 +21,7 @@ case "$kind" in cbrt) expected="29f2f4f1 56df2b56" ;; cbrt512) expected="7c0352fc a83a5c08" ;; ln) expected="31d42abd ef102248" ;; - exp) expected="4187462b" ;; + exp) expected="4187462b 79abc089" ;; *) echo "unknown kind: $kind" >&2; exit 2 ;; esac diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 8693d7c6a..6eabc89d5 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -2,8 +2,19 @@ pragma solidity ^0.8.34; import {Panic} from "../utils/Panic.sol"; +import {FastLogic} from "../utils/FastLogic.sol"; +import {Clz} from "./Clz.sol"; library Exp { + using FastLogic for bool; + + uint256 private constant _SCALE_MAX = 0x6f05b59d3b2000000000000000000000; + uint256 private constant _SCALE_MAX_CLZ = 129; + int256 private constant _EXP_RAY_TO_WAD_HI = 0x92b2f16cc66c5a4ae96e80d4; + int256 private constant _WAD_ZERO_MAX = -41446531673892822312323846185; + int256 private constant _X_HI = 86296823979713191022445399122; + int256 private constant _X_LO_ZERO = -88376265521393026950697095485; + /// @notice Compute the natural exponential of a fixnum with 10**27 (ray) basis, returning the /// result as a fixnum with 10**18 (wad) basis. /// @dev Let E = 10¹⁸ ⋅ exp(x / 10²⁷) be the exact, infinite-precision result. This function @@ -16,25 +27,91 @@ library Exp { function expRayToWad(int256 x) internal pure returns (int256) { // At this input the octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, where the deficit // envelope below exceeds 1ulp. - if (x >= 0x92b2f16cc66c5a4ae96e80d4) { + if (x >= _EXP_RAY_TO_WAD_HI) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } - return _expRayToWad(x); + + int256 k = _octave(x); + unchecked { + return int256(_expRayKernel(x, k, _SCALE_MAX, uint256(int256(67) - k), _WAD_ZERO_MAX)); + } + } + + /// @notice Compute y * exp(x / 10**27), with y's sign reapplied after magnitude evaluation. + /// @dev Let A = abs(y) * exp(x / 10**27). For accepted inputs, this function returns sign(y) * m + /// with m <= A < m + 2. Reverts with `Panic(17)` when abs(y) exceeds the supported scale, + /// or when x and abs(y) cannot preserve that bound with a single-word scaled product. + function mulExpRay(int256 y, int256 x) internal pure returns (int256) { + if (y == 0) { + return 0; + } + + (uint256 ay, uint256 sign) = _absSign(y); + uint256 s = _scaleShift(ay); + int256 k = _octave(x); + unchecked { + if ((ay > _SCALE_MAX).or(x >= _X_HI).or((x != 0).and(x > _X_LO_ZERO).and(k > int256(s) - 2))) { + Panic.panic(Panic.ARITHMETIC_OVERFLOW); + } + + uint256 m = _expRayKernel(x, k, ay << s, uint256(int256(s) - k), _X_LO_ZERO); + // Apply y's sign without branching: + // m = (m ^ sign) - sign + assembly ("memory-safe") { + m := sub(xor(m, sign), sign) + } + return int256(m); + } + } + + function _absSign(int256 y) private pure returns (uint256 ay, uint256 sign) { + // Compute `abs(y)` without negating `type(int256).min`: + // sign = 0 for nonnegative y, -1 for negative y + // ay = (y ^ sign) - sign + assembly ("memory-safe") { + sign := sar(0xff, y) + ay := sub(xor(y, sign), sign) + } + } + + function _scaleShift(uint256 ay) private pure returns (uint256 s) { + unchecked { + s = Clz.clz(ay) - _SCALE_MAX_CLZ; + uint256 scaleMax = _SCALE_MAX; + // Correct the bit-length estimate without branching: + // s -= gt(ay << s, scaleMax) + assembly ("memory-safe") { + s := sub(s, gt(shl(s, ay), scaleMax)) + } + } } - /// @dev The rational polynomial approximation kernel - function _expRayToWad(int256 x) private pure returns (int256 r) { + function _octave(int256 x) private pure returns (int256 k) { + // Round to the nearest octave: + // k = round(x / (10**27 * ln(2))) + assembly ("memory-safe") { + // k = round(x / (10²⁷⋅ln(2))), half-open. CINV = round(2¹⁹² / (10²⁷⋅ln(2))); the +2¹⁹¹ + // and `sar(192, …)` round to nearest with ties resolved toward +∞. + k := sar(0xc0, add(shl(0xbf, 0x01), mul(0x724d54edbacbebbb95c52a0f60, x))) + } + } + + /// @dev The rational polynomial approximation kernel. + function _expRayKernel(int256 x, int256 k, uint256 scale, uint256 shift, int256 zeroCutoff) + private + pure + returns (uint256 r) + { // Equivalent pseudocode; fixed-point truncations are accounted for below: - // k = round(x / (10²⁷⋅ln(2))); // x = (k⋅ln(2) + t)⋅10²⁷, |t| ≤ ln(2)/2 // t = x/10²⁷ - k⋅ln(2); // range-reduced argument; Q129 // ev = Ev(t²); // polynomial approximation; Q89 // od = Od(t²); // polynomial approximation; Q89 // n = ev + t⋅od; // rational numerator; Q89 // d = ev - t⋅od; // rational denominator; Q89 - // e = 10¹⁸⋅n / d; // ≈ 10¹⁸⋅exp(t); Q67 - // r = ⌊(e - margin)⋅2ᵏ⌋; // wad - // r = r ⋅ (x > C); // C = ⌊-18⋅ln10⋅10²⁷⌋; 0 where E < 1 - // return r + (x == 0); // pin exp(0) = 10¹⁸ exactly + // e = scale⋅n / d; // ≈ scale⋅exp(t) + // r = ⌊(e - margin) / 2ˢʰⁱᶠᵗ⌋; + // r = r ⋅ (x > zeroCutoff); + // return r + (x == 0); // pin exact scale points // // `exp(t) = (1 + tanh(t/2)) / (1 - tanh(t/2))`, so with the even/odd split N(t) = Ev(t²) + // t⋅Od(t²) the quotient N(t)/N(-t) is the reciprocal-symmetric rational that matches @@ -57,9 +134,9 @@ library Exp { // product stays inside 256 bits // dividend: Q156 the widest basis that fits in 256 bits before the single truncating // `DIV` by Q89 divisor. < 2¹²⁹ - // r: Q67 implied by the pre-scale 10¹⁸⋅2⁶⁷ < 2¹²⁷ to avoid overflowing the dividend. - // output: the closing `shr(67 - k, …)` is the output-rounding floor, with the 2ᵏ octave - // scaling folded in + // r: the pre-scale is at most 10¹⁸⋅2⁶⁷ < 2¹²⁷ to avoid overflowing the dividend. + // output: the closing `shr(shift, …)` is the output-rounding floor, with the 2ᵏ octave + // scaling folded into the caller's scale/shift pair. // // Error budget. Let ê = N/D be the exact value of the integer rational (N = Ev + t⋅Od, D = // Ev - t⋅Od; the closing `DIV` floor is counted on the output grid below) and write its @@ -82,25 +159,26 @@ library Exp { // (k⋅ln(2) grid error is below 2⁻²²⁹), enveloped one-sidedly at 2⁻¹³³ of reduced // argument, lifting ê by < 0.01105 (√2⋅2¹²⁶/(32⋅2¹²⁸) = √2/128). // - // The quotient `r` carries 10¹⁸⋅ê on the 2⁶⁷ output grid, where one grid unit is worth - // 2ᵏ⁻⁶⁷ ulp (1 ulp = 10⁻¹⁸ of the result) and Δ's image is below one grid unit: the Q89 - // closing bases confine the over-side jitter so that 5¹⁸⋅Δ/2⁴¹ < 1. The margin is the least - // integer strictly above that image: 0x01, worth 0.25 ulp at the supported edge k = 65. The - // `DIV` floor only lowers the quotient, so the pre-floor accumulator A = q - margin - // satisfies A⋅2ᵏ⁻⁶⁷ ≤ E. The under side is certified directly on the output grid, piecewise - // over the 32 domain pieces (per-piece denominator floors confine the truncation - // amplification): q ≥ 10¹⁸⋅2⁶⁷⋅exp(t) - 2993/1000, where 2993/1000 bounds, on each sign - // half, the sum of the integer-rational deficit together with the `DIV` floor (≤ 2378/1000, - // certified piecewise), the `Mp` factor (≤ 2/25, via ê ≤ 1.45), the under-direction - // reduced-argument gap (≤ 307/1000 on the t > 0 half via exp(t) ≤ √2; ≤ 218/1000 on the - // other, where exp(t) ≤ 1 + ε), and the under-direction argument granularity (≤ 143/500: - // the one-grain envelope with the negative-half denominator floor; free on the t > 0 half). + // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid unit + // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale ≤ 10¹⁸⋅2⁶⁷, Δ's + // image is below one grid unit: the Q89 closing bases confine the over-side jitter so that + // 5¹⁸⋅Δ/2⁴¹ < 1. The margin is the least integer strictly above that image: 0x01, worth + // 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so the + // pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is certified + // directly on the output grid, piecewise over the 32 domain pieces (per-piece denominator + // floors confine the truncation amplification): q ≥ scale⋅exp(t) - 2993/1000, where + // 2993/1000 bounds, on each sign half, the sum of the integer-rational deficit together + // with the `DIV` floor (≤ 2378/1000, certified piecewise), the `Mp` factor (≤ 2/25, via ê ≤ + // 1.45), the under-direction reduced-argument gap (≤ 307/1000 on the t > 0 half via exp(t) + // ≤ √2; ≤ 218/1000 on the other, where exp(t) ≤ 1 + ε), and the under-direction argument + // granularity (≤ 143/500: the one-grain envelope with the negative-half denominator floor; + // free on the t > 0 half). // - // Hence the maximum underestimation is E - A⋅2ᵏ⁻⁶⁷ ≤ (2993/1000 + margin)⋅2ᵏ⁻⁶⁷ = - // (3993/4000)⋅2ᵏ⁻⁶⁵ ulp. At k ≤ 65, this is < 1, so the floor returns ⌊E⌋ or ⌊E⌋ - 1. The - // deficit envelope doubles each octave and exceeds 1ulp at k ≥ 66. On the central octave k - // = 0, the margin is 2⁻⁶⁷ ≈ 6.8⋅10⁻²¹ ulp, far below the ≈10⁻⁹ ulp gap `lnWadToRay` leaves, - // so the round trip floors to ⌊E⌋. The k = 0 band is exactly [-H, H] with H = + // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2993/1000 + margin)⋅2ᵏ⁻ˢ. The caller + // keeps k ≤ s - 2, where this is < 1, so the floor returns ⌊E⌋ or ⌊E⌋ - 1. For the wad + // specialization s = 67, the deficit envelope exceeds 1ulp at k ≥ 66. On the central octave + // k = 0, the margin is 2⁻⁶⁷ ≈ 6.8⋅10⁻²¹ ulp, far below the ≈10⁻⁹ ulp gap `lnWadToRay` + // leaves, so the round trip floors to ⌊E⌋. The k = 0 band is exactly [-H, H] with H = // ⌊10²⁷⋅ln(2)/2⌋, matching `lnWadToRay`'s image over [1/√2, √2). // // Monotonicity: one unit step in x multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves the @@ -114,10 +192,6 @@ library Exp { // ⌊E⌋ ≥ 0, and the adjacent runtime values around x = 0 bracket the pinned scale-point // value. assembly ("memory-safe") { - // k = round(x / (10²⁷⋅ln(2))), half-open. CINV = round(2¹⁹² / (10²⁷⋅ln(2))); the +2¹⁹¹ - // and `sar(192, …)` round to nearest with ties resolved toward +∞. - let k := sar(0xc0, add(shl(0xbf, 0x01), mul(0x724d54edbacbebbb95c52a0f60, x))) - // t in Q129. K27 = round(2²³⁵ / 10²⁷) and LN2 = round(ln(2) ⋅ 2²³⁵). Subtracting k⋅LN2 // from K27⋅x at the Q235 product basis (so the k⋅ln(2) rounding error is ~2⁻²³⁵, far // below an output ulp) then one `sar(106, …)` leaves the reduced argument at Q129. @@ -155,22 +229,21 @@ library Exp { // both positive. let tod := sar(0x81, mul(t, od)) - // 10¹⁸⋅exp(t) in Q67: the constant is 10¹⁸⋅2⁶⁷ = 5¹⁸⋅2⁸⁵, so one `DIV` scales, widens, - // and floors at once. The numerator stays below 2¹²⁹ and 10¹⁸⋅2⁶⁷ < 2¹²⁷, so the + // The scaled rational: the caller keeps scale ≤ 10¹⁸⋅2⁶⁷, so one `DIV` scales, widens, + // and floors at once. The numerator stays below 2¹²⁹ and scale < 2¹²⁷, so the // dividend stays inside 256 bits; the denominator > 0. - r := div(mul(0x6f05b59d3b2000000000000000000000, add(ev, tod)), sub(ev, tod)) + r := div(mul(scale, add(ev, tod)), sub(ev, tod)) // Less the one-sided margin (0x01; see the budget above), then floored by - // `shr(67 - k, …)` which folds in the 2ᵏ octave scaling (67 - k ∈ [3, 127]). - r := shr(sub(0x43, k), sub(r, 0x01)) + // `shr(shift, …)` which folds in the 2ᵏ octave scaling. + r := shr(shift, sub(r, 0x01)) - // Zero the result at and below C = ⌊-18⋅ln(10)⋅10²⁷⌋ = ⌊10²⁷⋅ln(10⁻¹⁸)⌋, the greatest x - // with E < 1. This is the exact 0/1 output boundary, and it sits far above the inputs - // where the reduction would overflow, so it also discards those (otherwise garbage). - r := mul(slt(sub(0x00, 0x85ebc478242540a11f5f1029), x), r) + // Zero results whose exact magnitude is below one output unit. For very negative x, + // this also discards arithmetic outside the reduction range. + r := mul(slt(zeroCutoff, x), r) // exp(0) = 1 is the only input whose exact result is an integer; the construction lands - // on 10¹⁸ - 1, so add one back exactly there. + // one unit below the input magnitude, so add one back exactly there. r := add(iszero(x), r) } } diff --git a/src/wrappers/ExpWrapper.sol b/src/wrappers/ExpWrapper.sol index 59a8d3ea6..deabe86da 100644 --- a/src/wrappers/ExpWrapper.sol +++ b/src/wrappers/ExpWrapper.sol @@ -10,4 +10,8 @@ contract ExpWrapper { function wrap_expRayToWad(int256 x) external pure returns (int256) { return Exp.expRayToWad(x); } + + function wrap_mulExpRay(int256 y, int256 x) external pure returns (int256) { + return Exp.mulExpRay(y, x); + } } diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index 4538fe2c0..90778ef7c 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -6,8 +6,13 @@ import {Ln} from "src/vendor/Ln.sol"; import {Test, stdError} from "@forge-std/Test.sol"; contract ExpTest is Test { + uint256 private constant _SCALE_MAX = 0x6f05b59d3b2000000000000000000000; // First input whose octave count exceeds the supported range; `expRayToWad` reverts here. int256 private constant _TOO_BIG = 0x92b2f16cc66c5a4ae96e80d4; + // First input whose octave count reaches 125. + int256 private constant _X_HI = 86296823979713191022445399122; + // First input whose octave count reaches -127; all supported magnitudes floor to zero here. + int256 private constant _X_LO_ZERO = -88376265521393026950697095485; // floor(1e27 * ln(1e-18)): the greatest input whose exact result is < 1 and floors to 0. int256 private constant _ZERO_MAX = -41446531673892822312323846185; // Canonical central wad inputs satisfying 1/sqrt(2) <= w/1e18 < sqrt(2). @@ -18,6 +23,10 @@ contract ExpTest is Test { return Exp.expRayToWad(x); } + function mulExpRayExternal(int256 y, int256 x) external pure returns (int256) { + return Exp.mulExpRay(y, x); + } + function testExpRayToWadExactZero() external pure { assertEq(Exp.expRayToWad(0), 1e18, "expRayToWad(0) != 1e18"); } @@ -174,4 +183,97 @@ contract ExpTest is Test { assertGe(r, 0, "negative result"); assertGe(Exp.expRayToWad(x + 1), r, "adjacent monotonicity"); } + + function testMulExpRaySpecializesExpRayToWad() external pure { + int256[12] memory xs = [ + int256(_X_LO_ZERO), + _X_LO_ZERO + 1, + _ZERO_MAX, + _ZERO_MAX + 1, + -1, + 0, + 1, + 44014845965556527147989858478, + 44044505178945024895948687544, + 44707993146116472457411471834, + _TOO_BIG - 1, + -50e27 + ]; + for (uint256 i; i < xs.length; ++i) { + assertEq(Exp.mulExpRay(1e18, xs[i]), Exp.expRayToWad(xs[i]), "wad specialization"); + } + } + + function testMulExpRayScalePoint() external pure { + assertEq(Exp.mulExpRay(1, 0), 1, "one"); + assertEq(Exp.mulExpRay(-1, 0), -1, "minus one"); + assertEq(Exp.mulExpRay(int256(_SCALE_MAX), 0), int256(_SCALE_MAX), "scale max"); + assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), 0), -int256(_SCALE_MAX), "negative scale max"); + } + + function testMulExpRayZeroY() external pure { + assertEq(Exp.mulExpRay(0, type(int256).min), 0, "min x"); + assertEq(Exp.mulExpRay(0, type(int256).max), 0, "max x"); + } + + function testMulExpRayLowerZero() external pure { + assertEq(Exp.mulExpRay(1, _X_LO_ZERO), 0, "one at boundary"); + assertEq(Exp.mulExpRay(int256(_SCALE_MAX), _X_LO_ZERO), 0, "scale max at boundary"); + assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), _X_LO_ZERO - 1), 0, "negative below boundary"); + } + + function testMulExpRayNegativeSignSymmetry() external pure { + int256 x = 3e27; + int256 y = 123456789012345678901234567; + assertEq(Exp.mulExpRay(-y, x), -Exp.mulExpRay(y, x), "positive exponent"); + assertEq(Exp.mulExpRay(-y, -x), -Exp.mulExpRay(y, -x), "negative exponent"); + } + + function testMulExpRayOverScaleReverts() external { + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(int256(_SCALE_MAX + 1), 0); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(type(int256).min, 0); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(int256(_SCALE_MAX + 1), _X_LO_ZERO); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(type(int256).min, type(int256).min); + } + + function testMulExpRayHighGuardReverts() external { + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(1, _X_HI); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(1, type(int256).max); + } + + function testMulExpRayAccuracyGuardReverts() external { + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(1e18, _TOO_BIG); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(int256(_SCALE_MAX), _octaveStart(-1)); + } + + function testMulExpRaySmallMagnitudeHighOctave() external { + assertGt(Exp.mulExpRay(1, _X_HI - 1), 0, "k = 124 accepted"); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(1, _X_HI); + } + + function testFuzzMulExpRaySpecializesExpRayToWad(int256 x) external pure { + x = bound(x, _X_LO_ZERO - 1e27, _TOO_BIG - 1); + assertEq(Exp.mulExpRay(1e18, x), Exp.expRayToWad(x), "wad specialization"); + } + + function testFuzzMulExpRaySignSymmetry(uint256 uy, int256 x) external pure { + int256 y = int256(bound(uy, 1, 1e18)); + x = bound(x, _X_LO_ZERO + 1, _TOO_BIG - 1); + assertEq(Exp.mulExpRay(-y, x), -Exp.mulExpRay(y, x), "sign symmetry"); + } + + function testFuzzMulExpRayMonotoneMagnitude(uint256 uy, int256 x) external pure { + int256 y = int256(bound(uy, 1, 1e18)); + x = bound(x, _X_LO_ZERO + 1, _TOO_BIG - 2); + assertGe(Exp.mulExpRay(y, x + 1), Exp.mulExpRay(y, x), "adjacent monotonicity"); + } } From f9a160f5478bcf63eed13598ca439fb1a728238c Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 12:54:57 +0200 Subject: [PATCH 054/107] Repair exp proof seam for shared kernel Co-Authored-By: Codex --- .../ExpProof/ExpProof/Seam/Dispatcher.lean | 18 +- formal/exp/ExpProof/ExpProof/Seam/Guard.lean | 2 +- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 494 +++++++++++++++++- formal/exp/ExpProof/ExpProof/Seam/Revert.lean | 55 +- formal/exp/ExpProof/ExpProof/Seam/Value.lean | 208 +++++--- formal/yul/YulImporter.lean | 20 + 6 files changed, 695 insertions(+), 102 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean index 70310a73d..8606b5fd2 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean @@ -362,13 +362,16 @@ theorem selectSwitchCase_expRayToWad_sharedFor_mk (x : Nat) : (FormalYul.word 64) (FormalYul.word 128))) (Inhabited.default : EvmYul.Yul.VarStore)).toState (FormalYul.word 0)) - (FormalYul.word 224)) + (FormalYul.word 224)) [(FormalYul.word 1099384363, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr "external_fun_wrap_expRayToWad_97") [])])] = + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), + (FormalYul.word 2041299081, + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = some [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr "external_fun_wrap_expRayToWad_97") [])] := by + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])] := by rw [expRayToWad_selector_sharedFor_mk] rfl @@ -385,13 +388,16 @@ theorem selectSwitchCase_expRayToWad_sharedFor_mk_raw (x : Nat) : (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) - (EvmYul.UInt256.ofNat 224)) + (EvmYul.UInt256.ofNat 224)) [(EvmYul.UInt256.ofNat 1099384363, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr "external_fun_wrap_expRayToWad_97") [])])] = + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), + (EvmYul.UInt256.ofNat 2041299081, + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = some [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr "external_fun_wrap_expRayToWad_97") [])] := by + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])] := by simpa [FormalYul.word] using selectSwitchCase_expRayToWad_sharedFor_mk x /-- Revert-analogue of `Preservation.runContract_ok_of_dispatcherReturn`: if the bare dispatcher diff --git a/formal/exp/ExpProof/ExpProof/Seam/Guard.lean b/formal/exp/ExpProof/ExpProof/Seam/Guard.lean index ef18da487..e44f31d53 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Guard.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Guard.lean @@ -3,7 +3,7 @@ import Common.Word /-! # The overflow-guard comparison -`fun_expRayToWad_68` branches on `iszero(slt(x, C))` with `C = 0x92b2f16cc66c5a4ae96e80d4` +`fun_expRayToWad` branches on `iszero(slt(x, C))` with `C = 0x92b2f16cc66c5a4ae96e80d4` (the first input whose octave count reaches 65). For a signed input `x ≥ C` (with `u256 x < 2^255`, i.e. `x` a nonnegative signed value at least `C`), the signed comparison `slt(x, C)` is `0`, so the guard `iszero(slt(x, C))` is `1` and the revert diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index ff00d1b2c..0d6aa7c5d 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -6,7 +6,7 @@ import FormalYul.Preservation # Per-function "direct" reductions for the trivial solc ABI/cleanup helpers These functions (`cleanup_*`, `identity`, `convert_*`, the constant accessor, `zero_value_*`) are -the solc-emitted plumbing called from `fun_expRayToWad_68`'s overflow guard and panic-code path. +the solc-emitted plumbing called from `fun_expRayToWad`'s overflow guard and panic-code path. Each is a one-liner; the directs step the interpreter through them. They are branch-agnostic — the value path also evaluates the guard (to decide *not* to revert) — so they live here, shared by both `Seam/Revert.lean` and the value-path seam. @@ -16,6 +16,7 @@ namespace ExpYul open FormalYul open FormalYul.Preservation +open Common.Word set_option maxRecDepth 100000 @@ -41,6 +42,28 @@ theorem call_zero_value_for_split_t_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +/-- `zero_value_for_split_t_uint256()` returns the word `0`. -/ +theorem call_zero_value_for_split_t_uint256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [] (.some "zero_value_for_split_t_uint256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_zero_value_for_split_t_uint256] + simp only [yulFunction_zero_value_for_split_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + /-- A one-line identity helper `f(value) -> out { out := value }` returns its argument. The proof recipe is shared by `cleanup_t_int256`, `identity`, `cleanup_t_rational_*`, `cleanup_t_uint256`. -/ theorem call_cleanup_t_int256_direct @@ -126,6 +149,72 @@ theorem call_cleanup_t_rational_17_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +theorem call_cleanup_t_rational_67_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_67_by_1") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_67_by_1] + simp only [yulFunction_cleanup_t_rational_67_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_SCALE_MAX_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_147573952589676412928000000000000000000_by_1") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_147573952589676412928000000000000000000_by_1] + simp only [yulFunction_cleanup_t_rational_147573952589676412928000000000000000000_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_WAD_ZERO_MAX_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_minus_41446531673892822312323846185_by_1") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_minus_41446531673892822312323846185_by_1] + simp only [yulFunction_cleanup_t_rational_minus_41446531673892822312323846185_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + theorem call_cleanup_t_uint256_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -188,6 +277,397 @@ theorem call_convert_44_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] +theorem call_constant__EXP_RAY_TO_WAD_HI_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__EXP_RAY_TO_WAD_HI) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x92b2f16cc66c5a4ae96e80d4]) := by + rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_constant__EXP_RAY_TO_WAD_HI] + simp only [yulFunction_constant__EXP_RAY_TO_WAD_HI, yulFunction_constant__EXP_RAY_TO_WAD_HI_132, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hconv := + call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) + (fuel := fuel + extra + 35) (extra := 0) (shared := shared) + (store := Finmap.insert "expr_131" (FormalYul.word 0x92b2f16cc66c5a4ae96e80d4) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at hconv + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hconv] + +theorem call_convert_67_to_int256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0x43] + (.some "convert_t_rational_67_by_1_to_t_int256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x43]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_67_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_67_by_1_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_67_direct (v := 0x43) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x43) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0x43) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x43) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := 0x43) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x43) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_SCALE_MAX_to_uint256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) + [FormalYul.word 0x6f05b59d3b2000000000000000000000] + (.some "convert_t_rational_147573952589676412928000000000000000000_by_1_to_t_uint256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word 0x6f05b59d3b2000000000000000000000]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_147573952589676412928000000000000000000_by_1_to_t_uint256] + simp only [yulFunction_convert_t_rational_147573952589676412928000000000000000000_by_1_to_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_SCALE_MAX_direct + (v := 0x6f05b59d3b2000000000000000000000) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x6f05b59d3b2000000000000000000000) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0x6f05b59d3b2000000000000000000000) + (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x6f05b59d3b2000000000000000000000) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_uint256_direct (v := 0x6f05b59d3b2000000000000000000000) + (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x6f05b59d3b2000000000000000000000) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_WAD_ZERO_MAX_to_int256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) + [FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7] + (.some "convert_t_rational_minus_41446531673892822312323846185_by_1_to_t_int256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_minus_41446531673892822312323846185_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_minus_41446531673892822312323846185_by_1_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_WAD_ZERO_MAX_direct + (v := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (fuel := fuel + extra) (extra := 92) (shared := shared) + (store := Finmap.insert "value" + (FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" + (FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct + (v := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" + (FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_constant__SCALE_MAX_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__SCALE_MAX) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word 0x6f05b59d3b2000000000000000000000]) := by + rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX] + simp only [yulFunction_constant__SCALE_MAX, yulFunction_constant__SCALE_MAX_126, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hconv := + call_convert_SCALE_MAX_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) + (shared := shared) + (store := Finmap.insert "expr_125" + (FormalYul.word 0x6f05b59d3b2000000000000000000000) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at hconv + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hconv] + +theorem call_constant__WAD_ZERO_MAX_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__WAD_ZERO_MAX) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7]) := by + rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__WAD_ZERO_MAX] + simp only [yulFunction_constant__WAD_ZERO_MAX, yulFunction_constant__WAD_ZERO_MAX_136, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hconv := + call_convert_WAD_ZERO_MAX_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) + (shared := shared) + (store := Finmap.insert "expr_135" + (FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at hconv + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hconv] + +theorem call_wrapping_sub_t_int256_direct + (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word x, FormalYul.word y] + (.some "wrapping_sub_t_int256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmSub x y)]) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_wrapping_sub_t_int256] + simp only [yulFunction_wrapping_sub_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hcleanup := + call_cleanup_t_int256_direct (v := evmSub x y) (fuel := fuel + extra) (extra := 56) + (shared := shared) + (store := Finmap.insert "x" (FormalYul.word x) + (Finmap.insert "y" (FormalYul.word y) (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := hlookup) + simp [FormalYul.word] at hcleanup + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, hcleanup] + +theorem call_convert_int256_to_uint256_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word v] + (.some "convert_t_int256_to_t_uint256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_int256_to_t_uint256] + simp only [yulFunction_convert_t_int256_to_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_int256_direct (v := v) (fuel := fuel + extra) (extra := 92) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := v) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_uint256_direct (v := v) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_uint256_to_int256_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word v] + (.some "convert_t_uint256_to_t_int256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_uint256_to_t_int256] + simp only [yulFunction_convert_t_uint256_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_uint256_direct (v := v) (fuel := fuel + extra) (extra := 92) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := v) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := v) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_fun__octave_direct + (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word x] (.some yulName_fun__octave) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word + (evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)))]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__octave] + simp only [yulFunction_fun__octave, yulFunction_fun__octave_337, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 96) + (shared := shared) (hlookup := hlookup)] + apply FormalYul.Preservation.eq_of_wordNat_eq + simp only [wordNat_sar, + FormalYul.Preservation.wordNat_shiftLeft, FormalYul.Preservation.wordNat_add, + FormalYul.Preservation.wordNat_mul, FormalYul.Preservation.wordNat_ofNat] + simp only [FormalYul.Preservation.evmAdd_u256_left, + FormalYul.Preservation.evmMul_u256_left, FormalYul.Preservation.evmMul_u256_right, + FormalYul.Preservation.evmShl_u256_left, FormalYul.Preservation.evmShl_u256_right, + evmSar_u256_left] + have hsar : + evmSar 192 (evmAdd (evmShl 191 1) (evmMul 9055943544797870567083544809312 x)) < + 2 ^ 256 := + (evmSar_sandwich (s := 192) (by norm_num) + (FormalYul.Preservation.evmAdd_lt_pow256 _ _)).1 + exact (FormalYul.Preservation.u256_eq_of_lt _ (by simpa [FormalYul.WORD_MOD] using hsar)).symm + /-- `cleanup_t_uint8(value) -> cleaned { cleaned := and(value, 0xff) }`. Specialized to the panic code `0x11`, where `and(0x11, 0xff) = 0x11`. -/ theorem call_cleanup_t_uint8_17_direct @@ -251,27 +731,27 @@ theorem call_convert_17_to_uint8_17_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -/-- `constant_ARITHMETIC_OVERFLOW_17() = 0x11` — the solc panic-code accessor for arithmetic +/-- The solc panic-code accessor for arithmetic overflow returns `0x11`. overflow (`0x11`). -/ -theorem call_constant_ARITHMETIC_OVERFLOW_17_direct +theorem call_constant_ARITHMETIC_OVERFLOW_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant_ARITHMETIC_OVERFLOW_17") + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant_ARITHMETIC_OVERFLOW) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x11]) := by rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_constant_ARITHMETIC_OVERFLOW_17] - simp only [yulFunction_constant_ARITHMETIC_OVERFLOW_17, + lookup_constant_ARITHMETIC_OVERFLOW] + simp only [yulFunction_constant_ARITHMETIC_OVERFLOW, yulFunction_constant_ARITHMETIC_OVERFLOW_62, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hconv := call_convert_17_to_uint8_17_direct (fuel := fuel + extra + 35) (shared := shared) - (store := Finmap.insert "expr_16" (FormalYul.word 0x11) (Inhabited.default : EvmYul.Yul.VarStore)) + (store := Finmap.insert "expr_61" (FormalYul.word 0x11) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) simp [FormalYul.word] at hconv simp +decide [EvmYul.Yul.execCall.eq_def, diff --git a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean index 5a42c6b68..f2a9ea8e2 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean @@ -8,8 +8,8 @@ import FormalYul.Preservation /-! # Revert reduction for the overflow guard -`fun_expRayToWad_68` takes the overflow-guard branch for inputs at/above the threshold and calls -`fun_panic_8`, which does `mstore;mstore;revert(0x1c,0x24)`. These per-function "direct" lemmas +`fun_expRayToWad` takes the overflow-guard branch for inputs at/above the threshold and calls +`fun_panic`, which does `mstore;mstore;revert(0x1c,0x24)`. These per-function "direct" lemmas step the interpreter through that branch; mirrors the `ln` revert path. -/ @@ -33,18 +33,18 @@ private theorem primCall_revert_yul (fuel : Nat) (s : EvmYul.Yul.State) rfl set_option maxHeartbeats 8000000 in -/-- `fun_panic_8(code)` reverts: its body is `mstore(0,…); mstore(0x20,code); revert(0x1c,0x24)`. -/ -theorem call_fun_panic_8_revert_direct +/-- `fun_panic(code)` reverts: its body is `mstore(0,…); mstore(0x20,code); revert(0x1c,0x24)`. -/ +theorem call_fun_panic_revert_direct (code fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 600)) [FormalYul.word code] (.some "fun_panic_8") + EvmYul.Yul.call (fuel + (extra + 600)) [FormalYul.word code] (.some yulName_fun_panic) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .error EvmYul.Yul.Exception.Revert := by rw [show fuel + (extra + 600) = (fuel + extra) + 600 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_panic_8] - simp only [yulFunction_fun_panic_8, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_panic] + simp only [yulFunction_fun_panic, yulFunction_fun_panic_53, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -58,28 +58,31 @@ theorem call_fun_panic_8_revert_direct FormalYul.word, primCall_revert_yul] set_option maxHeartbeats 8000000 in -/-- For inputs at/above the overflow threshold, `fun_expRayToWad_68` takes the guard branch and -reverts via `fun_panic_8(ARITHMETIC_OVERFLOW)`. -/ -theorem call_fun_expRayToWad_68_revert_direct +/-- For inputs at/above the overflow threshold, `fun_expRayToWad` takes the guard branch and +reverts via `fun_panic(ARITHMETIC_OVERFLOW)`. -/ +theorem call_fun_expRayToWad_revert_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) (h1 : (0x92b2f16cc66c5a4ae96e80d4 : Nat) ≤ FormalYul.u256 x) (h2 : FormalYul.u256 x < 2 ^ 255) : - EvmYul.Yul.call (fuel + (extra + 1000)) [FormalYul.word x] (.some "fun_expRayToWad_68") + EvmYul.Yul.call (fuel + (extra + 1000)) [FormalYul.word x] (.some yulName_fun_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .error EvmYul.Yul.Exception.Revert := by rw [show fuel + (extra + 1000) = (fuel + extra) + 1000 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad_68] - simp only [yulFunction_fun_expRayToWad_68, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad] + simp only [yulFunction_fun_expRayToWad, yulFunction_fun_expRayToWad_190, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv44 := - call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) (extra := 867) + have hconstHi := + call_constant__EXP_RAY_TO_WAD_HI_direct (fuel := fuel + extra) (extra := 832) (shared := shared) (hlookup := hlookup) + have hcleanupHi := + call_cleanup_t_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) + (extra := 967) (shared := shared) (hlookup := hlookup) have hcleanup := call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 965) (shared := shared) (hlookup := hlookup) @@ -87,9 +90,9 @@ theorem call_fun_expRayToWad_68_revert_direct call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 865) (shared := shared) (hlookup := hlookup) have hpanic := - call_fun_panic_8_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 384) + call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 384) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hconv44 hcleanup hconvu hpanic + simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hconvu hpanic simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -100,12 +103,12 @@ theorem call_fun_expRayToWad_68_revert_direct slt_thresh_ge h1 h2, call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 976) (shared := shared) (hlookup := hlookup), - call_constant_ARITHMETIC_OVERFLOW_17_direct (fuel := fuel + extra) (extra := 826) + call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 826) (shared := shared) (hlookup := hlookup), - hcleanup, hconv44, hconvu, hpanic] + hcleanupHi, hcleanup, hconstHi, hconvu, hpanic] set_option maxHeartbeats 8000000 in -/-- The thin wrapper `fun_wrap_expRayToWad_97` just forwards to `fun_expRayToWad_68`, so it reverts +/-- The thin wrapper `fun_wrap_expRayToWad` just forwards to `fun_expRayToWad`, so it reverts on the same out-of-range inputs. -/ theorem call_fun_wrap_expRayToWad_revert_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -113,19 +116,19 @@ theorem call_fun_wrap_expRayToWad_revert_direct some (FormalYul.accountFor yulContract)) (h1 : (0x92b2f16cc66c5a4ae96e80d4 : Nat) ≤ FormalYul.u256 x) (h2 : FormalYul.u256 x < 2 ^ 255) : - EvmYul.Yul.call (fuel + (extra + 1200)) [FormalYul.word x] (.some "fun_wrap_expRayToWad_97") + EvmYul.Yul.call (fuel + (extra + 1200)) [FormalYul.word x] (.some yulName_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .error EvmYul.Yul.Exception.Revert := by rw [show fuel + (extra + 1200) = (fuel + extra) + 1200 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_97, + simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h70 := - call_fun_expRayToWad_68_revert_direct (x := x) (fuel := fuel + extra) (extra := 191) + call_fun_expRayToWad_revert_direct (x := x) (fuel := fuel + extra) (extra := 191) (shared := shared) (h1 := h1) (h2 := h2) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at h70 simp +decide [EvmYul.Yul.execCall.eq_def, @@ -139,8 +142,8 @@ theorem call_fun_wrap_expRayToWad_revert_direct h70] set_option maxHeartbeats 8000000 in -/-- The external entrypoint `external_fun_wrap_expRayToWad_97` decodes the calldata argument `x` -(`callvalue` is 0, so the value guard is skipped) and forwards to `fun_wrap_expRayToWad_97`, which +/-- The external entrypoint `external_fun_wrap_expRayToWad` decodes the calldata argument `x` +(`callvalue` is 0, so the value guard is skipped) and forwards to `fun_wrap_expRayToWad`, which reverts for out-of-range `x`. -/ theorem external_fun_wrap_expRayToWad_calldata_revert (x : Nat) (store : EvmYul.Yul.VarStore) @@ -152,7 +155,7 @@ theorem external_fun_wrap_expRayToWad_calldata_revert rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_97, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Seam/Value.lean b/formal/exp/ExpProof/ExpProof/Seam/Value.lean index 5f003e973..b171eb4eb 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Value.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Value.lean @@ -28,20 +28,26 @@ theorem evmShl_one_c0 : rw [evmShl_eq (by norm_num) (by norm_num)]; norm_num set_option maxHeartbeats 8000000 in -/-- The kernel `fun__expRayToWad_78` at the scale point `x = 0`: every `mul` by `x` vanishes, so -`k = t = v = 0`, the rational form evaluates to `2^126`, and the final `iszero(0) = 1` fix-up makes -the result exactly `10^18`. -/ -theorem call_fun__expRayToWad_78_zero_direct +/-- The shared kernel at the scale point `x = 0`: every `mul` by `x` vanishes, so `t = v = 0`, +the rational form evaluates to `2^126`, and the final `iszero(0) = 1` fix-up makes the result +exactly `10^18`. -/ +theorem call_fun__expRayKernel_zero_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 700)) [FormalYul.word 0] (.some "fun__expRayToWad_78") + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 0)) + EvmYul.Yul.call (fuel + (extra + 700)) + [FormalYul.word 0, FormalYul.word k, + FormalYul.word 0x6f05b59d3b2000000000000000000000, FormalYul.word (evmSub 0x43 k), + FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7] + (.some yulName_fun__expRayKernel) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 1000000000000000000]) := by + dsimp only rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayToWad_78] - simp only [yulFunction_fun__expRayToWad_78, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayKernel] + simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_355, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -54,37 +60,63 @@ theorem call_fun__expRayToWad_78_zero_direct EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 676) + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 676) (shared := shared) (hlookup := hlookup)] set_option maxHeartbeats 8000000 in -/-- `fun_expRayToWad_68` at `x = 0`: the overflow guard `iszero(slt(0, threshold)) = 0` is false, so +/-- `fun_expRayToWad` at `x = 0`: the overflow guard `iszero(slt(0, threshold)) = 0` is false, so the panic branch is skipped and the kernel result `10^18` is forwarded. -/ -theorem call_fun_expRayToWad_68_zero_direct +theorem call_fun_expRayToWad_zero_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 900)) [FormalYul.word 0] (.some "fun_expRayToWad_68") + EvmYul.Yul.call (fuel + (extra + 900)) [FormalYul.word 0] (.some yulName_fun_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 1000000000000000000]) := by rw [show fuel + (extra + 900) = (fuel + extra) + 900 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad_68] - simp only [yulFunction_fun_expRayToWad_68, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad] + simp only [yulFunction_fun_expRayToWad, yulFunction_fun_expRayToWad_190, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv44 := - call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) (extra := 767) + have hconstHi := + call_constant__EXP_RAY_TO_WAD_HI_direct (fuel := fuel + extra) (extra := 732) (shared := shared) (hlookup := hlookup) + have hcleanupHi := + call_cleanup_t_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) + (extra := 867) (shared := shared) (hlookup := hlookup) have hcleanup := call_cleanup_t_int256_direct (v := 0) (fuel := fuel + extra) (extra := 865) (shared := shared) (hlookup := hlookup) + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 0)) + have hoctave := + call_fun__octave_direct (x := 0) (fuel := fuel + extra) (extra := 767) + (shared := shared) (hlookup := hlookup) + have hscale := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 721) + (shared := shared) (hlookup := hlookup) + have hconv67 := + call_convert_67_to_int256_direct (fuel := fuel + extra) (extra := 759) + (shared := shared) (hlookup := hlookup) + have hwrapSub := + call_wrapping_sub_t_int256_direct (x := 0x43) (y := k) (fuel := fuel + extra) + (extra := 796) (shared := shared) (hlookup := hlookup) + have hshift := + call_convert_int256_to_uint256_direct (v := evmSub 0x43 k) (fuel := fuel + extra) + (extra := 755) (shared := shared) (hlookup := hlookup) + have hzeroCutoff := + call_constant__WAD_ZERO_MAX_direct (fuel := fuel + extra) (extra := 714) + (shared := shared) (hlookup := hlookup) have hkernel := - call_fun__expRayToWad_78_zero_direct (fuel := fuel + extra) (extra := 187) + call_fun__expRayKernel_zero_direct (fuel := fuel + extra) (extra := 173) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hconv44 hcleanup hkernel + have hconvertOut := + call_convert_uint256_to_int256_direct (v := 1000000000000000000) (fuel := fuel + extra) + (extra := 752) (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hoctave hscale hconv67 + simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertOut simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -96,27 +128,28 @@ theorem call_fun_expRayToWad_68_zero_direct Finmap.lookup_insert, FormalYul.word, call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 876) (shared := shared) (hlookup := hlookup), - hcleanup, hconv44, hkernel] + hconstHi, hcleanupHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, + hzeroCutoff, hkernel, hconvertOut, k] set_option maxHeartbeats 8000000 in -/-- `fun_wrap_expRayToWad_97` at `x = 0` forwards to `fun_expRayToWad_68`, giving `10^18`. -/ +/-- `fun_wrap_expRayToWad` at `x = 0` forwards to `fun_expRayToWad`, giving `10^18`. -/ theorem call_fun_wrap_expRayToWad_zero_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word 0] (.some "fun_wrap_expRayToWad_97") + EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word 0] (.some yulName_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 1000000000000000000]) := by rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_97, + simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h70 := - call_fun_expRayToWad_68_zero_direct (fuel := fuel + extra) (extra := 191) + call_fun_expRayToWad_zero_direct (fuel := fuel + extra) (extra := 191) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at h70 simp +decide [EvmYul.Yul.execCall.eq_def, @@ -148,7 +181,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_result rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_97, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -231,7 +264,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_97, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -409,18 +442,19 @@ theorem run_exp_ray_to_wad_evm_zero : (hReturn := hReturn) (by simpa using hresult) set_option maxHeartbeats 4000000 in -/-- General kernel reduction for symbolic `x`: `fun__expRayToWad_78(x)` evaluates to the inline, -`let`-shared `evm*` arithmetic tree transcribed from `Exp.sol`'s `_expRayToWad` (constants are the -literal hex). No hand model: the RHS is the interpreter's own `evm*` ops. The foundation for -the runtime floor and monotonicity claims. -/ -theorem call_fun__expRayToWad_78_direct - (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) +/-- General kernel reduction for symbolic inputs: the shared kernel evaluates to the inline, +`let`-shared `evm*` arithmetic tree. -/ +theorem call_fun__expRayKernel_direct + (x k scale shift zeroCutoff fuel extra : Nat) + (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 700)) [FormalYul.word x] (.some "fun__expRayToWad_78") + EvmYul.Yul.call (fuel + (extra + 700)) + [FormalYul.word x, FormalYul.word k, FormalYul.word scale, FormalYul.word shift, + FormalYul.word zeroCutoff] + (.some yulName_fun__expRayKernel) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word ( - let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) let v := evmShr 0x87 (evmMul t t) @@ -435,15 +469,15 @@ theorem call_fun__expRayToWad_78_direct (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) let tod := evmSar 0x81 (evmMul t od) - let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) - let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + let r0 := evmDiv (evmMul scale (evmAdd ev tod)) (evmSub ev tod) + let r1 := evmShr shift (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1) + (evmMul (evmSlt zeroCutoff x) r1) )]) := by rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayToWad_78] - simp only [yulFunction_fun__expRayToWad_78, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayKernel] + simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_355, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -456,7 +490,7 @@ theorem call_fun__expRayToWad_78_direct EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 676) + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 676) (shared := shared) (hlookup := hlookup)] apply FormalYul.Preservation.eq_of_wordNat_eq simp only [FormalYul.Preservation.wordNat_shiftRight, FormalYul.Preservation.wordNat_shiftLeft, @@ -473,15 +507,15 @@ theorem call_fun__expRayToWad_78_direct FormalYul.Preservation.u256_evmAdd] set_option maxHeartbeats 4000000 in -/-- `fun_expRayToWad_68(x)` for a signed input strictly below the threshold: the overflow guard +/-- `fun_expRayToWad(x)` for a signed input strictly below the threshold: the overflow guard `iszero(slt(x, C)) = 0` is skipped (via `slt_thresh_lt`), so the kernel result — the `evm*` tree — is forwarded. -/ -theorem call_fun_expRayToWad_68_direct +theorem call_fun_expRayToWad_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : - EvmYul.Yul.call (fuel + (extra + 900)) [FormalYul.word x] (.some "fun_expRayToWad_68") + EvmYul.Yul.call (fuel + (extra + 900)) [FormalYul.word x] (.some yulName_fun_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word ( let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) @@ -502,26 +536,75 @@ theorem call_fun_expRayToWad_68_direct let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) )]) := by rw [show fuel + (extra + 900) = (fuel + extra) + 900 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad_68] - simp only [yulFunction_fun_expRayToWad_68, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad] + simp only [yulFunction_fun_expRayToWad, yulFunction_fun_expRayToWad_190, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv44 := - call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) (extra := 767) + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + have hconstHi := + call_constant__EXP_RAY_TO_WAD_HI_direct (fuel := fuel + extra) (extra := 732) (shared := shared) (hlookup := hlookup) + have hcleanupHi := + call_cleanup_t_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) + (extra := 867) (shared := shared) (hlookup := hlookup) have hcleanup := call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 865) (shared := shared) (hlookup := hlookup) + have hoctave := + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 767) + (shared := shared) (hlookup := hlookup) + have hscale := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 721) + (shared := shared) (hlookup := hlookup) + have hconv67 := + call_convert_67_to_int256_direct (fuel := fuel + extra) (extra := 759) + (shared := shared) (hlookup := hlookup) + have hwrapSub := + call_wrapping_sub_t_int256_direct (x := 0x43) (y := k) (fuel := fuel + extra) + (extra := 796) (shared := shared) (hlookup := hlookup) + have hshift := + call_convert_int256_to_uint256_direct (v := evmSub 0x43 k) (fuel := fuel + extra) + (extra := 755) (shared := shared) (hlookup := hlookup) + have hzeroCutoff := + call_constant__WAD_ZERO_MAX_direct (fuel := fuel + extra) (extra := 714) + (shared := shared) (hlookup := hlookup) have hkernel := - call_fun__expRayToWad_78_direct (x := x) (fuel := fuel + extra) (extra := 187) + call_fun__expRayKernel_direct (x := x) (k := k) + (scale := 0x6f05b59d3b2000000000000000000000) (shift := evmSub 0x43 k) + (zeroCutoff := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) + (fuel := fuel + extra) (extra := 173) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hconv44 hcleanup hkernel + have hconvertOut := + call_convert_uint256_to_int256_direct + (v := + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) + (fuel := fuel + extra) (extra := 752) (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hoctave hscale hconv67 + simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertOut simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -534,17 +617,18 @@ theorem call_fun_expRayToWad_68_direct slt_thresh_lt hval, call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 876) (shared := shared) (hlookup := hlookup), - hcleanup, hconv44, hkernel] + hconstHi, hcleanupHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, + hzeroCutoff, hkernel, hconvertOut, k] set_option maxHeartbeats 4000000 in -/-- `fun_wrap_expRayToWad_97(x)` for a signed input below the threshold forwards to -`fun_expRayToWad_68`, returning the `evm*` tree. -/ +/-- `fun_wrap_expRayToWad(x)` for a signed input below the threshold forwards to +`fun_expRayToWad`, returning the `evm*` tree. -/ theorem call_fun_wrap_expRayToWad_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : - EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word x] (.some "fun_wrap_expRayToWad_97") + EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word x] (.some yulName_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word ( let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) @@ -565,18 +649,18 @@ theorem call_fun_wrap_expRayToWad_direct let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) )]) := by rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_97, + simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h70 := - call_fun_expRayToWad_68_direct (x := x) (fuel := fuel + extra) (extra := 191) + call_fun_expRayToWad_direct (x := x) (fuel := fuel + extra) (extra := 191) (shared := shared) (hlookup := hlookup) (hval := hval) simp only [Nat.reduceAdd, FormalYul.word] at h70 simp +decide [EvmYul.Yul.execCall.eq_def, @@ -625,12 +709,12 @@ theorem external_fun_wrap_expRayToWad_calldata_result let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) ) := by rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_97, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -654,7 +738,7 @@ theorem external_fun_wrap_expRayToWad_calldata_result let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1)) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) with htree let baseStore := Finmap.insert "ret_0" (FormalYul.word tree) @@ -731,7 +815,7 @@ theorem external_fun_wrap_expRayToWad_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_97, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -755,7 +839,7 @@ theorem external_fun_wrap_expRayToWad_calldata_halts let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1)) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) with htree let baseStore := Finmap.insert "ret_0" (FormalYul.word tree) @@ -861,7 +945,7 @@ theorem external_fun_wrap_expRayToWad_dispatcher_state_result let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) ) := by rw [sharedFor_inherited_mstore_mk_eq_expSharedAfterFreePtr_raw] exact external_fun_wrap_expRayToWad_calldata_result (x := x) @@ -940,7 +1024,7 @@ theorem run_exp_ray_to_wad_evm_eq_tree let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) (evmSub ev tod) let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) - (evmMul (evmSlt (evmSub 0x00 0x85ebc478242540a11f5f1029) x) r1) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) ) := by obtain ⟨haltState, _haltValue, hhalt⟩ := external_fun_wrap_expRayToWad_dispatcher_state_halts x hval diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index 6a2c33ad5..d2b92dd47 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -72,6 +72,8 @@ def functionPrefixes : ModelKind → List String "fun_wrap_expRayToWad_", "fun_wrap_mulExpRay_", "fun_expRayToWad_", "fun_mulExpRay_", "fun__absSign_", "fun__scaleShift_", "fun__octave_", "fun__expRayKernel_", + "constant__EXP_RAY_TO_WAD_HI_", "constant__WAD_ZERO_MAX_", + "constant_ARITHMETIC_OVERFLOW_", "fun_panic_", "fun_or_", "fun_and_", "fun_clz_"] def requiredCalls : ModelKind → List String @@ -586,12 +588,25 @@ def uniqueNameWithPrefix | [] => .error s!"deployed Yul is missing a function with prefix {pfx}" | names => .error s!"deployed Yul prefix {pfx} is ambiguous: {commaSep names}" +def uniqueNameWithPrefixExcluding + (functions : List FunctionSource) (pfx excludedPfx : String) : Except String String := + match (namesWithPrefix functions pfx).filter fun name => !(name.startsWith excludedPfx) with + | [name] => .ok name + | [] => .error s!"deployed Yul is missing a function with prefix {pfx}" + | names => .error s!"deployed Yul prefix {pfx} is ambiguous: {commaSep names}" + def aliasByPrefix (functions : List FunctionSource) (stable pfx : String) : Except String GeneratedAlias := do let original ← uniqueNameWithPrefix functions pfx .ok { stable, original } +def aliasByPrefixExcluding + (functions : List FunctionSource) (stable pfx excludedPfx : String) : + Except String GeneratedAlias := do + let original ← uniqueNameWithPrefixExcluding functions pfx excludedPfx + .ok { stable, original } + def callWithPrefixFrom (functions : List FunctionSource) (caller pfx : String) : Except String String := do let callerFn ← findFunction functions caller @@ -740,6 +755,11 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : aliasByPrefix functions "fun__scaleShift" "fun__scaleShift_", aliasByPrefix functions "fun__octave" "fun__octave_", aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", + aliasByPrefix functions "constant__EXP_RAY_TO_WAD_HI" "constant__EXP_RAY_TO_WAD_HI_", + aliasByPrefixExcluding functions "constant__SCALE_MAX" "constant__SCALE_MAX_" "constant__SCALE_MAX_CLZ_", + aliasByPrefix functions "constant__WAD_ZERO_MAX" "constant__WAD_ZERO_MAX_", + aliasByPrefix functions "constant_ARITHMETIC_OVERFLOW" "constant_ARITHMETIC_OVERFLOW_", + aliasByPrefix functions "fun_panic" "fun_panic_", aliasByPrefix functions "fun_or" "fun_or_", aliasByPrefix functions "fun_and" "fun_and_", aliasByPrefix functions "fun_clz" "fun_clz_" From 9bc035c2a362a241e6216057e6926331cab55cc0 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 14:14:55 +0200 Subject: [PATCH 055/107] Add mulExpRay proof pipeline Co-Authored-By: Codex --- formal/common/Common/Word.lean | 83 +++ formal/exp/ExpProof/ExpProof/Mono/Consts.lean | 20 + .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 86 +++ formal/exp/ExpProof/ExpProof/Mul.lean | 87 +++ .../ExpProof/ExpProof/Seam/Dispatcher.lean | 287 ++++++++ .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 626 ++++++++++++++++++ .../exp/ExpProof/ExpProof/Spec/RealExp.lean | 72 ++ formal/exp/ExpProof/ExpProof/Theorems.lean | 74 ++- 8 files changed, 1329 insertions(+), 6 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Mono/MulTree.lean create mode 100644 formal/exp/ExpProof/ExpProof/Mul.lean diff --git a/formal/common/Common/Word.lean b/formal/common/Common/Word.lean index 96b5a4a97..1944aefbd 100644 --- a/formal/common/Common/Word.lean +++ b/formal/common/Common/Word.lean @@ -258,6 +258,89 @@ theorem evmSdiv_u256_left (a b : Nat) : evmSdiv (u256 a) b = evmSdiv a b := by theorem evmSdiv_u256_right (a b : Nat) : evmSdiv a (u256 b) = evmSdiv a b := by simp only [evmSdiv, u256_idem] +def evmXor (a b : Nat) : Nat := + u256 a ^^^ u256 b + +theorem u256_evmXor (a b : Nat) : u256 (evmXor a b) = evmXor a b := by + unfold evmXor + apply u256_eq_self_of_lt + rw [word_mod_eq] + apply Nat.xor_lt_two_pow + · exact u256_lt_word a + · exact u256_lt_word b + +theorem evmXor_u256_left (a b : Nat) : evmXor (u256 a) b = evmXor a b := by + simp only [evmXor, u256_idem] + +theorem evmXor_u256_right (a b : Nat) : evmXor a (u256 b) = evmXor a b := by + simp only [evmXor, u256_idem] + +theorem evmSar_lt_WORD_MOD (s v : Nat) : evmSar s v < WORD_MOD := by + have hs : s % WORD_MOD < WORD_MOD := Nat.mod_lt _ (by unfold WORD_MOD; positivity) + have hv : v % WORD_MOD < WORD_MOD := Nat.mod_lt _ (by unfold WORD_MOD; positivity) + unfold evmSar u256 + dsimp only + split_ifs + · unfold WORD_MOD; norm_num + · exact Nat.lt_of_le_of_lt (Nat.sub_le _ _) (by unfold WORD_MOD; norm_num) + · unfold WORD_MOD; norm_num + · exact Nat.lt_of_le_of_lt (Nat.div_le_self _ _) hv + +theorem u256_evmSar (s v : Nat) : u256 (evmSar s v) = evmSar s v := by + exact u256_eq_self_of_lt (evmSar_lt_WORD_MOD s v) + +theorem wordNat_xor (a b : EvmYul.UInt256) : + wordNat (EvmYul.UInt256.xor a b) = evmXor (wordNat a) (wordNat b) := by + cases a with + | mk av => + cases b with + | mk bv => + cases av with + | mk av hav => + cases bv with + | mk bv hbv => + have hav' : av < EvmYul.UInt256.size := by + simpa [EvmYul.UInt256.size] using hav + have hbv' : bv < EvmYul.UInt256.size := by + simpa [EvmYul.UInt256.size] using hbv + have hxorlt : Nat.xor av bv < EvmYul.UInt256.size := by + rw [show EvmYul.UInt256.size = 2 ^ 256 by rfl] + apply Nat.xor_lt_two_pow + · simpa [EvmYul.UInt256.size] using hav + · simpa [EvmYul.UInt256.size] using hbv + have hxormod : + Nat.xor av bv % + 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + Nat.xor av bv := by + simpa [EvmYul.UInt256.size] using Nat.mod_eq_of_lt hxorlt + have havmod : + av % 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + av := by + simpa [EvmYul.UInt256.size] using Nat.mod_eq_of_lt hav' + have hbvmod : + bv % 115792089237316195423570985008687907853269984665640564039457584007913129639936 = + bv := by + simpa [EvmYul.UInt256.size] using Nat.mod_eq_of_lt hbv' + simp [wordNat, evmXor, u256, WORD_MOD, EvmYul.UInt256.xor, Fin.xor, + EvmYul.UInt256.toNat, EvmYul.UInt256.size, hxormod, havmod, hbvmod] + rfl + +theorem uint256_ofNat_xor_eq_word_evmXor (a b : Nat) : + EvmYul.UInt256.xor (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b) = + word (evmXor a b) := by + apply FormalYul.Preservation.eq_of_wordNat_eq + simp only [wordNat_xor, FormalYul.Preservation.wordNat_ofNat, + FormalYul.Preservation.wordNat_word] + simp [evmXor_u256_left, evmXor_u256_right, u256_evmXor] + +theorem uint256_ofNat_sar_eq_word_evmSar (s v : Nat) : + EvmYul.UInt256.sar (EvmYul.UInt256.ofNat s) (EvmYul.UInt256.ofNat v) = + word (evmSar s v) := by + apply FormalYul.Preservation.eq_of_wordNat_eq + simp only [wordNat_sar, FormalYul.Preservation.wordNat_ofNat, + FormalYul.Preservation.wordNat_word] + simp [evmSar_u256_left, evmSar_u256_right, u256_evmSar] + /-! ## Shift and division floor lemmas (general shift amounts) -/ theorem evmShr_lt (s w : Nat) : evmShr s w < 2 ^ 256 := by diff --git a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean index 89444af2c..205bdb32c 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean @@ -41,7 +41,10 @@ abbrev odShift4 : Nat := 0x80 abbrev todShift : Nat := 0x81 abbrev foldShift : Nat := 0x43 abbrev scaleQ67 : Nat := 0x6f05b59d3b2000000000000000000000 +abbrev scaleMaxClz : Nat := 0x81 abbrev marginWord : Nat := 0x1 +abbrev xHiMulExpRay : Nat := 0x0116d70f49dec622d4bda70c52 +abbrev xLoZeroMulExpRay : Nat := 0xfffffffffffffffffffffffffffffffffffffffee270ddd64709e8aac2676ec3 theorem scaleQ67_eq : (scaleQ67 : Int) = 3814697265625 * 2 ^ 85 := by unfold scaleQ67; norm_num @@ -60,4 +63,21 @@ theorem int256_C0thresh : int256 C0thresh = 45401140326676417766828703956 := by unfold C0thresh int256 norm_num +theorem int256_xHiMulExpRay : int256 xHiMulExpRay = 86296823979713191022445399122 := by + unfold xHiMulExpRay int256 + norm_num + +theorem int256_xLoZeroMulExpRay : + int256 xLoZeroMulExpRay = -88376265521393026950697095485 := by + unfold xLoZeroMulExpRay int256 + norm_num + +theorem xHiMulExpRay_lt : xHiMulExpRay < 2 ^ 256 := by + unfold xHiMulExpRay + norm_num + +theorem xLoZeroMulExpRay_lt : xLoZeroMulExpRay < 2 ^ 256 := by + unfold xLoZeroMulExpRay + norm_num + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean new file mode 100644 index 000000000..3c4087d93 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -0,0 +1,86 @@ +import ExpProof.Mono.Tree + +/-! +# `mulExpRay` runtime normal form + +The dynamic-scale entrypoint shares the exponent kernel with `expRayToWad`. This file names the +extra word computations around that kernel: absolute-value/sign extraction, scale shift selection, +dynamic closing shift, and sign reapplication. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word + +set_option maxRecDepth 100000 + +/-- The sign mask produced by `sar(255, y)`: `0` for nonnegative inputs and `-1` as a word for +negative inputs. -/ +def signTree (y : Nat) : Nat := + evmSar 0xff y + +/-- Absolute value as a word, computed without negating `int256.min`. -/ +def absTree (y : Nat) : Nat := + evmSub (evmXor y (signTree y)) (signTree y) + +/-- The largest shift chosen by the compiled bit-length estimate, corrected by one if the shifted +magnitude exceeds `scaleQ67`. -/ +def scaleShiftTree (ay : Nat) : Nat := + let s := evmSub (evmClz ay) scaleMaxClz + evmSub s (evmGt (evmShl s ay) scaleQ67) + +/-- Dynamic pre-shift scale `abs(y) << S`. -/ +def mulScaleTree (y : Nat) : Nat := + evmShl (scaleShiftTree (absTree y)) (absTree y) + +/-- Dynamic closing shift `S - k`. -/ +def mulShiftTree (y x : Nat) : Nat := + evmSub (scaleShiftTree (absTree y)) (kTree x) + +/-- The dynamic-scaled quotient before the closing shift. -/ +def r0MulTree (y x : Nat) : Nat := + evmDiv (evmMul (mulScaleTree y) (evmAdd (evTree x) (todTree x))) + (evmSub (evTree x) (todTree x)) + +/-- The nonnegative magnitude returned by the shared kernel before the sign mask is applied. -/ +def mulMagnitudeTree (y x : Nat) : Nat := + evmAdd (evmIszero x) + (evmMul (evmSlt xLoZeroMulExpRay x) + (evmShr (mulShiftTree y x) (evmSub (r0MulTree y x) marginWord))) + +/-- Signed result word after applying `y`'s sign mask. -/ +def mulExpTree (y x : Nat) : Nat := + let m := mulMagnitudeTree y x + evmSub (evmXor m (signTree y)) (signTree y) + +theorem absTree_lt (y : Nat) : absTree y < 2 ^ 256 := by + unfold absTree + exact evmSub_lt _ _ + +theorem scaleShiftTree_lt (ay : Nat) : scaleShiftTree ay < 2 ^ 256 := by + unfold scaleShiftTree + exact evmSub_lt _ _ + +theorem mulScaleTree_lt (y : Nat) : mulScaleTree y < 2 ^ 256 := by + unfold mulScaleTree + exact evmShl_lt _ _ + +theorem mulShiftTree_lt (y x : Nat) : mulShiftTree y x < 2 ^ 256 := by + unfold mulShiftTree + exact evmSub_lt _ _ + +theorem r0MulTree_lt (y x : Nat) : r0MulTree y x < 2 ^ 256 := by + unfold r0MulTree + exact evmDiv_lt _ _ + +theorem mulMagnitudeTree_lt (y x : Nat) : mulMagnitudeTree y x < 2 ^ 256 := by + unfold mulMagnitudeTree + exact evmAdd_lt _ _ + +theorem mulExpTree_lt (y x : Nat) : mulExpTree y x < 2 ^ 256 := by + unfold mulExpTree + exact evmSub_lt _ _ + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean new file mode 100644 index 000000000..b781a387f --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -0,0 +1,87 @@ +import ExpProof.Mono.MulTree +import ExpProof.ExpYulRuntime +import ExpProof.Spec.RealExp + +/-! +# `mulExpRay` proof facade + +This module states the public runtime specifications for `mulExpRay` and exposes the proof +obligations that connect the compiled run to the arithmetic tree. The tree is defined in +`Mono.MulTree`; consumers supply proofs that the tree satisfies the real bracket and monotonicity +predicates below. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open ExpRealSpec + +noncomputable section + +/-- The public bracket spec for one successful `mulExpRay` run. -/ +def MulExpRayRunBracket (y x : Nat) : Prop := + ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ + MulExpRayBracket (int256 y) (int256 x) (int256 r) + +/-- The public monotonicity spec for two successful `mulExpRay` runs at a fixed multiplier. -/ +def MulExpRayRunMonotone (y x1 x2 : Nat) : Prop := + ∃ r1 r2, run_mul_exp_ray_evm y x1 = .ok r1 ∧ run_mul_exp_ray_evm y x2 = .ok r2 ∧ + MulExpRaySignedMonotone (int256 y) (int256 x1) (int256 x2) (int256 r1) (int256 r2) + +/-- Runtime bracket proof obligation for the named arithmetic tree. -/ +theorem mulExpRay_run_bracket_of_tree + {y x : Nat} + (hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x)) + (hbracket : MulExpRayBracket (int256 y) (int256 x) (int256 (mulExpTree y x))) : + MulExpRayRunBracket y x := + ⟨mulExpTree y x, hrun, hbracket⟩ + +/-- Runtime monotonicity proof obligation for the named arithmetic tree. -/ +theorem mulExpRay_run_monotone_of_tree + {y x1 x2 : Nat} + (hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1)) + (hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2)) + (hmono : MulExpRaySignedMonotone (int256 y) (int256 x1) (int256 x2) + (int256 (mulExpTree y x1)) (int256 (mulExpTree y x2))) : + MulExpRayRunMonotone y x1 x2 := + ⟨mulExpTree y x1, mulExpTree y x2, hrun1, hrun2, hmono⟩ + +/-- The zero-magnitude result satisfies the signed `mulExpRay` bracket for every exponent. -/ +theorem mulExpRayBracket_zero_result (x : Int) : + MulExpRayBracket 0 x 0 := by + simp [MulExpRayBracket, mulExpRayMagnitudeBracket_zero] + +/-- A proved zero-magnitude runtime result immediately satisfies the public bracket spec. -/ +theorem mulExpRay_run_bracket_zero_of_run {x : Nat} + (hrun : run_mul_exp_ray_evm 0 x = .ok 0) : + MulExpRayRunBracket 0 x := + ⟨0, hrun, mulExpRayBracket_zero_result (int256 x)⟩ + +/-- The `y = 10^18` magnitude target is the existing `expRayToWad` target. -/ +theorem mulExpRayMagnitudeTarget_wad (x : Int) : + mulExpRayMagnitudeTarget (10 ^ 18) x = expRayToWadTarget x := by + simp [mulExpRayMagnitudeTarget, expRayToWadTarget, WAD] + +/-- Existing `expRayToWad` floor brackets instantiate the `mulExpRay` bracket at `y = 10^18`. -/ +theorem floorOrOneLess_to_mulExpRayBracket_wad {x r : Int} + (hr : 0 ≤ r) (h : FloorOrOneLessBracket x r) : + MulExpRayBracket (10 ^ 18) x r := by + rw [MulExpRayBracket] + norm_num + have hw := mulExpRayMagnitudeTarget_wad x + norm_num at hw + exact ⟨hr, by simpa [hw] using h.1, by simpa [hw] using h.2⟩ + +/-- Runtime specialization proof obligation for the existing `expRayToWad` theorem stack. -/ +theorem mulExpRay_run_bracket_wad_of_exp + {x r : Nat} + (hrun : run_mul_exp_ray_evm (10 ^ 18) x = .ok r) + (hr : 0 ≤ int256 r) + (hexp : FloorOrOneLessBracket (int256 x) (int256 r)) : + MulExpRayRunBracket (10 ^ 18) x := + ⟨r, hrun, floorOrOneLess_to_mulExpRayBracket_wad hr hexp⟩ + +end + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean index 8606b5fd2..d3498308e 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean @@ -56,6 +56,43 @@ theorem expRayToWad_calldata_size (x : Nat) : FormalYul.bytes, ByteArray.size_append, ByteArray.size_push, ByteArray.size_empty, FormalYul.Preservation.encodeWord_size] +/-- Shared state after the dispatcher's `mstore(64,128)` free-pointer init, for the +`mulExpRay` calldata. -/ +def mulExpSharedAfterFreePtr (y x : Nat) : EvmYul.SharedState .Yul := + let shared := FormalYul.sharedFor yulContract (selector_mulExpRay ++ FormalYul.encodeWords [y, x]) + { shared with toMachineState := shared.toMachineState.mstore (FormalYul.word 64) (FormalYul.word 128) } + +@[simp] +theorem mulExpSharedAfterFreePtr_lookup (y x : Nat) : + (mulExpSharedAfterFreePtr y x).accountMap.find? + (mulExpSharedAfterFreePtr y x).executionEnv.codeOwner = + some (FormalYul.accountFor yulContract) := by + simp [mulExpSharedAfterFreePtr] + +@[simp] +theorem mulExpSharedAfterFreePtr_calldata (y x : Nat) : + (mulExpSharedAfterFreePtr y x).executionEnv.calldata = + selector_mulExpRay ++ FormalYul.encodeWords [y, x] := by + simp [mulExpSharedAfterFreePtr, FormalYul.sharedFor, FormalYul.envFor] + +@[simp] +theorem mulExpSharedAfterFreePtr_weiValue (y x : Nat) : + (mulExpSharedAfterFreePtr y x).executionEnv.weiValue = ({ val := 0 } : EvmYul.UInt256) := by + simp [mulExpSharedAfterFreePtr, FormalYul.sharedFor, FormalYul.envFor] + +@[simp] +theorem mulExpSharedAfterFreePtr_mload64 (y x : Nat) : + ((mulExpSharedAfterFreePtr y x).mload (FormalYul.word 64)).1 = FormalYul.word 128 := + FormalYul.Preservation.sharedFor_mload_freePtr_after_mstore yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x]) + +@[simp] +theorem mulExpRay_calldata_size (y x : Nat) : + (selector_mulExpRay ++ FormalYul.encodeWords [y, x]).size = 68 := by + simp [selector_mulExpRay, FormalYul.encodeWords, + FormalYul.bytes, ByteArray.size_append, ByteArray.size_push, ByteArray.size_empty, + FormalYul.Preservation.encodeWord_size] + @[simp] theorem calldataload_expRayToWad_arg_of_calldata (x : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -66,6 +103,26 @@ theorem calldataload_expRayToWad_arg_of_calldata simp [EvmYul.State.calldataload, EvmYul.Yul.State.toState, hdata, selector_expRayToWad, FormalYul.encodeWords] +@[simp] +theorem calldataload_mulExpRay_arg0_of_calldata + (y x : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + EvmYul.State.calldataload + (EvmYul.Yul.State.Ok shared store).toState (FormalYul.word 4) = + FormalYul.word y := by + exact FormalYul.Preservation.calldataload_two_args_first_of_calldata + 0x79 0xab 0xc0 0x89 y x shared store (by simpa [selector_mulExpRay] using hdata) + +@[simp] +theorem calldataload_mulExpRay_arg1_of_calldata + (y x : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + EvmYul.State.calldataload + (EvmYul.Yul.State.Ok shared store).toState (FormalYul.word 36) = + FormalYul.word x := by + exact FormalYul.Preservation.calldataload_two_args_second_of_calldata + 0x79 0xab 0xc0 0x89 y x shared store (by simpa [selector_mulExpRay] using hdata) + /-- `validator_revert_t_int256(value)` does `if iszero(eq(value, cleanup_t_int256(value))) {revert}`; since `cleanup_t_int256` is the identity the equality always holds, so it never reverts. -/ theorem call_validator_revert_t_int256_direct @@ -165,6 +222,129 @@ theorem call_abi_decode_tuple_t_int256_of_calldata EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, hdecode] +theorem call_abi_decode_t_int256_mul_arg0_of_calldata + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + EvmYul.Yul.call (fuel + (extra + 200)) [FormalYul.word 4, FormalYul.word 68] + (.some "abi_decode_t_int256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word y]) := by + rw [show fuel + (extra + 200) = (fuel + extra) + 200 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_abi_decode_t_int256] + simp only [yulFunction_abi_decode_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hvalidator := + call_validator_revert_t_int256_direct (v := y) (fuel := fuel + extra) (extra := 115) + (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hvalidator + have hload := + calldataload_mulExpRay_arg0_of_calldata y x shared + (Finmap.insert "offset" (FormalYul.word 4) + (Finmap.insert "end" (FormalYul.word 68) (Inhabited.default : EvmYul.Yul.VarStore))) + hdata + simp [FormalYul.word] at hload + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hload, hvalidator] + +theorem call_abi_decode_t_int256_mul_arg1_of_calldata + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + EvmYul.Yul.call (fuel + (extra + 200)) [FormalYul.word 36, FormalYul.word 68] + (.some "abi_decode_t_int256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word x]) := by + rw [show fuel + (extra + 200) = (fuel + extra) + 200 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_abi_decode_t_int256] + simp only [yulFunction_abi_decode_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hvalidator := + call_validator_revert_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 115) + (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hvalidator + have hload := + calldataload_mulExpRay_arg1_of_calldata y x shared + (Finmap.insert "offset" (FormalYul.word 36) + (Finmap.insert "end" (FormalYul.word 68) (Inhabited.default : EvmYul.Yul.VarStore))) + hdata + simp [FormalYul.word] at hload + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hload, hvalidator] + +/-- `abi_decode_tuple_t_int256t_int256(headStart, dataEnd)` decodes `(y, x)`. -/ +theorem call_abi_decode_tuple_t_int256t_int256_of_mul_calldata + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + EvmYul.Yul.call (fuel + (extra + 520)) [FormalYul.word 4, FormalYul.word 68] + (.some "abi_decode_tuple_t_int256t_int256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word y, FormalYul.word x]) := by + rw [show fuel + (extra + 520) = (fuel + extra) + 520 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_abi_decode_tuple_t_int256t_int256] + simp only [yulFunction_abi_decode_tuple_t_int256t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hdecode0 := + call_abi_decode_t_int256_mul_arg0_of_calldata (y := y) (x := x) + (fuel := fuel + extra) (extra := 313) + (shared := shared) + (store := Finmap.insert "offset" (FormalYul.word 0) + (Finmap.insert "headStart" (FormalYul.word 4) + (Finmap.insert "dataEnd" (FormalYul.word 68) + (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) (hdata := hdata) + have hdecode1 := + call_abi_decode_t_int256_mul_arg1_of_calldata (y := y) (x := x) + (fuel := fuel + extra) (extra := 312) + (shared := shared) + (store := Finmap.insert "offset" (FormalYul.word 32) + (Finmap.insert "value0" (FormalYul.word y) + (Finmap.insert "offset" (FormalYul.word 0) + (Finmap.insert "headStart" (FormalYul.word 4) + (Finmap.insert "dataEnd" (FormalYul.word 68) + (Inhabited.default : EvmYul.Yul.VarStore)))))) + (hlookup := hlookup) (hdata := hdata) + simp only [Nat.reduceAdd, FormalYul.word] at hdecode0 hdecode1 + have h436 : EvmYul.UInt256.ofNat 4 + EvmYul.UInt256.ofNat 32 = EvmYul.UInt256.ofNat 36 := by + decide + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h436, hdecode0, hdecode1] + /-- `allocate_unbounded() := mload(64)` — returns the current free pointer. -/ theorem call_allocate_unbounded_direct (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -400,6 +580,113 @@ theorem selectSwitchCase_expRayToWad_sharedFor_mk_raw (x : Nat) : (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])] := by simpa [FormalYul.word] using selectSwitchCase_expRayToWad_sharedFor_mk x +theorem sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr (y x : Nat) : + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (FormalYul.word 64) (FormalYul.word 128))) = + mulExpSharedAfterFreePtr y x := rfl + +theorem sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr_raw (y x : Nat) : + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) = + mulExpSharedAfterFreePtr y x := by + simpa [FormalYul.word] using sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr y x + +@[simp] +theorem sharedFor_mulExpRay_calldata_size (y x : Nat) : + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).executionEnv.calldata.size = 68 := by + simp [FormalYul.sharedFor, FormalYul.envFor, mulExpRay_calldata_size] + +theorem mulExpRay_selector_afterFreePtr (y x : Nat) : + EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (FormalYul.word 0)) + (FormalYul.word 224) = + FormalYul.word 2041299081 := by + have hselector := + FormalYul.Preservation.shiftRight_calldataload_selector_two_args_of_calldata + (shared := mulExpSharedAfterFreePtr y x) + (store := (Inhabited.default : EvmYul.Yul.VarStore)) + (a := 0x79) (b := 0xab) (c := 0xc0) (d := 0x89) (x := y) (y := x) + (by simp [selector_mulExpRay]) + simpa [EvmYul.fromBytesBigEndian, EvmYul.fromBytes', FormalYul.word] using hselector + +@[simp] +theorem mulExpRay_selector_sharedFor_mk (y x : Nat) : + EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (FormalYul.word 64) (FormalYul.word 128))) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (FormalYul.word 0)) + (FormalYul.word 224) = + FormalYul.word 2041299081 := by + rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr] + exact mulExpRay_selector_afterFreePtr y x + +@[simp] +theorem selectSwitchCase_mulExpRay_sharedFor_mk (y x : Nat) : + EvmYul.Yul.selectSwitchCase + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (FormalYul.word 64) (FormalYul.word 128))) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (FormalYul.word 0)) + (FormalYul.word 224)) + [(FormalYul.word 1099384363, + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), + (FormalYul.word 2041299081, + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = + some + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])] := by + rw [mulExpRay_selector_sharedFor_mk] + rfl + +theorem selectSwitchCase_mulExpRay_sharedFor_mk_raw (y x : Nat) : + EvmYul.Yul.selectSwitchCase + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + [(EvmYul.UInt256.ofNat 1099384363, + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), + (EvmYul.UInt256.ofNat 2041299081, + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = + some + [EvmYul.Yul.Ast.Stmt.ExprStmtCall + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])] := by + simpa [FormalYul.word] using selectSwitchCase_mulExpRay_sharedFor_mk y x + /-- Revert-analogue of `Preservation.runContract_ok_of_dispatcherReturn`: if the bare dispatcher `exec` on `stateFor` reverts, the wrapped `runContract` returns `.error "revert"`. Contract polymorphic; mirrors `ln`'s lemma verbatim. -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 0d6aa7c5d..72b63f202 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -1,5 +1,6 @@ import ExpProof.ExpYulProof import Common.Word +import ExpProof.Mono.MulTree import FormalYul.Preservation /-! @@ -800,4 +801,629 @@ theorem call_convert_uint8_to_uint256_17_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] +theorem call_zero_value_for_split_t_bool_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [] (.some "zero_value_for_split_t_bool") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_zero_value_for_split_t_bool] + simp only [yulFunction_zero_value_for_split_t_bool, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_0_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_0_by_1") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_0_by_1] + simp only [yulFunction_cleanup_t_rational_0_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_2_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_2_by_1") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_2_by_1] + simp only [yulFunction_cleanup_t_rational_2_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_129_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_129_by_1") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_129_by_1] + simp only [yulFunction_cleanup_t_rational_129_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_X_HI_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_86296823979713191022445399122_by_1") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_86296823979713191022445399122_by_1] + simp only [yulFunction_cleanup_t_rational_86296823979713191022445399122_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_cleanup_t_rational_X_LO_ZERO_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_minus_88376265521393026950697095485_by_1") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_minus_88376265521393026950697095485_by_1] + simp only [yulFunction_cleanup_t_rational_minus_88376265521393026950697095485_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_convert_0_to_int256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0] + (.some "convert_t_rational_0_by_1_to_t_int256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_0_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_0_by_1_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_0_direct (v := 0) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := 0) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_2_to_int256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 2] + (.some "convert_t_rational_2_by_1_to_t_int256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 2]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_2_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_2_by_1_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_2_direct (v := 2) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 2) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := 2) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_129_to_uint256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0x81] + (.some "convert_t_rational_129_by_1_to_t_uint256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x81]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_129_by_1_to_t_uint256] + simp only [yulFunction_convert_t_rational_129_by_1_to_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_129_direct (v := 0x81) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x81) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0x81) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x81) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_uint256_direct (v := 0x81) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x81) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_X_HI_to_int256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word xHiMulExpRay] + (.some "convert_t_rational_86296823979713191022445399122_by_1_to_t_int256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xHiMulExpRay]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_86296823979713191022445399122_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_86296823979713191022445399122_by_1_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_X_HI_direct (v := xHiMulExpRay) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word xHiMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := xHiMulExpRay) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word xHiMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := xHiMulExpRay) (fuel := fuel + extra) (extra := 96) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word xHiMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word, xHiMulExpRay] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, xHiMulExpRay, h1, h2, h3] + +theorem call_convert_X_LO_ZERO_to_int256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word xLoZeroMulExpRay] + (.some "convert_t_rational_minus_88376265521393026950697095485_by_1_to_t_int256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xLoZeroMulExpRay]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_minus_88376265521393026950697095485_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_minus_88376265521393026950697095485_by_1_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_X_LO_ZERO_direct (v := xLoZeroMulExpRay) (fuel := fuel + extra) + (extra := 92) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word xLoZeroMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := xLoZeroMulExpRay) (fuel := fuel + extra) (extra := 94) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word xLoZeroMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := xLoZeroMulExpRay) (fuel := fuel + extra) (extra := 96) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word xLoZeroMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word, xLoZeroMulExpRay] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, xLoZeroMulExpRay, h1, h2, h3] + +theorem call_constant__X_HI_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant__X_HI_139") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xHiMulExpRay]) := by + rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__X_HI_139] + simp only [yulFunction_constant__X_HI_139, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hconv := + call_convert_X_HI_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) + (shared := shared) + (store := Finmap.insert "expr_138" (FormalYul.word xHiMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word, xHiMulExpRay] at hconv + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, xHiMulExpRay, hconv] + +theorem call_constant__X_LO_ZERO_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant__X_LO_ZERO_143") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xLoZeroMulExpRay]) := by + rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__X_LO_ZERO_143] + simp only [yulFunction_constant__X_LO_ZERO_143, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hconv := + call_convert_X_LO_ZERO_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) + (shared := shared) + (store := Finmap.insert "expr_142" (FormalYul.word xLoZeroMulExpRay) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word, xLoZeroMulExpRay] at hconv + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, xLoZeroMulExpRay, hconv] + +theorem call_constant__SCALE_MAX_CLZ_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant__SCALE_MAX_CLZ_129") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word scaleMaxClz]) := by + rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX_CLZ_129] + simp only [yulFunction_constant__SCALE_MAX_CLZ_129, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hconv := + call_convert_129_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) + (shared := shared) + (store := Finmap.insert "expr_128" (FormalYul.word scaleMaxClz) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word, scaleMaxClz] at hconv + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, scaleMaxClz, hconv] + +theorem call_wrapping_sub_t_uint256_direct + (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word x, FormalYul.word y] + (.some "wrapping_sub_t_uint256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmSub x y)]) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_wrapping_sub_t_uint256] + simp only [yulFunction_wrapping_sub_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hcleanup := + call_cleanup_t_uint256_direct (v := evmSub x y) (fuel := fuel + extra) (extra := 56) + (shared := shared) + (store := Finmap.insert "x" (FormalYul.word x) + (Finmap.insert "y" (FormalYul.word y) (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := hlookup) + simp [FormalYul.word] at hcleanup + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, hcleanup] + +theorem call_fun_clz_direct + (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word x] (.some yulName_fun_clz) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmClz x)]) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_clz] + simp only [yulFunction_fun_clz, yulFunction_fun_clz_96, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_clz_eq_word_evmClz, + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 56) + (shared := shared) (hlookup := hlookup)] + +theorem call_shift_left_dynamic_direct + (bits value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 40)) [FormalYul.word bits, FormalYul.word value] + (.some "shift_left_dynamic") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmShl bits value)]) := by + rw [show fuel + (extra + 40) = (fuel + extra) + 40 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_shift_left_dynamic] + simp only [yulFunction_shift_left_dynamic, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl] + +theorem call_shift_left_t_uint256_t_uint256_direct + (value bits fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 180)) [FormalYul.word value, FormalYul.word bits] + (.some "shift_left_t_uint256_t_uint256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmShl bits value)]) := by + rw [show fuel + (extra + 180) = (fuel + extra) + 180 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_shift_left_t_uint256_t_uint256] + simp only [yulFunction_shift_left_t_uint256_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hbits := + call_cleanup_t_uint256_direct (v := bits) (fuel := fuel + extra) (extra := 156) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word bits) (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := hlookup) + have hvalue := + call_cleanup_t_uint256_direct (v := value) (fuel := fuel + extra) (extra := 151) + (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word bits) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word bits) (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + have hshift := + call_shift_left_dynamic_direct (bits := bits) (value := value) (fuel := fuel + extra) + (extra := 133) (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word bits) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word bits) (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + have hcleanup := + call_cleanup_t_uint256_direct (v := evmShl bits value) (fuel := fuel + extra) (extra := 155) + (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word bits) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word bits) (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + simp [FormalYul.word] at hbits hvalue hshift hcleanup + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hbits, hvalue, hshift, hcleanup] + +theorem call_fun_or_direct + (a b fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word a, FormalYul.word b] (.some yulName_fun_or) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmOr a b)]) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_or] + simp only [yulFunction_fun_or, yulFunction_fun_or_12, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_or_eq_word_evmOr, + call_zero_value_for_split_t_bool_direct (fuel := fuel + extra) (extra := 56) + (shared := shared) (hlookup := hlookup)] + +theorem call_fun_and_direct + (a b fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word a, FormalYul.word b] (.some yulName_fun_and) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmAnd a b)]) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_and] + simp only [yulFunction_fun_and, yulFunction_fun_and_23, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_and_eq_word_evmAnd, + call_zero_value_for_split_t_bool_direct (fuel := fuel + extra) (extra := 56) + (shared := shared) (hlookup := hlookup)] + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean b/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean index e307f4a5d..f459d8996 100644 --- a/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean +++ b/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean @@ -70,6 +70,78 @@ theorem expRayToWadTarget_zero : expRayToWadTarget 0 = (WAD : Real) := by theorem floorOrOneLess_zero : FloorOrOneLessBracket 0 (10 ^ 18) := by constructor <;> rw [expRayToWadTarget_zero] <;> simp [WAD] +/-! ## `mulExpRay` magnitude target -/ + +/-- `A = abs(y) · exp(x / 10^27)`, the nonnegative real magnitude target of `mulExpRay`. -/ +def mulExpRayMagnitudeTarget (y x : Int) : Real := + (y.natAbs : Real) * Real.exp ((x : Real) / (RAY : Real)) + +/-- **Magnitude floor-or-one-less bracket.** The nonnegative magnitude result never exceeds the +target magnitude and is under it by strictly less than two output units. -/ +def MulExpRayMagnitudeBracket (y x m : Int) : Prop := + 0 ≤ m ∧ (m : Real) ≤ mulExpRayMagnitudeTarget y x ∧ + mulExpRayMagnitudeTarget y x < (m : Real) + 2 + +/-- **Signed magnitude bracket.** The runtime result is interpreted by removing `y`'s sign before +checking the magnitude bracket. -/ +def MulExpRayBracket (y x r : Int) : Prop := + if y < 0 then MulExpRayMagnitudeBracket y x (-r) else MulExpRayMagnitudeBracket y x r + +/-- The exact real target of `mulExpRay`, including sign. -/ +def mulExpRayTarget (y x : Int) : Real := + (y : Real) * Real.exp ((x : Real) / (RAY : Real)) + +/-- Monotonicity in `x` follows `y`'s sign: positive magnitudes are nondecreasing, negative +magnitudes are nonincreasing, and zero is constant. -/ +def MulExpRaySignedMonotone (y x1 x2 r1 r2 : Int) : Prop := + x1 ≤ x2 ∧ if y < 0 then r2 ≤ r1 else r1 ≤ r2 + +theorem mulExpRayMagnitudeTarget_nonneg (y x : Int) : + 0 ≤ mulExpRayMagnitudeTarget y x := by + unfold mulExpRayMagnitudeTarget + positivity + +theorem mulExpRayMagnitudeTarget_mono {y x1 x2 : Int} (hle : x1 ≤ x2) : + mulExpRayMagnitudeTarget y x1 ≤ mulExpRayMagnitudeTarget y x2 := by + unfold mulExpRayMagnitudeTarget + have hR : (0 : Real) ≤ (RAY : Real) := by norm_num [RAY] + have hx : ((x1 : Real) / (RAY : Real)) ≤ ((x2 : Real) / (RAY : Real)) := by + exact div_le_div_of_nonneg_right (by exact_mod_cast hle) hR + exact mul_le_mul_of_nonneg_left (Real.exp_le_exp.mpr hx) (by positivity) + +theorem mulExpRayTarget_mono_nonneg {y x1 x2 : Int} (hy : 0 ≤ y) (hle : x1 ≤ x2) : + mulExpRayTarget y x1 ≤ mulExpRayTarget y x2 := by + unfold mulExpRayTarget + have hR : (0 : Real) ≤ (RAY : Real) := by norm_num [RAY] + have hx : ((x1 : Real) / (RAY : Real)) ≤ ((x2 : Real) / (RAY : Real)) := by + exact div_le_div_of_nonneg_right (by exact_mod_cast hle) hR + exact mul_le_mul_of_nonneg_left (Real.exp_le_exp.mpr hx) (by exact_mod_cast hy) + +theorem mulExpRayTarget_antitone_neg {y x1 x2 : Int} (hy : y < 0) (hle : x1 ≤ x2) : + mulExpRayTarget y x2 ≤ mulExpRayTarget y x1 := by + unfold mulExpRayTarget + have hR : (0 : Real) ≤ (RAY : Real) := by norm_num [RAY] + have hx : ((x1 : Real) / (RAY : Real)) ≤ ((x2 : Real) / (RAY : Real)) := by + exact div_le_div_of_nonneg_right (by exact_mod_cast hle) hR + exact mul_le_mul_of_nonpos_left (Real.exp_le_exp.mpr hx) (by exact_mod_cast (le_of_lt hy)) + +theorem mulExpRayTarget_signed_mono {y x1 x2 : Int} (hle : x1 ≤ x2) : + if y < 0 then mulExpRayTarget y x2 ≤ mulExpRayTarget y x1 + else mulExpRayTarget y x1 ≤ mulExpRayTarget y x2 := by + by_cases hy : y < 0 + · simp [hy, mulExpRayTarget_antitone_neg hy hle] + · have hy0 : 0 ≤ y := by omega + simp [hy, mulExpRayTarget_mono_nonneg hy0 hle] + +theorem mulExpRayMagnitudeBracket_zero (x r : Int) (hr : r = 0) : + MulExpRayMagnitudeBracket 0 x r := by + subst hr + constructor + · norm_num + · constructor + · simp [mulExpRayMagnitudeTarget] + · simp [mulExpRayMagnitudeTarget] + end end ExpRealSpec diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 79940ed6d..0b2d7d24b 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -6,17 +6,19 @@ import ExpProof.Floor.PublicUncond import ExpProof.Floor.R0BoundHolds import ExpProof.Floor.R0Bound import ExpProof.Floor.RoundTrip +import ExpProof.Mul /-! -# `expRayToWad` — proven properties of the compiled runtime (signpost) +# `expRayToWad` and `mulExpRay` — compiled-runtime proof signpost This file is the at-a-glance demonstration that the documented properties hold for *the interpretation of the implementation*: the EVMYulLean execution of the compiled `ExpWrapper` Yul, -`run_exp_ray_to_wad_evm` (defined in the generated `ExpYulRuntime`). Each property below is a -runtime-level theorem; the axiom gate at the bottom pins it to Lean's three standard axioms, so a -stray `sorry` (or any new axiom) breaks the build. +`run_exp_ray_to_wad_evm` and `run_mul_exp_ray_evm` (defined in the generated `ExpYulRuntime`). +Each listed theorem is a runtime-level theorem or a runtime proof obligation; the axiom gate at the +bottom pins it to Lean's three standard axioms, so a stray `sorry` (or any new axiom) breaks the +build. -## Documented properties (about the runtime) +## Documented `expRayToWad` properties (about the runtime) | Property | Theorem | |---------------------------------------------------|--------------------------------------------------| @@ -28,7 +30,7 @@ stray `sorry` (or any new axiom) breaks the build. | Monotone in the input | `run_exp_ray_to_wad_evm_mono_unconditional` | | `lnWadToRay` round trip | `run_exp_ray_to_wad_evm_lnWadToRay_roundTrip_if` | -Every property is unconditional. The monotonicity analytic core (`RegionMonotonicityFacts`, +Every `expRayToWad` property is unconditional. The monotonicity analytic core (`RegionMonotonicityFacts`, reduced to the octave-seam `r0` doubling bound `SeamR0Bound`) is discharged by `seamR0Bound_holds`; the floor brackets consume the discharged accumulator facts (`accumReal_over`, `accumReal_under`, `belowC_target_lt_one`) directly. @@ -91,6 +93,66 @@ example (x1 x2 : Nat) #guard_msgs in #print axioms seamR0Bound_holds +/-! ## `mulExpRay` + +The public spec for `mulExpRay` is a signed magnitude bracket and a monotonicity predicate in the +exponent argument. Positive multipliers are nondecreasing in `x`; negative multipliers are +nonincreasing. The runtime facade below reduces successful-run bracket and monotonicity statements +to the compiled arithmetic tree `mulExpTree`. +-/ + +/-- A tree equality plus a tree bracket gives the public runtime bracket spec. -/ +example {y x : Nat} + (hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x)) + (hbracket : ExpRealSpec.MulExpRayBracket + (FormalYul.Preservation.int256 y) (FormalYul.Preservation.int256 x) + (FormalYul.Preservation.int256 (mulExpTree y x))) : + MulExpRayRunBracket y x := + mulExpRay_run_bracket_of_tree hrun hbracket + +/-- A tree equality plus ordered tree results gives the public runtime monotonicity spec. -/ +example {y x1 x2 : Nat} + (hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1)) + (hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2)) + (hmono : ExpRealSpec.MulExpRaySignedMonotone + (FormalYul.Preservation.int256 y) (FormalYul.Preservation.int256 x1) + (FormalYul.Preservation.int256 x2) (FormalYul.Preservation.int256 (mulExpTree y x1)) + (FormalYul.Preservation.int256 (mulExpTree y x2))) : + MulExpRayRunMonotone y x1 x2 := + mulExpRay_run_monotone_of_tree hrun1 hrun2 hmono + +/-- Zero magnitude satisfies the signed bracket for every exponent. -/ +example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := + mulExpRayBracket_zero_result x + +/-- Existing `expRayToWad` floor brackets instantiate the `y = 10^18` specialization. -/ +example {x r : Int} (hr : 0 ≤ r) + (h : ExpRealSpec.FloorOrOneLessBracket x r) : + ExpRealSpec.MulExpRayBracket (10 ^ 18) x r := + floorOrOneLess_to_mulExpRayBracket_wad hr h + +/-- The real target is monotone in the exponent with direction determined by the multiplier sign. -/ +example {y x1 x2 : Int} (hle : x1 ≤ x2) : + if y < 0 then ExpRealSpec.mulExpRayTarget y x2 ≤ ExpRealSpec.mulExpRayTarget y x1 + else ExpRealSpec.mulExpRayTarget y x1 ≤ ExpRealSpec.mulExpRayTarget y x2 := + ExpRealSpec.mulExpRayTarget_signed_mono hle + +/-- info: 'ExpYul.mulExpRay_run_bracket_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_bracket_of_tree + +/-- info: 'ExpYul.mulExpRay_run_monotone_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_monotone_of_tree + +/-- info: 'ExpYul.mulExpRayBracket_zero_result' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRayBracket_zero_result + +/-- info: 'ExpRealSpec.mulExpRayTarget_signed_mono' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms ExpRealSpec.mulExpRayTarget_signed_mono + /-! ## `Real.exp` floor brackets Each bracket is stated on the runtime result `r` (`run_exp_ray_to_wad_evm x = .ok r`) against the From 79b0eda5e753b7ad89f5aebb1150ec80d5a2c745 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 14:59:10 +0200 Subject: [PATCH 056/107] Document mulExpRay monotonicity specs Co-Authored-By: Codex --- formal/exp/ExpProof/ExpProof/Mul.lean | 39 +++++++++-- .../exp/ExpProof/ExpProof/Spec/RealExp.lean | 49 ++++++++++++++ formal/exp/ExpProof/ExpProof/Theorems.lean | 64 +++++++++++++++++-- src/vendor/Exp.sol | 14 +++- 4 files changed, 154 insertions(+), 12 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index b781a387f..30e74a201 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -7,8 +7,8 @@ import ExpProof.Spec.RealExp This module states the public runtime specifications for `mulExpRay` and exposes the proof obligations that connect the compiled run to the arithmetic tree. The tree is defined in -`Mono.MulTree`; consumers supply proofs that the tree satisfies the real bracket and monotonicity -predicates below. +`Mono.MulTree`; consumers supply proofs that the tree satisfies the real bracket and x/y +monotonicity predicates below. -/ namespace ExpYul @@ -24,11 +24,22 @@ def MulExpRayRunBracket (y x : Nat) : Prop := ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ MulExpRayBracket (int256 y) (int256 x) (int256 r) -/-- The public monotonicity spec for two successful `mulExpRay` runs at a fixed multiplier. -/ +/-- The public monotonicity-in-`x` spec for two successful runs at a fixed multiplier. -/ def MulExpRayRunMonotone (y x1 x2 : Nat) : Prop := ∃ r1 r2, run_mul_exp_ray_evm y x1 = .ok r1 ∧ run_mul_exp_ray_evm y x2 = .ok r2 ∧ MulExpRaySignedMonotone (int256 y) (int256 x1) (int256 x2) (int256 r1) (int256 r2) +/-- The public monotonicity-in-`y` spec for two successful runs at a fixed exponent. -/ +def MulExpRayRunYMonotone (y1 y2 x : Nat) : Prop := + ∃ r1 r2, run_mul_exp_ray_evm y1 x = .ok r1 ∧ run_mul_exp_ray_evm y2 x = .ok r2 ∧ + MulExpRayYMonotone (int256 y1) (int256 y2) (int256 x) (int256 r1) (int256 r2) + +/-- The public sign-aware joint monotonicity spec for two successful runs. -/ +def MulExpRayRunJointMonotone (y1 y2 x1 x2 : Nat) : Prop := + ∃ r1 r2, run_mul_exp_ray_evm y1 x1 = .ok r1 ∧ run_mul_exp_ray_evm y2 x2 = .ok r2 ∧ + MulExpRayJointMonotone (int256 y1) (int256 y2) (int256 x1) (int256 x2) + (int256 r1) (int256 r2) + /-- Runtime bracket proof obligation for the named arithmetic tree. -/ theorem mulExpRay_run_bracket_of_tree {y x : Nat} @@ -37,7 +48,7 @@ theorem mulExpRay_run_bracket_of_tree MulExpRayRunBracket y x := ⟨mulExpTree y x, hrun, hbracket⟩ -/-- Runtime monotonicity proof obligation for the named arithmetic tree. -/ +/-- Runtime monotonicity-in-`x` proof obligation for the named arithmetic tree. -/ theorem mulExpRay_run_monotone_of_tree {y x1 x2 : Nat} (hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1)) @@ -47,6 +58,26 @@ theorem mulExpRay_run_monotone_of_tree MulExpRayRunMonotone y x1 x2 := ⟨mulExpTree y x1, mulExpTree y x2, hrun1, hrun2, hmono⟩ +/-- Runtime monotonicity-in-`y` proof obligation for the named arithmetic tree. -/ +theorem mulExpRay_run_y_monotone_of_tree + {y1 y2 x : Nat} + (hrun1 : run_mul_exp_ray_evm y1 x = .ok (mulExpTree y1 x)) + (hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x)) + (hmono : MulExpRayYMonotone (int256 y1) (int256 y2) (int256 x) + (int256 (mulExpTree y1 x)) (int256 (mulExpTree y2 x))) : + MulExpRayRunYMonotone y1 y2 x := + ⟨mulExpTree y1 x, mulExpTree y2 x, hrun1, hrun2, hmono⟩ + +/-- Runtime sign-aware joint monotonicity proof obligation for the named arithmetic tree. -/ +theorem mulExpRay_run_joint_monotone_of_tree + {y1 y2 x1 x2 : Nat} + (hrun1 : run_mul_exp_ray_evm y1 x1 = .ok (mulExpTree y1 x1)) + (hrun2 : run_mul_exp_ray_evm y2 x2 = .ok (mulExpTree y2 x2)) + (hmono : MulExpRayJointMonotone (int256 y1) (int256 y2) (int256 x1) (int256 x2) + (int256 (mulExpTree y1 x1)) (int256 (mulExpTree y2 x2))) : + MulExpRayRunJointMonotone y1 y2 x1 x2 := + ⟨mulExpTree y1 x1, mulExpTree y2 x2, hrun1, hrun2, hmono⟩ + /-- The zero-magnitude result satisfies the signed `mulExpRay` bracket for every exponent. -/ theorem mulExpRayBracket_zero_result (x : Int) : MulExpRayBracket 0 x 0 := by diff --git a/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean b/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean index f459d8996..b69e9dde1 100644 --- a/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean +++ b/formal/exp/ExpProof/ExpProof/Spec/RealExp.lean @@ -96,6 +96,19 @@ magnitudes are nonincreasing, and zero is constant. -/ def MulExpRaySignedMonotone (y x1 x2 r1 r2 : Int) : Prop := x1 ≤ x2 ∧ if y < 0 then r2 ≤ r1 else r1 ≤ r2 +/-- Monotonicity in `y`: at a fixed exponent, signed results are nondecreasing in signed +multiplier order. -/ +def MulExpRayYMonotone (y1 y2 _x r1 r2 : Int) : Prop := + y1 ≤ y2 ∧ r1 ≤ r2 + +/-- Joint monotonicity is sign-aware: nonnegative multipliers move with `x`, nonpositive +multipliers move against `x`, and sign-crossing multipliers are ordered for any exponents. -/ +def MulExpRayJointMonotone (y1 y2 x1 x2 r1 r2 : Int) : Prop := + ((0 ≤ y1 ∧ y1 ≤ y2 ∧ x1 ≤ x2) ∨ + (y1 ≤ y2 ∧ y2 ≤ 0 ∧ x2 ≤ x1) ∨ + (y1 ≤ 0 ∧ 0 ≤ y2)) ∧ + r1 ≤ r2 + theorem mulExpRayMagnitudeTarget_nonneg (y x : Int) : 0 ≤ mulExpRayMagnitudeTarget y x := by unfold mulExpRayMagnitudeTarget @@ -125,6 +138,14 @@ theorem mulExpRayTarget_antitone_neg {y x1 x2 : Int} (hy : y < 0) (hle : x1 ≤ exact div_le_div_of_nonneg_right (by exact_mod_cast hle) hR exact mul_le_mul_of_nonpos_left (Real.exp_le_exp.mpr hx) (by exact_mod_cast (le_of_lt hy)) +theorem mulExpRayTarget_antitone_nonpos {y x1 x2 : Int} (hy : y ≤ 0) (hle : x1 ≤ x2) : + mulExpRayTarget y x2 ≤ mulExpRayTarget y x1 := by + unfold mulExpRayTarget + have hR : (0 : Real) ≤ (RAY : Real) := by norm_num [RAY] + have hx : ((x1 : Real) / (RAY : Real)) ≤ ((x2 : Real) / (RAY : Real)) := by + exact div_le_div_of_nonneg_right (by exact_mod_cast hle) hR + exact mul_le_mul_of_nonpos_left (Real.exp_le_exp.mpr hx) (by exact_mod_cast hy) + theorem mulExpRayTarget_signed_mono {y x1 x2 : Int} (hle : x1 ≤ x2) : if y < 0 then mulExpRayTarget y x2 ≤ mulExpRayTarget y x1 else mulExpRayTarget y x1 ≤ mulExpRayTarget y x2 := by @@ -133,6 +154,34 @@ theorem mulExpRayTarget_signed_mono {y x1 x2 : Int} (hle : x1 ≤ x2) : · have hy0 : 0 ≤ y := by omega simp [hy, mulExpRayTarget_mono_nonneg hy0 hle] +theorem mulExpRayTarget_mono_y {y1 y2 x : Int} (hle : y1 ≤ y2) : + mulExpRayTarget y1 x ≤ mulExpRayTarget y2 x := by + unfold mulExpRayTarget + exact mul_le_mul_of_nonneg_right (by exact_mod_cast hle) (le_of_lt (Real.exp_pos _)) + +theorem mulExpRayTarget_nonpos_of_nonpos_y {y x : Int} (hy : y ≤ 0) : + mulExpRayTarget y x ≤ 0 := by + unfold mulExpRayTarget + exact mul_nonpos_of_nonpos_of_nonneg (by exact_mod_cast hy) (le_of_lt (Real.exp_pos _)) + +theorem mulExpRayTarget_nonneg_of_nonneg_y {y x : Int} (hy : 0 ≤ y) : + 0 ≤ mulExpRayTarget y x := by + unfold mulExpRayTarget + exact mul_nonneg (by exact_mod_cast hy) (le_of_lt (Real.exp_pos _)) + +theorem mulExpRayTarget_joint_mono {y1 y2 x1 x2 : Int} + (h : + (0 ≤ y1 ∧ y1 ≤ y2 ∧ x1 ≤ x2) ∨ + (y1 ≤ y2 ∧ y2 ≤ 0 ∧ x2 ≤ x1) ∨ + (y1 ≤ 0 ∧ 0 ≤ y2)) : + mulExpRayTarget y1 x1 ≤ mulExpRayTarget y2 x2 := by + rcases h with ⟨hy1, hy, hx⟩ | ⟨hy, hy2, hx⟩ | ⟨hy1, hy2⟩ + · exact le_trans (mulExpRayTarget_mono_nonneg hy1 hx) (mulExpRayTarget_mono_y hy) + · have hy1 : y1 ≤ 0 := le_trans hy hy2 + exact le_trans (mulExpRayTarget_antitone_nonpos hy1 hx) (mulExpRayTarget_mono_y hy) + · exact le_trans (mulExpRayTarget_nonpos_of_nonpos_y hy1) + (mulExpRayTarget_nonneg_of_nonneg_y hy2) + theorem mulExpRayMagnitudeBracket_zero (x r : Int) (hr : r = 0) : MulExpRayMagnitudeBracket 0 x r := by subst hr diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 0b2d7d24b..a4a39f9e1 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -95,10 +95,11 @@ example (x1 x2 : Nat) /-! ## `mulExpRay` -The public spec for `mulExpRay` is a signed magnitude bracket and a monotonicity predicate in the -exponent argument. Positive multipliers are nondecreasing in `x`; negative multipliers are -nonincreasing. The runtime facade below reduces successful-run bracket and monotonicity statements -to the compiled arithmetic tree `mulExpTree`. +The public spec for `mulExpRay` is a signed magnitude bracket plus monotonicity predicates in both +arguments. Positive multipliers are nondecreasing in `x`; negative multipliers are nonincreasing in +`x`; for fixed `x`, signed results are nondecreasing in `y`; and joint monotonicity is stated +piecewise over the two sign regions and the sign-crossing case. The runtime facade below reduces +successful-run bracket and monotonicity statements to the compiled arithmetic tree `mulExpTree`. -/ /-- A tree equality plus a tree bracket gives the public runtime bracket spec. -/ @@ -110,7 +111,7 @@ example {y x : Nat} MulExpRayRunBracket y x := mulExpRay_run_bracket_of_tree hrun hbracket -/-- A tree equality plus ordered tree results gives the public runtime monotonicity spec. -/ +/-- A tree equality plus ordered tree results gives the public runtime monotonicity-in-`x` spec. -/ example {y x1 x2 : Nat} (hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1)) (hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2)) @@ -121,6 +122,29 @@ example {y x1 x2 : Nat} MulExpRayRunMonotone y x1 x2 := mulExpRay_run_monotone_of_tree hrun1 hrun2 hmono +/-- A tree equality plus ordered tree results gives the public runtime monotonicity-in-`y` spec. -/ +example {y1 y2 x : Nat} + (hrun1 : run_mul_exp_ray_evm y1 x = .ok (mulExpTree y1 x)) + (hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x)) + (hmono : ExpRealSpec.MulExpRayYMonotone + (FormalYul.Preservation.int256 y1) (FormalYul.Preservation.int256 y2) + (FormalYul.Preservation.int256 x) (FormalYul.Preservation.int256 (mulExpTree y1 x)) + (FormalYul.Preservation.int256 (mulExpTree y2 x))) : + MulExpRayRunYMonotone y1 y2 x := + mulExpRay_run_y_monotone_of_tree hrun1 hrun2 hmono + +/-- A tree equality plus sign-aware ordered tree results gives the joint runtime spec. -/ +example {y1 y2 x1 x2 : Nat} + (hrun1 : run_mul_exp_ray_evm y1 x1 = .ok (mulExpTree y1 x1)) + (hrun2 : run_mul_exp_ray_evm y2 x2 = .ok (mulExpTree y2 x2)) + (hmono : ExpRealSpec.MulExpRayJointMonotone + (FormalYul.Preservation.int256 y1) (FormalYul.Preservation.int256 y2) + (FormalYul.Preservation.int256 x1) (FormalYul.Preservation.int256 x2) + (FormalYul.Preservation.int256 (mulExpTree y1 x1)) + (FormalYul.Preservation.int256 (mulExpTree y2 x2))) : + MulExpRayRunJointMonotone y1 y2 x1 x2 := + mulExpRay_run_joint_monotone_of_tree hrun1 hrun2 hmono + /-- Zero magnitude satisfies the signed bracket for every exponent. -/ example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := mulExpRayBracket_zero_result x @@ -137,6 +161,20 @@ example {y x1 x2 : Int} (hle : x1 ≤ x2) : else ExpRealSpec.mulExpRayTarget y x1 ≤ ExpRealSpec.mulExpRayTarget y x2 := ExpRealSpec.mulExpRayTarget_signed_mono hle +/-- The real target is monotone in the multiplier. -/ +example {y1 y2 x : Int} (hle : y1 ≤ y2) : + ExpRealSpec.mulExpRayTarget y1 x ≤ ExpRealSpec.mulExpRayTarget y2 x := + ExpRealSpec.mulExpRayTarget_mono_y hle + +/-- The real target is sign-aware jointly monotone in the multiplier and exponent. -/ +example {y1 y2 x1 x2 : Int} + (h : + (0 ≤ y1 ∧ y1 ≤ y2 ∧ x1 ≤ x2) ∨ + (y1 ≤ y2 ∧ y2 ≤ 0 ∧ x2 ≤ x1) ∨ + (y1 ≤ 0 ∧ 0 ≤ y2)) : + ExpRealSpec.mulExpRayTarget y1 x1 ≤ ExpRealSpec.mulExpRayTarget y2 x2 := + ExpRealSpec.mulExpRayTarget_joint_mono h + /-- info: 'ExpYul.mulExpRay_run_bracket_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms mulExpRay_run_bracket_of_tree @@ -145,6 +183,14 @@ example {y x1 x2 : Int} (hle : x1 ≤ x2) : #guard_msgs in #print axioms mulExpRay_run_monotone_of_tree +/-- info: 'ExpYul.mulExpRay_run_y_monotone_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_y_monotone_of_tree + +/-- info: 'ExpYul.mulExpRay_run_joint_monotone_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_joint_monotone_of_tree + /-- info: 'ExpYul.mulExpRayBracket_zero_result' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms mulExpRayBracket_zero_result @@ -153,6 +199,14 @@ example {y x1 x2 : Int} (hle : x1 ≤ x2) : #guard_msgs in #print axioms ExpRealSpec.mulExpRayTarget_signed_mono +/-- info: 'ExpRealSpec.mulExpRayTarget_mono_y' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms ExpRealSpec.mulExpRayTarget_mono_y + +/-- info: 'ExpRealSpec.mulExpRayTarget_joint_mono' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms ExpRealSpec.mulExpRayTarget_joint_mono + /-! ## `Real.exp` floor brackets Each bracket is stated on the runtime result `r` (`run_exp_ray_to_wad_evm x = .ok r`) against the diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 6eabc89d5..657d8f02f 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -38,9 +38,17 @@ library Exp { } /// @notice Compute y * exp(x / 10**27), with y's sign reapplied after magnitude evaluation. - /// @dev Let A = abs(y) * exp(x / 10**27). For accepted inputs, this function returns sign(y) * m - /// with m <= A < m + 2. Reverts with `Panic(17)` when abs(y) exceeds the supported scale, - /// or when x and abs(y) cannot preserve that bound with a single-word scaled product. + /// @dev Let A = abs(y) ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m + /// with 0 ≤ m, m ≤ A, and A < m + 2; equivalently the magnitude is either ⌊A⌋ or + /// ⌊A⌋ - 1. Negative y uses the same magnitude bracket and then reapplies the sign. + /// `mulExpRay(0, x) == 0` for every x and `mulExpRay(y, 0) == y` for every supported y. + /// Among accepted inputs, the result is monotone in x: nondecreasing if y ≥ 0 and + /// nonincreasing if y < 0. For a fixed x, among accepted inputs, the result is + /// nondecreasing in y. Jointly, for accepted pairs (y₁, x₁) and (y₂, x₂), the first + /// result is no greater than the second when 0 ≤ y₁ ≤ y₂ and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 + /// and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. Reverts with `Panic(17)` when + /// abs(y) exceeds the supported scale, x is too large, or x and abs(y) cannot preserve + /// the two-unit magnitude bracket with a single-word scaled product. function mulExpRay(int256 y, int256 x) internal pure returns (int256) { if (y == 0) { return 0; From 2ea4a57e0ec4252b9c2bd97a219a9afc9e0c5fff Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 16:09:52 +0200 Subject: [PATCH 057/107] Extend mulExpRay proof pipeline Co-Authored-By: Codex --- formal/exp/ExpProof/ExpProof/Mul.lean | 8 + formal/exp/ExpProof/ExpProof/Mul/Bridge.lean | 70 ++++ formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 94 +++++ .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 102 +++++ .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 376 ++++++++++++++++++ formal/exp/ExpProof/ExpProof/Theorems.lean | 77 ++++ 6 files changed, 727 insertions(+) create mode 100644 formal/exp/ExpProof/ExpProof/Mul/Bridge.lean create mode 100644 formal/exp/ExpProof/ExpProof/Mul/Domain.lean create mode 100644 formal/exp/ExpProof/ExpProof/Seam/MulValue.lean diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index 30e74a201..a35eaeff4 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -1,6 +1,9 @@ import ExpProof.Mono.MulTree import ExpProof.ExpYulRuntime import ExpProof.Spec.RealExp +import ExpProof.Seam.MulValue +import ExpProof.Mul.Domain +import ExpProof.Mul.Bridge /-! # `mulExpRay` proof facade @@ -89,6 +92,11 @@ theorem mulExpRay_run_bracket_zero_of_run {x : Nat} MulExpRayRunBracket 0 x := ⟨0, hrun, mulExpRayBracket_zero_result (int256 x)⟩ +/-- The compiled runtime satisfies the public bracket spec unconditionally for zero magnitude. -/ +theorem mulExpRay_run_bracket_zero (x : Nat) : + MulExpRayRunBracket 0 x := + mulExpRay_run_bracket_zero_of_run (run_mul_exp_ray_evm_zero x) + /-- The `y = 10^18` magnitude target is the existing `expRayToWad` target. -/ theorem mulExpRayMagnitudeTarget_wad (x : Int) : mulExpRayMagnitudeTarget (10 ^ 18) x = expRayToWadTarget x := by diff --git a/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean b/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean new file mode 100644 index 000000000..fd8b5d60e --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean @@ -0,0 +1,70 @@ +import ExpProof.Mono.MulTree +import ExpProof.Spec.RealExp + +/-! +# `mulExpRay` public-spec bridge + +This file contains the scale-agnostic reductions that do not depend on the polynomial +certificates. The public magnitude bracket depends only on the concrete floor step and the two +accumulator inequalities; sign reapplication is handled separately. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open ExpRealSpec + +noncomputable section + +set_option maxRecDepth 100000 + +/-- The dynamic real pre-floor accumulator of the shared kernel body. -/ +def mulAccumReal (y x : Nat) : Real := + (int256 (evmSub (r0MulTree y x) marginWord) : Real) / + (2 ^ (mulShiftTree y x) : Real) + +/-- The public magnitude bracket follows from the floor step, never-over accumulator bound, and +deficit-under-one accumulator bound. -/ +theorem mulExpRayMagnitudeBracket_of_accum {y x m : Int} {A : Real} + (hm_nonneg : 0 ≤ m) + (hfloor : (m : Real) ≤ A) + (hfloor1 : A < (m : Real) + 1) + (hover : A ≤ mulExpRayMagnitudeTarget y x) + (hunder : mulExpRayMagnitudeTarget y x < A + 1) : + MulExpRayMagnitudeBracket y x m := by + refine ⟨hm_nonneg, le_trans hfloor hover, ?_⟩ + calc mulExpRayMagnitudeTarget y x < A + 1 := hunder + _ < ((m : Real) + 1) + 1 := by linarith + _ = (m : Real) + 2 := by ring + +/-- Sign reapplication turns a proven magnitude bracket into the signed public bracket. -/ +theorem mulExpRayBracket_of_signed_magnitude {y x r m : Int} + (hmag : MulExpRayMagnitudeBracket y x m) + (hsign : if y < 0 then r = -m else r = m) : + MulExpRayBracket y x r := by + unfold MulExpRayBracket + by_cases hy : y < 0 + · simp [hy] at hsign ⊢ + rw [hsign] + simpa using hmag + · simp [hy] at hsign ⊢ + rw [hsign] + exact hmag + +/-- Magnitude brackets imply the magnitude is one unit below the exact floor at worst. -/ +theorem mulExpRayMagnitudeBracket_to_underByAtMostOne {y x m : Int} + (h : MulExpRayMagnitudeBracket y x m) : + ⌊mulExpRayMagnitudeTarget y x⌋ - 1 ≤ m := by + obtain ⟨_, hle, hlt⟩ := h + set A := mulExpRayMagnitudeTarget y x with hA + have hmle : m ≤ ⌊A⌋ := Int.le_floor.mpr hle + have hfloorle : (⌊A⌋ : Real) ≤ A := Int.floor_le A + have hlt2 : (⌊A⌋ : Real) < (m : Real) + 2 := lt_of_le_of_lt hfloorle hlt + have hlt2' : (⌊A⌋ : Real) < ((m + 2 : Int) : Real) := by push_cast; linarith + have hge : ⌊A⌋ < m + 2 := by exact_mod_cast hlt2' + omega + +end + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean new file mode 100644 index 000000000..fc68d0e6a --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -0,0 +1,94 @@ +import ExpProof.Mono.MulTree + +/-! +# `mulExpRay` value and panic domains + +The runtime guard partitions canonical calldata into a value path and a `Panic(17)` path. The value +domain keeps the same short-circuits as the implementation: zero multiplier returns before any +range checks, sufficiently small exponents clamp to zero without needing the accuracy guard, and +the scale point is accepted independently of the `k ≤ s - 2` guard. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation + +set_option maxRecDepth 100000 + +/-- ABI words transported into this proof layer. -/ +def MulExpRayCanonical (y x : Nat) : Prop := + y < 2 ^ 256 ∧ x < 2 ^ 256 + +/-- The exact successful-input domain induced by the implementation guard. -/ +def MulExpRayValueDomain (y x : Nat) : Prop := + MulExpRayCanonical y x ∧ + (int256 y = 0 ∨ + absTree y ≤ scaleQ67 ∧ + int256 x < int256 xHiMulExpRay ∧ + (int256 x ≤ int256 xLoZeroMulExpRay ∨ + int256 x = 0 ∨ + int256 (kTree x) ≤ (scaleShiftTree (absTree y) : Int) - 2)) + +/-- The exact nonzero-multiplier panic domain induced by the implementation guard. -/ +def MulExpRayPanicDomain (y x : Nat) : Prop := + MulExpRayCanonical y x ∧ + int256 y ≠ 0 ∧ + (scaleQ67 < absTree y ∨ + int256 xHiMulExpRay ≤ int256 x ∨ + (int256 x ≠ 0 ∧ + int256 xLoZeroMulExpRay < int256 x ∧ + (scaleShiftTree (absTree y) : Int) - 2 < int256 (kTree x))) + +/-- Canonical inputs are either accepted by the value guard or rejected by the panic guard. -/ +theorem mulExpRay_value_or_panic_of_canonical {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := by + by_cases hy0 : int256 y = 0 + · exact Or.inl ⟨hcanon, Or.inl hy0⟩ + · by_cases hscale : absTree y ≤ scaleQ67 + · by_cases hxhi : int256 x < int256 xHiMulExpRay + · by_cases hxlo : int256 x ≤ int256 xLoZeroMulExpRay + · exact Or.inl ⟨hcanon, Or.inr ⟨hscale, hxhi, Or.inl hxlo⟩⟩ + · by_cases hx0 : int256 x = 0 + · exact Or.inl ⟨hcanon, Or.inr ⟨hscale, hxhi, Or.inr (Or.inl hx0)⟩⟩ + · by_cases hk : + int256 (kTree x) ≤ (scaleShiftTree (absTree y) : Int) - 2 + · exact Or.inl ⟨hcanon, Or.inr ⟨hscale, hxhi, Or.inr (Or.inr hk)⟩⟩ + · exact Or.inr ⟨hcanon, hy0, + Or.inr (Or.inr ⟨hx0, by omega, by omega⟩)⟩ + · exact Or.inr ⟨hcanon, hy0, Or.inr (Or.inl (by omega))⟩ + · exact Or.inr ⟨hcanon, hy0, Or.inl (by omega)⟩ + +/-- The accepted and rejected guard domains are disjoint. -/ +theorem mulExpRay_value_not_panic {y x : Nat} : + MulExpRayValueDomain y x → ¬ MulExpRayPanicDomain y x := by + intro hv hp + rcases hv with ⟨_, hy0 | ⟨hscale, hxhi, hxlo | hx0 | hk⟩⟩ + · exact hp.2.1 hy0 + · rcases hp with ⟨_, _, hpguard⟩ + rcases hpguard with hbadScale | hbadHi | ⟨_, hbadLo, _⟩ + · omega + · omega + · omega + · rcases hp with ⟨_, _, hpguard⟩ + rcases hpguard with hbadScale | hbadHi | ⟨hxne, _, _⟩ + · omega + · omega + · exact hxne hx0 + · rcases hp with ⟨_, _, hpguard⟩ + rcases hpguard with hbadScale | hbadHi | ⟨_, _, hbadK⟩ + · omega + · omega + · omega + +/-- Canonical inputs are accepted exactly when they are not in the panic domain. -/ +theorem mulExpRay_value_iff_not_panic {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayValueDomain y x ↔ ¬ MulExpRayPanicDomain y x := by + constructor + · exact mulExpRay_value_not_panic + · intro hnot + rcases mulExpRay_value_or_panic_of_canonical hcanon with hval | hpanic + · exact hval + · exact False.elim (hnot hpanic) + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 72b63f202..0e3b37218 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -1293,6 +1293,108 @@ theorem call_fun_clz_direct call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 56) (shared := shared) (hlookup := hlookup)] +theorem call_fun__absSign_direct + (y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 200)) [FormalYul.word y] (.some yulName_fun__absSign) + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word (absTree y), FormalYul.word (signTree y)]) := by + rw [show fuel + (extra + 200) = (fuel + extra) + 200 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__absSign] + simp only [yulFunction_fun__absSign, yulFunction_fun__absSign_305, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, signTree, absTree, + uint256_ofNat_sar_eq_word_evmSar, + uint256_ofNat_xor_eq_word_evmXor, + FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 176) + (shared := shared) (hlookup := hlookup), + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 174) + (shared := shared) (hlookup := hlookup)] + +theorem call_fun__scaleShift_direct + (ay fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 700)) [FormalYul.word ay] + (.some yulName_fun__scaleShift) (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (scaleShiftTree ay)]) := by + rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__scaleShift] + simp only [yulFunction_fun__scaleShift, yulFunction_fun__scaleShift_328, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + let s := evmSub (evmClz ay) scaleMaxClz + let initStore := + Finmap.insert "var_ay_307" (FormalYul.word ay) + (Inhabited.default : EvmYul.Yul.VarStore) + let zeroStore := Finmap.insert "zero_t_uint256_42" (FormalYul.word 0) initStore + let baseStore := Finmap.insert "var_s_310" (FormalYul.word 0) zeroStore + let beforeClzStore := + Finmap.insert "expr_315" (FormalYul.word ay) + (Finmap.insert "_43" (FormalYul.word ay) + (Finmap.insert "expr_313_address" (FormalYul.word 0) baseStore)) + let afterClzStore := Finmap.insert "expr_316" (FormalYul.word (evmClz ay)) beforeClzStore + let afterClzConstStore := Finmap.insert "expr_317" (FormalYul.word scaleMaxClz) afterClzStore + let afterSubStore := Finmap.insert "expr_318" (FormalYul.word s) afterClzConstStore + let beforeScaleStore := + Finmap.insert "expr_319" (FormalYul.word s) + (Finmap.insert "var_s_310" (FormalYul.word s) afterSubStore) + have hzero := + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 676) + (shared := shared) (hlookup := hlookup) + (store := initStore) + have hclz := + call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 611) + (shared := shared) (store := beforeClzStore) (hlookup := hlookup) + have hclzConst := + call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 530) + (shared := shared) (store := afterClzStore) (hlookup := hlookup) + have hsub := + call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) + (fuel := fuel + extra) (extra := 609) + (shared := shared) (store := afterClzConstStore) (hlookup := hlookup) + have hscale := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 526) + (shared := shared) (store := beforeScaleStore) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word, initStore, zeroStore, baseStore, + beforeClzStore, afterClzStore, afterClzConstStore, afterSubStore, beforeScaleStore] + at hzero hclz hclzConst hsub hscale + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + GetElem?.getElem!, decidableGetElem?, + EvmYul.Yul.State.instGetElemIdentifierLiteralMemVarStoreStore, + EvmYul.Yul.State.store, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, scaleShiftTree, s, + initStore, zeroStore, baseStore, beforeClzStore, afterClzStore, afterClzConstStore, + afterSubStore, beforeScaleStore, + FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, + FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl, + FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, + hzero, hclz, hclzConst, hsub, hscale] + theorem call_shift_left_dynamic_direct (bits value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean new file mode 100644 index 000000000..4408c1039 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -0,0 +1,376 @@ +import ExpProof.ExpYulProof +import Common.Word +import ExpProof.Seam.Helpers +import ExpProof.Seam.Dispatcher +import FormalYul.Preservation + +/-! +# Value-path reductions for `mulExpRay` + +This file discharges the concrete zero-magnitude path, which returns before the dynamic scale, +octave, range guard, and kernel. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word + +set_option maxRecDepth 100000 + +set_option maxHeartbeats 4000000 in +/-- `fun_mulExpRay(0, x)` returns `0` before evaluating scale, octave, range, or kernel code. -/ +theorem call_fun_mulExpRay_zero_direct + (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 500)) [FormalYul.word 0, FormalYul.word x] + (.some yulName_fun_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + rw [show fuel + (extra + 500) = (fuel + extra) + 500 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_mulExpRay] + simp only [yulFunction_fun_mulExpRay, yulFunction_fun_mulExpRay_294, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hzeroInit := + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 476) + (shared := shared) (hlookup := hlookup) + have hcleanupY := + call_cleanup_t_int256_direct (v := 0) (fuel := fuel + extra) (extra := 467) + (shared := shared) (hlookup := hlookup) + have hconvertCmp := + call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 369) + (shared := shared) (hlookup := hlookup) + have hconvertRet := + call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 367) + (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hcleanupY hconvertCmp hconvertRet + simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.overwrite?, + FormalYul.Preservation.call_on_checkpoint, + Finmap.lookup_insert, FormalYul.word, + hzeroInit, hcleanupY, hconvertCmp, hconvertRet] + +set_option maxHeartbeats 4000000 in +/-- `fun_wrap_mulExpRay(0, x)` forwards to `fun_mulExpRay`, giving `0`. -/ +theorem call_fun_wrap_mulExpRay_zero_direct + (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word 0, FormalYul.word x] + (.some yulName_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_mulExpRay] + simp only [yulFunction_fun_wrap_mulExpRay, yulFunction_fun_wrap_mulExpRay_390, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hinner := + call_fun_mulExpRay_zero_direct (x := x) (fuel := fuel + extra) (extra := 589) + (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hinner + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 1076) + (shared := shared) (hlookup := hlookup), + hinner] + +set_option maxHeartbeats 12000000 in +/-- The external `mulExpRay` entrypoint at `y = 0` ABI-encodes and returns `0`. -/ +theorem external_fun_wrap_mulExpRay_zero_calldata_result + (x : Nat) (store : EvmYul.Yul.VarStore) : + ((match + EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) store) + with + | .error (.YulHalt state _) => FormalYul.resultWord (FormalYul.returnOf state) + | .error .Revert => .error "revert" + | .error err => .error (reprStr err) + | .ok (state, _) => FormalYul.resultWord (FormalYul.returnOf state)) : + Except String Nat) = + .ok 0 := by + rw [EvmYul.Yul.call.eq_def] + simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, + lookup_external_fun_wrap_mulExpRay] + simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_390, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + let baseStore := + Finmap.insert "ret_0" (FormalYul.word 0) + (Finmap.insert "param_0" (FormalYul.word 0) + (Finmap.insert "param_1" (FormalYul.word x) + (Inhabited.default : EvmYul.Yul.VarStore))) + let memPos := + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + (FormalYul.word 64)).1 + let memShared := + { mulExpSharedAfterFreePtr 0 x with + toMachineState := + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + (FormalYul.word 64)).2 } + let encStore := Finmap.insert "memPos" memPos baseStore + have hdecode := + call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := 0) (x := x) + (fuel := 0) (extra := 999464) + (shared := mulExpSharedAfterFreePtr 0 x) + (store := (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + (hdata := mulExpSharedAfterFreePtr_calldata 0 x) + simp only [Nat.reduceAdd, FormalYul.word] at hdecode + have hwrap := + call_fun_wrap_mulExpRay_zero_direct (x := x) (fuel := 0) (extra := 998883) + (shared := mulExpSharedAfterFreePtr 0 x) + (store := Finmap.insert "param_0" (FormalYul.word 0) + (Finmap.insert "param_1" (FormalYul.word x) + (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + simp only [Nat.reduceAdd, FormalYul.word] at hwrap + have halloc := + call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr 0 x) + (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + simp only [FormalYul.word, baseStore] at halloc + have hencode := + call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + (headStart := memPos) (v := 0) (fuel := 999831) + (shared := memShared) (store := encStore) + (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup 0 x]) + simp [FormalYul.word, memShared, encStore, memPos, baseStore] at hencode + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.executionEnv, + mulExpSharedAfterFreePtr_weiValue, mulExpSharedAfterFreePtr_calldata, mulExpRay_calldata_size, + GetElem?.getElem!, decidableGetElem?, + EvmYul.Yul.State.instGetElemIdentifierLiteralMemVarStoreStore, + EvmYul.Yul.State.store, + EvmYul.Yul.State.toMachineState, FormalYul.returnOf, + Finmap.lookup_insert, Finmap.lookup_insert_of_ne, + hdecode, hwrap, halloc, hencode] + have hmload : + ((mulExpSharedAfterFreePtr 0 x).mload (EvmYul.UInt256.ofNat 64)).1 = + EvmYul.UInt256.ofNat 128 := by + simpa [FormalYul.word] using mulExpSharedAfterFreePtr_mload64 0 x + rw [hmload] + have hretLen : + EvmYul.UInt256.ofNat 128 + EvmYul.UInt256.ofNat 32 - EvmYul.UInt256.ofNat 128 = + FormalYul.word 32 := by decide + rw [hretLen] + rw [FormalYul.Preservation.resultWord_evmReturn_mstore_word] + rfl + +set_option maxHeartbeats 12000000 in +/-- The external `mulExpRay` entrypoint at `y = 0` halts (returns). -/ +theorem external_fun_wrap_mulExpRay_zero_calldata_halts + (x : Nat) (store : EvmYul.Yul.VarStore) : + ∃ state value, + EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) store) = + .error (.YulHalt state value) := by + rw [EvmYul.Yul.call.eq_def] + simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, + lookup_external_fun_wrap_mulExpRay] + simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_390, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + let baseStore := + Finmap.insert "ret_0" (FormalYul.word 0) + (Finmap.insert "param_0" (FormalYul.word 0) + (Finmap.insert "param_1" (FormalYul.word x) + (Inhabited.default : EvmYul.Yul.VarStore))) + let memPos := + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + (FormalYul.word 64)).1 + let memShared := + { mulExpSharedAfterFreePtr 0 x with + toMachineState := + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + (FormalYul.word 64)).2 } + let encStore := Finmap.insert "memPos" memPos baseStore + have hdecode := + call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := 0) (x := x) + (fuel := 0) (extra := 999464) + (shared := mulExpSharedAfterFreePtr 0 x) + (store := (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + (hdata := mulExpSharedAfterFreePtr_calldata 0 x) + simp only [Nat.reduceAdd, FormalYul.word] at hdecode + have hwrap := + call_fun_wrap_mulExpRay_zero_direct (x := x) (fuel := 0) (extra := 998883) + (shared := mulExpSharedAfterFreePtr 0 x) + (store := Finmap.insert "param_0" (FormalYul.word 0) + (Finmap.insert "param_1" (FormalYul.word x) + (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + simp only [Nat.reduceAdd, FormalYul.word] at hwrap + have halloc := + call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr 0 x) + (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + simp only [FormalYul.word, baseStore] at halloc + have hencode := + call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + (headStart := memPos) (v := 0) (fuel := 999831) + (shared := memShared) (store := encStore) + (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup 0 x]) + simp [FormalYul.word, memShared, encStore, memPos, baseStore] at hencode + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.executionEnv, + mulExpSharedAfterFreePtr_weiValue, mulExpSharedAfterFreePtr_calldata, mulExpRay_calldata_size, + GetElem?.getElem!, decidableGetElem?, + EvmYul.Yul.State.instGetElemIdentifierLiteralMemVarStoreStore, + EvmYul.Yul.State.store, + EvmYul.Yul.State.toMachineState, + Finmap.lookup_insert, Finmap.lookup_insert_of_ne, + hdecode, hwrap, halloc, hencode] + +set_option maxHeartbeats 12000000 in +/-- Result, starting from the exact state the dispatcher hands the external `mulExpRay` function. -/ +theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_result (x : Nat) : + ((match + EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Finmap.insert "selector" + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + (Inhabited.default : EvmYul.Yul.VarStore))) + with + | .error (.YulHalt state _) => FormalYul.resultWord (FormalYul.returnOf state) + | .error .Revert => .error "revert" + | .error err => .error (reprStr err) + | .ok (state, _) => FormalYul.resultWord (FormalYul.returnOf state)) : + Except String Nat) = + .ok 0 := by + rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr_raw] + exact external_fun_wrap_mulExpRay_zero_calldata_result x + (store := Finmap.insert "selector" + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + (Inhabited.default : EvmYul.Yul.VarStore)) + +set_option maxHeartbeats 12000000 in +/-- Halt, starting from the exact state the dispatcher hands the external `mulExpRay` function. -/ +theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_halts (x : Nat) : + ∃ state value, + EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Finmap.insert "selector" + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + (Inhabited.default : EvmYul.Yul.VarStore))) = + .error (.YulHalt state value) := by + rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr_raw] + exact external_fun_wrap_mulExpRay_zero_calldata_halts x + (store := Finmap.insert "selector" + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + (Inhabited.default : EvmYul.Yul.VarStore)) + +set_option maxHeartbeats 12000000 in +/-- **Zero-magnitude exactness.** `mulExpRay(0, x)` returns `0` for every exponent word. -/ +theorem run_mul_exp_ray_evm_zero (x : Nat) : + run_mul_exp_ray_evm 0 x = .ok 0 := by + obtain ⟨haltState, _haltValue, hhalt⟩ := + external_fun_wrap_mulExpRay_zero_dispatcher_state_halts x + have hresult := external_fun_wrap_mulExpRay_zero_dispatcher_state_result x + rw [hhalt] at hresult + have hReturn : + FormalYul.Preservation.DispatcherReturn yulContract + (FormalYul.calldata selector_mulExpRay [0, x]) 999998 (FormalYul.returnOf haltState) := by + apply FormalYul.Preservation.dispatcherReturn_of_exec_halt + (hdispatcher := yulContract_dispatcher) + refine ⟨haltState, _haltValue, ?_, rfl⟩ + simp +decide [FormalYul.calldata, FormalYul.stateFor, + yulDispatcher, EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', + EvmYul.Yul.head', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, + EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, + EvmYul.Yul.State.executionEnv, + EvmYul.Yul.State.toMachineState, + GetElem?.getElem!, decidableGetElem?, + EvmYul.Yul.State.instGetElemIdentifierLiteralMemVarStoreStore, + EvmYul.Yul.State.store, Finmap.lookup_insert, + FormalYul.word, + call_shift_right_224_unsigned_direct] + rw [selectSwitchCase_mulExpRay_sharedFor_mk_raw 0 x] + simp +decide [hhalt, EvmYul.Yul.exec.eq_def, + EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.multifill'] + unfold run_mul_exp_ray_evm + exact FormalYul.Preservation.callWord_ok_of_dispatcherReturn_result_1000000 + (contract := yulContract) (selector := selector_mulExpRay) (args := [0, x]) + (hReturn := hReturn) (by simpa using hresult) + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index a4a39f9e1..896fc6f3b 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -102,6 +102,16 @@ piecewise over the two sign regions and the sign-crossing case. The runtime faca successful-run bracket and monotonicity statements to the compiled arithmetic tree `mulExpTree`. -/ +/-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ +example {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := + mulExpRay_value_or_panic_of_canonical hcanon + +/-- The value and panic guards are disjoint on canonical inputs. -/ +example {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayValueDomain y x ↔ ¬ MulExpRayPanicDomain y x := + mulExpRay_value_iff_not_panic hcanon + /-- A tree equality plus a tree bracket gives the public runtime bracket spec. -/ example {y x : Nat} (hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x)) @@ -149,6 +159,37 @@ example {y1 y2 x1 x2 : Nat} example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := mulExpRayBracket_zero_result x +/-- The compiled runtime returns zero for every exponent when the multiplier is zero. -/ +example (x : Nat) : run_mul_exp_ray_evm 0 x = .ok 0 := + run_mul_exp_ray_evm_zero x + +/-- The compiled runtime satisfies the public bracket spec unconditionally at zero magnitude. -/ +example (x : Nat) : MulExpRayRunBracket 0 x := + mulExpRay_run_bracket_zero x + +/-- The accumulator floor and target bounds imply the public magnitude bracket. -/ +example {y x m : Int} {A : Real} + (hm_nonneg : 0 ≤ m) + (hfloor : (m : Real) ≤ A) + (hfloor1 : A < (m : Real) + 1) + (hover : A ≤ ExpRealSpec.mulExpRayMagnitudeTarget y x) + (hunder : ExpRealSpec.mulExpRayMagnitudeTarget y x < A + 1) : + ExpRealSpec.MulExpRayMagnitudeBracket y x m := + mulExpRayMagnitudeBracket_of_accum hm_nonneg hfloor hfloor1 hover hunder + +/-- Sign reapplication turns a magnitude bracket into the signed public bracket. -/ +example {y x r m : Int} + (hmag : ExpRealSpec.MulExpRayMagnitudeBracket y x m) + (hsign : if y < 0 then r = -m else r = m) : + ExpRealSpec.MulExpRayBracket y x r := + mulExpRayBracket_of_signed_magnitude hmag hsign + +/-- Magnitude brackets imply the magnitude is under by at most one output unit. -/ +example {y x m : Int} + (h : ExpRealSpec.MulExpRayMagnitudeBracket y x m) : + ⌊ExpRealSpec.mulExpRayMagnitudeTarget y x⌋ - 1 ≤ m := + mulExpRayMagnitudeBracket_to_underByAtMostOne h + /-- Existing `expRayToWad` floor brackets instantiate the `y = 10^18` specialization. -/ example {x r : Int} (hr : 0 ≤ r) (h : ExpRealSpec.FloorOrOneLessBracket x r) : @@ -191,10 +232,46 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_joint_monotone_of_tree +/-- info: 'ExpYul.mulExpRay_value_or_panic_of_canonical' depends on axioms: [propext, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_value_or_panic_of_canonical + +/-- info: 'ExpYul.mulExpRay_value_iff_not_panic' depends on axioms: [propext, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_value_iff_not_panic + +/-- info: 'ExpYul.mulExpRayMagnitudeBracket_of_accum' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRayMagnitudeBracket_of_accum + +/-- info: 'ExpYul.mulExpRayBracket_of_signed_magnitude' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRayBracket_of_signed_magnitude + +/-- info: 'ExpYul.mulExpRayMagnitudeBracket_to_underByAtMostOne' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRayMagnitudeBracket_to_underByAtMostOne + /-- info: 'ExpYul.mulExpRayBracket_zero_result' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms mulExpRayBracket_zero_result +/-- info: 'ExpYul.run_mul_exp_ray_evm_zero' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_zero + +/-- info: 'ExpYul.mulExpRay_run_bracket_zero' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_bracket_zero + +/-- info: 'ExpYul.call_fun__absSign_direct' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms call_fun__absSign_direct + +/-- info: 'ExpYul.call_fun__scaleShift_direct' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms call_fun__scaleShift_direct + /-- info: 'ExpRealSpec.mulExpRayTarget_signed_mono' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms ExpRealSpec.mulExpRayTarget_signed_mono From 09680ec624bfdccda444f20399c36ba32a0f41ea Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 17:14:54 +0200 Subject: [PATCH 058/107] Expose mulExpRay guard tree Co-Authored-By: Codex --- formal/common/Common/Word.lean | 22 +++++++++++++++++++ .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 15 +++++++++++++ .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 8 +++++++ 3 files changed, 45 insertions(+) diff --git a/formal/common/Common/Word.lean b/formal/common/Common/Word.lean index 1944aefbd..adc369e67 100644 --- a/formal/common/Common/Word.lean +++ b/formal/common/Common/Word.lean @@ -235,6 +235,21 @@ theorem wordNat_slt (a b : EvmYul.UInt256) : rw [hua', hub', word_mod_eq] rw [hLHS, hRHS] +theorem wordNat_sgt (a b : EvmYul.UInt256) : + wordNat (EvmYul.UInt256.sgt a b) = evmSgt (wordNat a) (wordNat b) := by + have hbool : EvmYul.UInt256.sgtBool a b = EvmYul.UInt256.sltBool b a := by + unfold EvmYul.UInt256.sgtBool EvmYul.UInt256.sltBool + by_cases ha : 2 ^ 255 ≤ a.toNat <;> by_cases hb : 2 ^ 255 ≤ b.toNat + · rw [if_pos ha, if_pos hb, if_pos hb, if_pos ha] + · rw [if_pos ha, if_neg hb, if_neg hb, if_pos ha] + · rw [if_neg ha, if_pos hb, if_pos hb, if_neg ha] + · rw [if_neg ha, if_neg hb, if_neg hb, if_neg ha] + unfold EvmYul.UInt256.sgt + rw [hbool] + change wordNat (EvmYul.UInt256.slt b a) = evmSgt (wordNat a) (wordNat b) + rw [wordNat_slt b a] + rfl + /-- An `evmAdd` result is already `u256`-wrapped, so injecting it through `ofNat` and reading its `toNat` is the identity. Discharges the run-level `resultWord` extraction without re-stating the evm* tree. -/ @@ -248,6 +263,13 @@ theorem evmSlt_u256_left (a b : Nat) : evmSlt (u256 a) b = evmSlt a b := by simp only [evmSlt, u256_idem] theorem evmSlt_u256_right (a b : Nat) : evmSlt a (u256 b) = evmSlt a b := by simp only [evmSlt, u256_idem] +theorem evmSgt_u256_left (a b : Nat) : evmSgt (u256 a) b = evmSgt a b := by + simp only [evmSgt, u256_idem] +theorem evmSgt_u256_right (a b : Nat) : evmSgt a (u256 b) = evmSgt a b := by + simp only [evmSgt, u256_idem] +theorem u256_evmSgt (a b : Nat) : u256 (evmSgt a b) = evmSgt a b := by + unfold evmSgt + split <;> simp [u256, WORD_MOD] theorem evmSar_u256_left (s v : Nat) : evmSar (u256 s) v = evmSar s v := by simp only [evmSar, u256_idem] diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean index 3c4087d93..7c5f31be9 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -39,6 +39,17 @@ def mulScaleTree (y : Nat) : Nat := def mulShiftTree (y x : Nat) : Nat := evmSub (scaleShiftTree (absTree y)) (kTree x) +/-- The branch word for the `Panic(17)` guard. -/ +def mulExpGuardTree (y x : Nat) : Nat := + let ay := absTree y + let s := scaleShiftTree ay + let k := kTree x + let outOfRange := evmOr (evmGt ay scaleQ67) (evmIszero (evmSlt x xHiMulExpRay)) + let inaccurate := + evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x xLoZeroMulExpRay)) + (evmSgt k (evmSub s 2)) + evmOr outOfRange inaccurate + /-- The dynamic-scaled quotient before the closing shift. -/ def r0MulTree (y x : Nat) : Nat := evmDiv (evmMul (mulScaleTree y) (evmAdd (evTree x) (todTree x))) @@ -71,6 +82,10 @@ theorem mulShiftTree_lt (y x : Nat) : mulShiftTree y x < 2 ^ 256 := by unfold mulShiftTree exact evmSub_lt _ _ +theorem mulExpGuardTree_lt (y x : Nat) : mulExpGuardTree y x < 2 ^ 256 := by + unfold mulExpGuardTree + simpa [WORD_MOD] using evmOr_lt_WORD_MOD _ _ + theorem r0MulTree_lt (y x : Nat) : r0MulTree y x < 2 ^ 256 := by unfold r0MulTree exact evmDiv_lt _ _ diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 0e3b37218..8f1f7e024 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -1528,4 +1528,12 @@ theorem call_fun_and_direct call_zero_value_for_split_t_bool_direct (fuel := fuel + extra) (extra := 56) (shared := shared) (hlookup := hlookup)] +theorem uint256_ofNat_sgt_eq_word_evmSgt (a b : Nat) : + EvmYul.UInt256.sgt (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b) = + FormalYul.word (evmSgt a b) := by + apply FormalYul.Preservation.eq_of_wordNat_eq + simp only [wordNat_sgt, FormalYul.Preservation.wordNat_ofNat, + FormalYul.Preservation.wordNat_word] + simp [evmSgt_u256_left, evmSgt_u256_right, u256_evmSgt] + end ExpYul From 012afb408d9cdb1e956452e0ed1c35d4ea869c6a Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 17:16:27 +0200 Subject: [PATCH 059/107] Inline single-use mulExpRay helpers Co-Authored-By: Codex --- src/vendor/Exp.sol | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 657d8f02f..868150227 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -54,10 +54,23 @@ library Exp { return 0; } - (uint256 ay, uint256 sign) = _absSign(y); - uint256 s = _scaleShift(ay); - int256 k = _octave(x); + uint256 ay; + uint256 sign; + // Compute `abs(y)` without negating `type(int256).min`. + assembly ("memory-safe") { + sign := sar(0xff, y) + ay := sub(xor(y, sign), sign) + } + unchecked { + uint256 s = Clz.clz(ay) - _SCALE_MAX_CLZ; + uint256 scaleMax = _SCALE_MAX; + // Correct the bit-length estimate without branching. + assembly ("memory-safe") { + s := sub(s, gt(shl(s, ay), scaleMax)) + } + + int256 k = _octave(x); if ((ay > _SCALE_MAX).or(x >= _X_HI).or((x != 0).and(x > _X_LO_ZERO).and(k > int256(s) - 2))) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } @@ -72,28 +85,6 @@ library Exp { } } - function _absSign(int256 y) private pure returns (uint256 ay, uint256 sign) { - // Compute `abs(y)` without negating `type(int256).min`: - // sign = 0 for nonnegative y, -1 for negative y - // ay = (y ^ sign) - sign - assembly ("memory-safe") { - sign := sar(0xff, y) - ay := sub(xor(y, sign), sign) - } - } - - function _scaleShift(uint256 ay) private pure returns (uint256 s) { - unchecked { - s = Clz.clz(ay) - _SCALE_MAX_CLZ; - uint256 scaleMax = _SCALE_MAX; - // Correct the bit-length estimate without branching: - // s -= gt(ay << s, scaleMax) - assembly ("memory-safe") { - s := sub(s, gt(shl(s, ay), scaleMax)) - } - } - } - function _octave(int256 x) private pure returns (int256 k) { // Round to the nearest octave: // k = round(x / (10**27 * ln(2))) From badf6a08eecffc59e53fd5258992fed9bb37775e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 17:38:37 +0200 Subject: [PATCH 060/107] Repair exp proof after mulExpRay inlining Co-Authored-By: Codex --- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 104 +----------------- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 8 +- formal/exp/ExpProof/ExpProof/Seam/Revert.lean | 4 +- formal/exp/ExpProof/ExpProof/Seam/Value.lean | 16 +-- formal/exp/ExpProof/ExpProof/Theorems.lean | 8 -- formal/yul/YulImporter.lean | 4 +- 6 files changed, 16 insertions(+), 128 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 8f1f7e024..99962a432 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -638,7 +638,7 @@ theorem call_fun__octave_direct rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__octave] - simp only [yulFunction_fun__octave, yulFunction_fun__octave_337, + simp only [yulFunction_fun__octave, yulFunction_fun__octave_310, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1293,108 +1293,6 @@ theorem call_fun_clz_direct call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 56) (shared := shared) (hlookup := hlookup)] -theorem call_fun__absSign_direct - (y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 200)) [FormalYul.word y] (.some yulName_fun__absSign) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, - [FormalYul.word (absTree y), FormalYul.word (signTree y)]) := by - rw [show fuel + (extra + 200) = (fuel + extra) + 200 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__absSign] - simp only [yulFunction_fun__absSign, yulFunction_fun__absSign_305, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, signTree, absTree, - uint256_ofNat_sar_eq_word_evmSar, - uint256_ofNat_xor_eq_word_evmXor, - FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 176) - (shared := shared) (hlookup := hlookup), - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 174) - (shared := shared) (hlookup := hlookup)] - -theorem call_fun__scaleShift_direct - (ay fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 700)) [FormalYul.word ay] - (.some yulName_fun__scaleShift) (.some yulContract) - (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (scaleShiftTree ay)]) := by - rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__scaleShift] - simp only [yulFunction_fun__scaleShift, yulFunction_fun__scaleShift_328, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - let s := evmSub (evmClz ay) scaleMaxClz - let initStore := - Finmap.insert "var_ay_307" (FormalYul.word ay) - (Inhabited.default : EvmYul.Yul.VarStore) - let zeroStore := Finmap.insert "zero_t_uint256_42" (FormalYul.word 0) initStore - let baseStore := Finmap.insert "var_s_310" (FormalYul.word 0) zeroStore - let beforeClzStore := - Finmap.insert "expr_315" (FormalYul.word ay) - (Finmap.insert "_43" (FormalYul.word ay) - (Finmap.insert "expr_313_address" (FormalYul.word 0) baseStore)) - let afterClzStore := Finmap.insert "expr_316" (FormalYul.word (evmClz ay)) beforeClzStore - let afterClzConstStore := Finmap.insert "expr_317" (FormalYul.word scaleMaxClz) afterClzStore - let afterSubStore := Finmap.insert "expr_318" (FormalYul.word s) afterClzConstStore - let beforeScaleStore := - Finmap.insert "expr_319" (FormalYul.word s) - (Finmap.insert "var_s_310" (FormalYul.word s) afterSubStore) - have hzero := - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 676) - (shared := shared) (hlookup := hlookup) - (store := initStore) - have hclz := - call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 611) - (shared := shared) (store := beforeClzStore) (hlookup := hlookup) - have hclzConst := - call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 530) - (shared := shared) (store := afterClzStore) (hlookup := hlookup) - have hsub := - call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) - (fuel := fuel + extra) (extra := 609) - (shared := shared) (store := afterClzConstStore) (hlookup := hlookup) - have hscale := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 526) - (shared := shared) (store := beforeScaleStore) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word, initStore, zeroStore, baseStore, - beforeClzStore, afterClzStore, afterClzConstStore, afterSubStore, beforeScaleStore] - at hzero hclz hclzConst hsub hscale - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - GetElem?.getElem!, decidableGetElem?, - EvmYul.Yul.State.instGetElemIdentifierLiteralMemVarStoreStore, - EvmYul.Yul.State.store, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, scaleShiftTree, s, - initStore, zeroStore, baseStore, beforeClzStore, afterClzStore, afterClzConstStore, - afterSubStore, beforeScaleStore, - FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, - FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl, - FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, - hzero, hclz, hclzConst, hsub, hscale] - theorem call_shift_left_dynamic_direct (bits value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 4408c1039..4d1b68232 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -31,7 +31,7 @@ theorem call_fun_mulExpRay_zero_direct rw [show fuel + (extra + 500) = (fuel + extra) + 500 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_mulExpRay] - simp only [yulFunction_fun_mulExpRay, yulFunction_fun_mulExpRay_294, + simp only [yulFunction_fun_mulExpRay, yulFunction_fun_mulExpRay_301, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -73,7 +73,7 @@ theorem call_fun_wrap_mulExpRay_zero_direct rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_mulExpRay] - simp only [yulFunction_fun_wrap_mulExpRay, yulFunction_fun_wrap_mulExpRay_390, + simp only [yulFunction_fun_wrap_mulExpRay, yulFunction_fun_wrap_mulExpRay_363, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -111,7 +111,7 @@ theorem external_fun_wrap_mulExpRay_zero_calldata_result rw [EvmYul.Yul.call.eq_def] simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_mulExpRay] - simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_390, + simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_363, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -193,7 +193,7 @@ theorem external_fun_wrap_mulExpRay_zero_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_mulExpRay] - simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_390, + simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_363, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean index f2a9ea8e2..60b3a4985 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean @@ -122,7 +122,7 @@ theorem call_fun_wrap_expRayToWad_revert_direct rw [show fuel + (extra + 1200) = (fuel + extra) + 1200 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_374, + simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -155,7 +155,7 @@ theorem external_fun_wrap_expRayToWad_calldata_revert rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Seam/Value.lean b/formal/exp/ExpProof/ExpProof/Seam/Value.lean index b171eb4eb..d8d190e19 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Value.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Value.lean @@ -47,7 +47,7 @@ theorem call_fun__expRayKernel_zero_direct rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayKernel] - simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_355, + simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_328, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -143,7 +143,7 @@ theorem call_fun_wrap_expRayToWad_zero_direct rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_374, + simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -181,7 +181,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_result rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -264,7 +264,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -477,7 +477,7 @@ theorem call_fun__expRayKernel_direct rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayKernel] - simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_355, + simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_328, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -654,7 +654,7 @@ theorem call_fun_wrap_expRayToWad_direct rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_374, + simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -714,7 +714,7 @@ theorem external_fun_wrap_expRayToWad_calldata_result rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -815,7 +815,7 @@ theorem external_fun_wrap_expRayToWad_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_374, + simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 896fc6f3b..3fbab2338 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -264,14 +264,6 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_bracket_zero -/-- info: 'ExpYul.call_fun__absSign_direct' depends on axioms: [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in -#print axioms call_fun__absSign_direct - -/-- info: 'ExpYul.call_fun__scaleShift_direct' depends on axioms: [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in -#print axioms call_fun__scaleShift_direct - /-- info: 'ExpRealSpec.mulExpRayTarget_signed_mono' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms ExpRealSpec.mulExpRayTarget_signed_mono diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index d2b92dd47..662ba688b 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -71,7 +71,7 @@ def functionPrefixes : ModelKind → List String "external_fun_wrap_mulExpRay_", "fun_wrap_expRayToWad_", "fun_wrap_mulExpRay_", "fun_expRayToWad_", "fun_mulExpRay_", - "fun__absSign_", "fun__scaleShift_", "fun__octave_", "fun__expRayKernel_", + "fun__octave_", "fun__expRayKernel_", "constant__EXP_RAY_TO_WAD_HI_", "constant__WAD_ZERO_MAX_", "constant_ARITHMETIC_OVERFLOW_", "fun_panic_", "fun_or_", "fun_and_", "fun_clz_"] @@ -751,8 +751,6 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : aliasByPrefix functions "fun_wrap_mulExpRay" "fun_wrap_mulExpRay_", aliasByPrefix functions "fun_expRayToWad" "fun_expRayToWad_", aliasByPrefix functions "fun_mulExpRay" "fun_mulExpRay_", - aliasByPrefix functions "fun__absSign" "fun__absSign_", - aliasByPrefix functions "fun__scaleShift" "fun__scaleShift_", aliasByPrefix functions "fun__octave" "fun__octave_", aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", aliasByPrefix functions "constant__EXP_RAY_TO_WAD_HI" "constant__EXP_RAY_TO_WAD_HI_", From 9807053d9cb812f6e53ad7a8d6a3067e42033bcd Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 19:53:39 +0200 Subject: [PATCH 061/107] Add mulExpRay seam word rewrites Co-Authored-By: Codex --- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 99962a432..a3358ad9a 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -1434,4 +1434,23 @@ theorem uint256_ofNat_sgt_eq_word_evmSgt (a b : Nat) : FormalYul.Preservation.wordNat_word] simp [evmSgt_u256_left, evmSgt_u256_right, u256_evmSgt] +theorem uint256_ofNat_slt_eq_word_evmSlt (a b : Nat) : + EvmYul.UInt256.slt (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b) = + FormalYul.word (evmSlt a b) := by + apply FormalYul.Preservation.eq_of_wordNat_eq + simp only [wordNat_slt, FormalYul.Preservation.wordNat_ofNat, + FormalYul.Preservation.wordNat_word] + have hclosed : u256 (evmSlt a b) = evmSlt a b := by + unfold evmSlt + split <;> simp [u256, WORD_MOD] + simp [evmSlt_u256_left, evmSlt_u256_right, hclosed] + +theorem uint256_ofNat_iszero_eq_word_evmIszero (a : Nat) : + EvmYul.UInt256.isZero (EvmYul.UInt256.ofNat a) = + FormalYul.word (evmIszero a) := by + apply FormalYul.Preservation.eq_of_wordNat_eq + simp only [FormalYul.Preservation.wordNat_iszero, FormalYul.Preservation.wordNat_ofNat, + FormalYul.Preservation.wordNat_word] + simp [FormalYul.Preservation.evmIszero_u256] + end ExpYul From a346ffa1e5b244aa7c6fd45995c14af0a310dc41 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 21:45:13 +0200 Subject: [PATCH 062/107] Tighten the mulExpRay guard and fold the zero multiplier The guard reuses the kernel's closing shift (k > s - 2 is shift < 2), the zero multiplier flows through the shared guard and kernel with its sign reapplied by a branchless sgn(y) multiply, and the upper revert boundary is the first octave (k = 126) past the deficit envelope at the maximal scale headroom (s = 127, y = 0), which also fences the octave reciprocal's wraparound region. mulExpRay(0, x) now takes the same range checks as every other multiplier. Every constant now carries its derivation, the kernel documents its caller contract, and the error-budget comment states the certified constants: the reduced-argument link is 0.00552 (about sqrt(2)/256) and the budget total 0.5737291786393199862, whose image 5^18*B/2^41 = 0.99527 is below the margin. Co-Authored-By: Claude Fable 5 --- src/vendor/Exp.sol | 145 ++++++++++++++++++++++++++++++------------ test/0.8.34/Exp.t.sol | 30 ++++++++- 2 files changed, 131 insertions(+), 44 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 868150227..fa6a0f225 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -8,12 +8,35 @@ import {Clz} from "./Clz.sol"; library Exp { using FastLogic for bool; + // 10¹⁸ ⋅ 2⁶⁷: the largest scale `_expRayKernel` accepts. The kernel's margin and deficit + // budgets are certified at exactly this scale (smaller scales only shrink the error terms), + // and it keeps the kernel's dividend inside 256 bits. uint256 private constant _SCALE_MAX = 0x6f05b59d3b2000000000000000000000; + // clz(_SCALE_MAX); must track _SCALE_MAX (paired by `testScaleMaxClzPairing`). uint256 private constant _SCALE_MAX_CLZ = 129; + // The least x whose octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, i.e. + // ⌈(66⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ 65.5⋅ln(2)⋅10²⁷ ≈ 45.40⋅10²⁷ (CINV is `_octave`'s + // reciprocal): at `expRayToWad`'s fixed headroom s = 67 the deficit envelope reaches one + // output unit at k = 66. int256 private constant _EXP_RAY_TO_WAD_HI = 0x92b2f16cc66c5a4ae96e80d4; + // ⌊10²⁷ ⋅ ln(10⁻¹⁸)⌋: the greatest x with 10¹⁸⋅exp(x / 10²⁷) < 1. At or below it + // `expRayToWad` clamps to zero; the clamp consults only x, so it also discards the + // reduction garbage for x ≲ -2¹⁵¹ where `_octave`'s product wraps. int256 private constant _WAD_ZERO_MAX = -41446531673892822312323846185; - int256 private constant _X_HI = 86296823979713191022445399122; - int256 private constant _X_LO_ZERO = -88376265521393026950697095485; + // The least x whose octave count reaches 126, i.e. ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ + // 125.5⋅ln(2)⋅10²⁷ ≈ 87.00⋅10²⁷: the first octave past the deficit envelope at even the + // maximal scale headroom (s = 127, at y = 0). This comparison doubles as the fence that + // keeps accepted x clear of the region (x ≳ 2¹⁵¹) where `_octave`'s product wraps and k is + // garbage; without it, a garbage k could pass the accuracy guard and the kernel would + // return an unflagged wrong value. + int256 private constant _MUL_EXP_RAY_HI = 86989971160273136331862631244; + // The least x whose octave count reaches -127, i.e. ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ + // -127.5⋅ln(2)⋅10²⁷ ≈ -88.38⋅10²⁷. At or below it `mulExpRay` clamps to zero, which is + // within the bracket at every supported scale (10¹⁸⋅2⁶⁷⋅exp(x/10²⁷) < 0.62); the clamp + // consults only x, so it also discards the reduction garbage for x ≲ -2¹⁵¹ where + // `_octave`'s product wraps. Above it, k ≥ -127 keeps the closing shift below 256 and the + // reduced argument on the certified domain. + int256 private constant _MUL_EXP_RAY_ZERO_MAX = -88376265521393026950697095485; /// @notice Compute the natural exponential of a fixnum with 10**27 (ray) basis, returning the /// result as a fixnum with 10**18 (wad) basis. @@ -39,47 +62,72 @@ library Exp { /// @notice Compute y * exp(x / 10**27), with y's sign reapplied after magnitude evaluation. /// @dev Let A = abs(y) ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m - /// with 0 ≤ m, m ≤ A, and A < m + 2; equivalently the magnitude is either ⌊A⌋ or - /// ⌊A⌋ - 1. Negative y uses the same magnitude bracket and then reapplies the sign. - /// `mulExpRay(0, x) == 0` for every x and `mulExpRay(y, 0) == y` for every supported y. - /// Among accepted inputs, the result is monotone in x: nondecreasing if y ≥ 0 and - /// nonincreasing if y < 0. For a fixed x, among accepted inputs, the result is - /// nondecreasing in y. Jointly, for accepted pairs (y₁, x₁) and (y₂, x₂), the first - /// result is no greater than the second when 0 ≤ y₁ ≤ y₂ and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 - /// and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. Reverts with `Panic(17)` when - /// abs(y) exceeds the supported scale, x is too large, or x and abs(y) cannot preserve - /// the two-unit magnitude bracket with a single-word scaled product. + /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, except that when + /// A < 1 the lower bound pins m = 0. `mulExpRay(0, x) == 0` for every accepted x and + /// `mulExpRay(y, 0) == y` for every supported y. Among accepted inputs, the result is + /// monotone in x: nondecreasing if y ≥ 0 and nonincreasing if y < 0. For a fixed x, + /// among accepted inputs, the result is nondecreasing in y. Jointly, for accepted pairs + /// (y₁, x₁) and (y₂, x₂), the first result is no greater than the second when 0 ≤ y₁ ≤ y₂ + /// and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. + /// + /// Reverts with `Panic(17)` in exactly three cases: abs(y) > 10¹⁸⋅2⁶⁷ (including + /// y = type(int256).min); x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ (regardless of + /// y); or x and abs(y) jointly exhaust the accuracy envelope: with 2ˢ the scale headroom + /// above abs(y) (the largest power of two with abs(y)⋅2ˢ ≤ 10¹⁸⋅2⁶⁷; s = 127 at y = 0), + /// any x whose octave count k = round(x / (10²⁷⋅ln(2))) exceeds s - 2 reverts, except + /// x = 0 (returned exactly at any headroom) and x ≤ -88376265521393026950697095485 ≈ + /// -88.38⋅10²⁷ (clamped to zero at any headroom). Because the headroom shrinks as abs(y) + /// grows, the accepted exponents need not form an interval: at the largest magnitudes, + /// x = 0 is accepted while every other x > -1.5⋅ln(2)⋅10²⁷ reverts, and sufficiently + /// negative x are accepted again. function mulExpRay(int256 y, int256 x) internal pure returns (int256) { - if (y == 0) { - return 0; - } - uint256 ay; uint256 sign; - // Compute `abs(y)` without negating `type(int256).min`. + // Split y into a sign mask and a magnitude without negating `type(int256).min`: + // sign = y >> 255; ay = (y ^ sign) - sign assembly ("memory-safe") { sign := sar(0xff, y) ay := sub(xor(y, sign), sign) } unchecked { + // The scale headroom: the largest s with ay << s ≤ _SCALE_MAX (127 at ay = 0). When + // ay > _SCALE_MAX this underflows — clz comes up short of _SCALE_MAX_CLZ, or the + // decrement below takes s = 0 to 2²⁵⁶ - 1 — leaving garbage whose int256 value is in + // [-129, -1]. Every such ay trips the first guard disjunct below (FastLogic evaluates + // all disjuncts eagerly), so the garbage s and shift are compared but never otherwise + // consumed. uint256 s = Clz.clz(ay) - _SCALE_MAX_CLZ; uint256 scaleMax = _SCALE_MAX; - // Correct the bit-length estimate without branching. + // Aligning ay's top bit with _SCALE_MAX's top bit can still overshoot _SCALE_MAX + // within the same bit length; correct without branching: + // s -= (ay << s) > _SCALE_MAX ? 1 : 0 assembly ("memory-safe") { s := sub(s, gt(shl(s, ay), scaleMax)) } int256 k = _octave(x); - if ((ay > _SCALE_MAX).or(x >= _X_HI).or((x != 0).and(x > _X_LO_ZERO).and(k > int256(s) - 2))) { + int256 shift = int256(s) - k; + // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: + // - abs(y) above the maximal scale; + // - x at or above the octave (k = 126) that exhausts the deficit envelope at even + // the maximal headroom; this comparison also fences accepted x away from + // `_octave`'s wraparound region (see `_MUL_EXP_RAY_HI`); + // - a live x — neither pinned (x = 0, exact at any headroom) nor clamped (at or + // below the zero cutoff, where the result is zero without consulting k, keeping + // deep-negative x with a wrapped octave product accepted) — leaving fewer than two + // bits of closing shift: the deficit envelope (2993/1000 + margin)⋅2ᵏ⁻ˢ reaches + // one output unit at k > s - 2 (see the kernel). + if ((ay > _SCALE_MAX).or(x >= _MUL_EXP_RAY_HI).or((x != 0).and(x > _MUL_EXP_RAY_ZERO_MAX).and(shift < 2))) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } - uint256 m = _expRayKernel(x, k, ay << s, uint256(int256(s) - k), _X_LO_ZERO); - // Apply y's sign without branching: - // m = (m ^ sign) - sign + uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), _MUL_EXP_RAY_ZERO_MAX); + // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale + // is zero) in one branchless step: + // m *= sgn(y) assembly ("memory-safe") { - m := sub(xor(m, sign), sign) + m := mul(m, or(sign, lt(0, ay))) } return int256(m); } @@ -95,7 +143,19 @@ library Exp { } } - /// @dev The rational polynomial approximation kernel. + /// @dev The rational polynomial approximation kernel, shared by `expRayToWad` + /// (scale = 10¹⁸⋅2⁶⁷, shift = 67 - k) and `mulExpRay` (scale = abs(y)⋅2ˢ, shift = s - k). + /// The caller must maintain: + /// - `k == _octave(x)` and `scale ≤ 10¹⁸⋅2⁶⁷`: the margin and deficit budgets below are + /// certified at exactly the maximal scale, and smaller scales only shrink them; + /// - `scale == base << s` for the caller's magnitude base, with `shift == s - k`; + /// - for every accepted x with `zeroCutoff` < x and x ≠ 0: `shift ≥ 2` (the deficit + /// envelope reaches one output unit below that), `_octave`'s product must not wrap + /// (x ≲ 2¹⁵¹), and `shift < 256`. At x = 0 the result is exact for any shift; + /// - for every x ≤ `zeroCutoff`: base⋅exp(x / 10²⁷) < 1, so the clamped-to-zero result + /// satisfies the bracket. The clamp consults only x, so `_octave` wraparound garbage + /// (x ≲ -2¹⁵¹) in k, t, and shift is discarded. + /// When `scale == 0` the returned value is unspecified and the caller must discard it. function _expRayKernel(int256 x, int256 k, uint256 scale, uint256 shift, int256 zeroCutoff) private pure @@ -141,28 +201,29 @@ library Exp { // Ev - t⋅Od; the closing `DIV` floor is counted on the output grid below) and write its // excess over exp(t) as Δ = (ê - exp(t))⋅2¹²⁶ (in Q126 units, one unit = 2⁻¹²⁶). Δ is the // tightest bound the proof technique can bear, in spite of the fact that the worst-case - // error contributions do not co-occur. The budget bounds Δ ≤ 0.5792534503673398887, the sum + // error contributions do not co-occur. The budget bounds Δ ≤ 0.5737291786393199862, the sum // of four one-sided contributions: - // integer Horner truncation: the shared Ev shared cancels to first order in the - // quotient, so its truncation barely perturbs ê; this jitter stays < 0.21706. + // integer Horner truncation: the shared Ev cancels to first order in the quotient, so + // its truncation barely perturbs ê; this jitter stays ≤ 0.2170557036555806152. // argument granularity: v carries t² on the Q123 grid, and its floor only lowers the - // polynomials' shared argument, which lifts ê on the t > 0 half by < 0.32906: one - // v-grain moves the quotient by 2t⋅(Od⋅ΔEv - Ev⋅ΔOd)/(D⋅D′), whose one-signed - // numerator is maximal at each piece's upper edge and whose denominator, when - // analyzed over over 32 domain pieces, has pointwise supremum ≈ 0.3287 at t = - // ln(2)/2). The t < 0 direction is budgeted on the under side. + // polynomials' shared argument, which lifts ê on the t > 0 half by + // ≤ 0.3290521163436398582: one v-grain moves the quotient by + // 2t⋅(Od⋅ΔEv - Ev⋅ΔOd)/(D⋅D′), whose one-signed numerator is maximal at each + // piece's upper edge and whose denominator, analyzed over 32 domain pieces, has + // pointwise supremum ≈ 0.3287 at t = ln(2)/2. The t < 0 direction is budgeted on + // the under side. // rational `Mp`-factor (the dyadic gap between the reciprocal-symmetric form and exp): - // < 0.02210 (its supremum is √2⋅2¹²⁶/(2¹³²-1)). - // reduced-argument gap: the Q128 floor of t only pushes ê downward (that direction is + // ≤ 0.0220970869120796102 (its supremum is √2⋅2¹²⁶/(2¹³²-1)). + // reduced-argument gap: the Q129 floor of t only pushes ê downward (that direction is // budgeted on the under side); the over side is the K27/LN2 constant-grid residue - // (k⋅ln(2) grid error is below 2⁻²²⁹), enveloped one-sidedly at 2⁻¹³³ of reduced - // argument, lifting ê by < 0.01105 (√2⋅2¹²⁶/(32⋅2¹²⁸) = √2/128). + // (the K27 coefficient-grid term is below 2⁻¹³³ over |x| < 2⁹⁷ and the k⋅ln(2) + // grid term below 2⁻²²⁸), lifting ê by ≤ 0.0055242717280199026 (≈ √2/256). // // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid unit // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale ≤ 10¹⁸⋅2⁶⁷, Δ's // image is below one grid unit: the Q89 closing bases confine the over-side jitter so that - // 5¹⁸⋅Δ/2⁴¹ < 1. The margin is the least integer strictly above that image: 0x01, worth - // 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so the + // 5¹⁸⋅Δ/2⁴¹ ≤ 0.99527 < 1. The margin is the least integer that dominates the image: 0x01, + // worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so the // pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is certified // directly on the output grid, piecewise over the 32 domain pieces (per-piece denominator // floors confine the truncation amplification): q ≥ scale⋅exp(t) - 2993/1000, where @@ -181,7 +242,8 @@ library Exp { // ⌊10²⁷⋅ln(2)/2⌋, matching `lnWadToRay`'s image over [1/√2, √2). // // Monotonicity: one unit step in x multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves the - // pre-floor accumulator by at least 10¹⁸⋅2⁶⁷⋅10⁻²⁷/√2 ≈ 1.0⋅10¹¹ grid units. The error + // pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live + // scale exceeds 10¹⁸⋅2⁶⁶: the maximal headroom leaves scale > 10¹⁸⋅2⁶⁷/2). The error // terms above confine the accumulator to a band of width 5¹⁸⋅Δ/2⁴¹ + 2993/1000 ≈ 4.0 grid // units just below E's grid image at every octave (in grid units the band is k-independent; // an octave seam rescales E and the band together), so the per-step gain exceeds any @@ -192,8 +254,9 @@ library Exp { // value. assembly ("memory-safe") { // t in Q129. K27 = round(2²³⁵ / 10²⁷) and LN2 = round(ln(2) ⋅ 2²³⁵). Subtracting k⋅LN2 - // from K27⋅x at the Q235 product basis (so the k⋅ln(2) rounding error is ~2⁻²³⁵, far - // below an output ulp) then one `sar(106, …)` leaves the reduced argument at Q129. + // from K27⋅x at the Q235 product basis (so the k⋅ln(2) rounding error stays below + // 2⁻²²⁸ over |k| ≤ 127, far below an output ulp) then one `sar(106, …)` leaves the + // reduced argument at Q129. let t := sar( 0x6a, diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index 90778ef7c..0c97de970 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -3,14 +3,18 @@ pragma solidity ^0.8.34; import {Exp} from "src/vendor/Exp.sol"; import {Ln} from "src/vendor/Ln.sol"; +import {Clz} from "src/vendor/Clz.sol"; import {Test, stdError} from "@forge-std/Test.sol"; contract ExpTest is Test { uint256 private constant _SCALE_MAX = 0x6f05b59d3b2000000000000000000000; // First input whose octave count exceeds the supported range; `expRayToWad` reverts here. int256 private constant _TOO_BIG = 0x92b2f16cc66c5a4ae96e80d4; - // First input whose octave count reaches 125. + // First input whose octave count reaches 125: the accuracy-guard boundary at the deepest + // scale headroom reachable with a nonzero multiplier (abs(y) = 1, s = 126). int256 private constant _X_HI = 86296823979713191022445399122; + // First input whose octave count reaches 126; `mulExpRay` reverts here for every y. + int256 private constant _MUL_HI = 86989971160273136331862631244; // First input whose octave count reaches -127; all supported magnitudes floor to zero here. int256 private constant _X_LO_ZERO = -88376265521393026950697095485; // floor(1e27 * ln(1e-18)): the greatest input whose exact result is < 1 and floors to 0. @@ -211,9 +215,25 @@ contract ExpTest is Test { assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), 0), -int256(_SCALE_MAX), "negative scale max"); } - function testMulExpRayZeroY() external pure { + /// A zero multiplier takes the same guard as every other y: any x below the k = 126 fence is + /// accepted (the maximal headroom s = 127 keeps the accuracy guard clear through k = 125) and + /// returns zero; at or above the fence it reverts. + function testMulExpRayZeroY() external { + assertEq(Exp.mulExpRay(0, 0), 0, "zero x"); assertEq(Exp.mulExpRay(0, type(int256).min), 0, "min x"); - assertEq(Exp.mulExpRay(0, type(int256).max), 0, "max x"); + assertEq(Exp.mulExpRay(0, _X_LO_ZERO), 0, "clamp boundary"); + assertEq(Exp.mulExpRay(0, _X_HI), 0, "octave 125 accepted only at zero magnitude"); + assertEq(Exp.mulExpRay(0, _MUL_HI - 1), 0, "greatest accepted x"); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(0, _MUL_HI); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(0, type(int256).max); + } + + /// `_SCALE_MAX_CLZ` inside the library must track `_SCALE_MAX`. + function testScaleMaxClzPairing() external pure { + assertEq(_SCALE_MAX, uint256(1e18) << 67, "scale is the wad unit at 67 bits of headroom"); + assertEq(Clz.clz(_SCALE_MAX), 129, "_SCALE_MAX_CLZ"); } function testMulExpRayLowerZero() external pure { @@ -241,8 +261,12 @@ contract ExpTest is Test { } function testMulExpRayHighGuardReverts() external { + // Octave 125 exceeds the headroom of any nonzero magnitude (accuracy guard) ... vm.expectRevert(stdError.arithmeticError); this.mulExpRayExternal(1, _X_HI); + // ... and octave 126 is past the envelope for every y (unconditional fence). + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(1, _MUL_HI); vm.expectRevert(stdError.arithmeticError); this.mulExpRayExternal(1, type(int256).max); } From a2944faf231487d6aeeb38fb1195bdeb0e95139b Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 22:37:49 +0200 Subject: [PATCH 063/107] Rebuild the mulExpRay proof seam on the shared guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Yul importer emits, for every stable alias, a suffix-free body lemma (yulFunctionBody_*) and aliases the mulExpRay constants, so the hand-written seam proofs never name a solc-numbered definition. The mulExpRay model trees mirror the shared guard (slt(shift, 2)) and the closing sgn(y) multiply; the value and panic domains are stated with the exact signed comparisons of the compiled guard; and one value-path reduction, run_mul_exp_ray_evm_eq_tree_of_guard, covers every multiplier at once — sgn(0) collapses the zero multiplier's result at the tree level (run_mul_exp_ray_evm_zero_of_guard), so the zero-path duplicate proofs are gone, as is the unused dynamic-accumulator definition. Comments across the Floor and Mono layers state the shipped parameters (MARGIN = 1, closing shift 67 - k on the 2^67 grid, k <= 65, budget image (5^18/2^41)*B with B = 5737291786393199862/10^19, t at Q129, Qexp = 2^129). Co-Authored-By: Claude Fable 5 Co-Authored-By: Codex --- formal/exp/ExpProof/ExpProof/Floor/CapsV.lean | 2 +- .../ExpProof/ExpProof/Floor/CertDefsV.lean | 2 +- formal/exp/ExpProof/ExpProof/Floor/Fold.lean | 2 +- .../ExpProof/ExpProof/Floor/R0BoundHolds.lean | 10 +- formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean | 15 +- .../ExpProof/ExpProof/Floor/R0ExpUnder.lean | 7 +- .../exp/ExpProof/ExpProof/Floor/Reduce.lean | 2 +- .../ExpProof/ExpProof/Floor/RoundTrip.lean | 8 +- formal/exp/ExpProof/ExpProof/Floor/Spec.lean | 10 +- formal/exp/ExpProof/ExpProof/Mono/Consts.lean | 22 +- .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 43 +- formal/exp/ExpProof/ExpProof/Mono/Tree.lean | 8 +- formal/exp/ExpProof/ExpProof/Mul.lean | 14 +- formal/exp/ExpProof/ExpProof/Mul/Bridge.lean | 7 - formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 81 ++-- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 128 +++--- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 427 +++++++++++++----- formal/exp/ExpProof/ExpProof/Seam/Revert.lean | 8 +- formal/exp/ExpProof/ExpProof/Seam/Value.lean | 20 +- formal/exp/ExpProof/ExpProof/Theorems.lean | 43 +- formal/yul/YulImporter.lean | 45 +- 21 files changed, 575 insertions(+), 329 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean b/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean index 7fbb0ef99..0abc59182 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean @@ -15,7 +15,7 @@ The v-form cell covers (`Cert/ExpVUp`, `Cert/ExpVLo`, `Cert/ExpVNum`, `Cert/ExpV four v-form certificate polynomials nonnegative over `t ∈ [0, H129]`. This module converts that nonnegativity into the two bare-argument Taylor caps the floor layer folds with `2^k`, targeting the implementation's exact **v-form** rational `ê_v(t) = NUM(t)/DEN(t)` (built from the even/odd Horner -polynomials in `v = t²`) nudged by the dyadic margin, with `Qexp = 2^128`: +polynomials in `v = t²`) nudged by the dyadic margin, with `Qexp = 2^129`: * `capExpUp` — never-over `exp(t/Qexp) ≤ yUB(t)/wUB(t)` with `yUB/wUB = ê_v·(1 + 2⁻¹³²)`; * `capExpLo` — not-two-below `yLB(t)/wLB(t) ≤ exp(t/Qexp)` with `yLB/wLB = ê_v·(1 − 2⁻¹³²)`. diff --git a/formal/exp/ExpProof/ExpProof/Floor/CertDefsV.lean b/formal/exp/ExpProof/ExpProof/Floor/CertDefsV.lean index a5b595e85..eef5ea236 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/CertDefsV.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/CertDefsV.lean @@ -92,7 +92,7 @@ def expN27 : List Int := expPolyNum [0, 1] [(Qexp : Int)] 27 `yUB/wUB = ê_v·(1 + 2⁻¹³²)` and `yLB/wLB = ê_v·(1 − 2⁻¹³²)`. The tight `2⁻¹³²` margins keep the `2¹²⁶·(ê_v − exp)` contribution to the runtime over/under budget below `2¹²⁶·exp·2⁻¹³² ≈ 0.022` ulp, -inside the `MARGIN`; the realized envelope `2¹²⁶·|ê_v − exp(t/2¹²⁸)| ≤ 0.0075` ulp leaves slack. -/ +inside the `MARGIN`; the realized envelope `2¹²⁶·|ê_v − exp(t/2¹²⁹)| ≤ 0.0075` ulp leaves slack. -/ def yUB : List Int := polyScale (2 ^ 132 + 1) numExpV def wUB : List Int := polyScale (2 ^ 132) denExpV diff --git a/formal/exp/ExpProof/ExpProof/Floor/Fold.lean b/formal/exp/ExpProof/ExpProof/Floor/Fold.lean index 2380f96ed..ff0f57c7d 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/Fold.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/Fold.lean @@ -38,7 +38,7 @@ theorem accumReal_eq {x : Nat} (hx : x < 2 ^ 256) refine ⟨s, hsint, ?_⟩ unfold accumReal rw [hseq] - -- the integer shift argument has the closed value `r0 − 3` + -- the integer shift argument has the closed value `r0 − 1` rw [hargeq] push_cast ring diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean b/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean index 0a6239963..268b61ab2 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean @@ -9,12 +9,12 @@ import ExpProof.Seam.RealExp The per-point `r0`-vs-`exp` brackets (`r0_real_over_within`, `r0_real_under_within`) and the below-clamp bound (`belowC_target_lt_one`) establish the never-over and deficit-under-one facts about the real pre-floor accumulator unconditionally and axiom-clean, via the octave fold -`E·2^s = WAD·2⁶⁸·exp(rt)` (`WAD·2⁶⁸ = scaleQ67`; `s = 68 − k`, the closing shift; `k ≤ 64` so -`s ≥ 4`). +`E·2^s = WAD·2⁶⁷·exp(rt)` (`WAD·2⁶⁷ = scaleQ67`; `s = 67 − k`, the closing shift; `k ≤ 65` so +`s ≥ 2`). -* `accumReal_over` ⟸ `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴⁰)·B` and `(5¹⁸/2⁴⁰)·B ≤ MARGIN = 3`; +* `accumReal_over` ⟸ `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` and `(5¹⁸/2⁴¹)·B ≤ MARGIN = 1`; * `accumReal_under` ⟸ `scaleQ67·exp(rt) ≤ r0 + U` (`U = 2993/1000`) and - `U + MARGIN < 2⁴ ≤ 2^s`. + `U + MARGIN < 2² ≤ 2^s`. These make the global floor-or-one-less and one-unit underestimation brackets hypothesis-free. -/ @@ -44,7 +44,7 @@ theorem accumReal_over (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 rw [hfold] have hwad : (WAD : Real) = (10 ^ 18 : Real) := by unfold WAD; norm_num rw [hwad] - -- (5¹⁸/2⁴⁰)·B ≤ 1 = MARGIN + -- (5¹⁸/2⁴¹)·B ≤ 1 = MARGIN have hBM : (3814697265625 : Real) * 5737291786393199862 / (10000000000000000000 * 2199023255552) ≤ 1 := by norm_num linarith [hover, hBM] diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean index 43ba5b407..3466e63c9 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean @@ -8,9 +8,8 @@ import Mathlib.Analysis.SpecialFunctions.Pow.Real /-! # The per-point `r0`-vs-`exp` bridge (never-over side) -This module bounds the scaled quotient `r0Tree x` above by `(10¹⁸·2⁶⁸)·exp(rt)` plus the -never-over budget (stated `2⁴⁰`-scaled so every constant stays integral: `2⁴⁰·r0 ≤ -5¹⁸·2¹²⁶·exp(rt) + 5¹⁸·B`) +This module bounds the scaled quotient `r0Tree x` above by `scaleQ67·exp(rt) = (10¹⁸·2⁶⁷)·exp(rt)` +plus the never-over budget image `(5¹⁸/2⁴¹)·B` (`rt = X/RAY − k·ln2` the reduced argument), the analytic content the floor brackets (`Floor.R0BoundHolds`) consume. The chain has four links: @@ -25,7 +24,8 @@ never-over budget (stated `2⁴⁰`-scaled so every constant stays integral: `2 4. **`exp(t/2¹²⁸)` vs `exp(rt)`** — the reduced-argument gap (`Floor.Reduce`), `≤ 55242717280199026/10¹⁹`. -The total is the budget `B = 5737291786393199862/10¹⁹`; `MARGIN = ⌊5¹⁸·B⌋ + 1`. On the `t ≤ 0` +The total is the budget `B = 5737291786393199862/10¹⁹`, whose image `(5¹⁸/2⁴¹)·B ≈ 0.9953` +sits below `MARGIN = 1`. On the `t ≤ 0` half link 2 is free (the grain moves `ê` the other way) and links 3–4 shrink (`ê ≤ 1`), so the same `B` covers both halves. -/ @@ -825,9 +825,8 @@ theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * (DENv v t : Real) := mul_le_mul_of_nonneg_left hDENlowR (by norm_num) -/-- **The per-point never-over (nonneg half).** `r0 ≤ 2¹²⁶·exp(rt) + B` with the four-link budget -`B = 5737291786393199862/10¹⁹`: link-1 jitter `≤ 0.6207…`, granularity `≤ 0.3291…`, the `Mp` -factor `≤ √2·2¹²⁶/(2¹³²−1) ≤ 0.0442…`, and the reduced-argument gap `≤ √2/128 ≤ 0.0111…`. -/ +/-- **The per-point never-over (nonneg half).** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` with the +four-link budget `B = 5737291786393199862/10¹⁹` itemized in the module header. -/ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) (htnn : 0 ≤ int256 (tTree x)) : @@ -1099,7 +1098,7 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) linarith [hlink1, hgranR, hNEMp, hcMp, hEtErt] /-- **Per-point never-over (tight, any sign):** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴⁰)·B` -(the budget's image is strictly below `MARGIN = 3`). -/ +(the budget's image is strictly below `MARGIN = 1`). -/ theorem r0_real_over_within {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean index 3b7f8c94f..c6b337633 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean @@ -12,8 +12,11 @@ This module contains the counterpart to the never-over `r0_real_over_within`: th 3. the `Mp` factor, `≤ 2/25` (via `r0 ≤ 1.45·scaleQ67`); 4. the under-direction reduced-argument gap, `≤ 307/1000` (via `exp(rt) ≤ √2·(1+ε)`). -The sum `2378/1000 + 2/25 + (5¹⁸/2⁴¹)·1644901622230542074/10¹⁹ + 307/1000 ≤ 2993/1000` feeds the `k = 64` deficit -envelope `(2993/1000 + MARGIN)/2² < 1`. The module closes with the octave-seam `r0`-doubling +Per sign half the links sum inside the budget: `2378/1000 + 2/25 + 307/1000 ≤ 2993/1000` on the +`t ≥ 0` half (granularity free there) and `2378/1000 + 2/25 + +(5¹⁸/2⁴¹)·1644901622230542074/10¹⁹ + 218/1000 ≤ 2993/1000` on the `t ≤ 0` half. The budget feeds +the `k = 65` deficit envelope `(2993/1000 + MARGIN)/2² < 1`. The module closes with the +octave-seam `r0`-doubling bound `r0₁ + 3 ≤ 2·r0₂` (`SeamR0Bound`), where the `1 − exp(−1/RAY)` seam slack (≈ `8.5·10¹⁰` grid units against `r0₂ > 2¹²³`) dwarfs both per-point budgets and the three integer units. -/ diff --git a/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean b/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean index 5a30994f3..014e32b89 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean @@ -5,7 +5,7 @@ import ExpProof.Spec.RealExp /-! # The reduced-argument real identity (gap-1) -The runtime forms the reduced argument `t = tTree x` (Q128) and octave index `k = kTree x` so that +The runtime forms the reduced argument `t = tTree x` (Q129) and octave index `k = kTree x` so that `exp(x/RAY) = 2^k · exp(rt)` with `rt = X/RAY − k·ln2` (`X = int256 x`). To fold the cert's `exp(t/2¹²⁹)` bound onto the target, the reduced argument `rt` must coincide with `t/2¹²⁹` up to a margin the runtime `MARGIN` absorbs: diff --git a/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean b/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean index c9ffb796e..9045fc947 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean @@ -33,13 +33,13 @@ set_option maxRecDepth 100000 /-! ## Strict never-over: the accumulator stays a positive distance below the target -`accumReal_over` gives `accumReal x ≤ E`. With `B' = (5¹⁸/2⁴⁰)·B ≈ 2.0097` the never-over -envelope's image on the output grid, `MARGIN = 3` exceeds it strictly — the slack -`δ = MARGIN − B' ≈ 0.99` (worth `δ/2^s` after the closing shift). The round trip needs this +`accumReal_over` gives `accumReal x ≤ E`. With `B' = (5¹⁸/2⁴¹)·B ≈ 0.99527` the never-over +envelope's image on the output grid, `MARGIN = 1` exceeds it strictly — the slack +`δ = MARGIN − B' ≈ 0.0047` (worth `δ/2^s` after the closing shift). The round trip needs this strictness to rule out `accumReal x = w` exactly. -/ /-- **Strict never-over.** On the region the real pre-floor accumulator is strictly below the -target. The proven over bound `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴⁰)·B` plus `(5¹⁸/2⁴⁰)·B < MARGIN` +target. The proven over bound `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` plus `(5¹⁸/2⁴¹)·B < MARGIN` give a strictly negative residue. -/ theorem accumReal_over_strict (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : diff --git a/formal/exp/ExpProof/ExpProof/Floor/Spec.lean b/formal/exp/ExpProof/ExpProof/Floor/Spec.lean index be96bd75c..c459a46fd 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/Spec.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/Spec.lean @@ -8,13 +8,13 @@ import ExpProof.Mono.RangeNonneg # Floor + branch assembly: the public `Real.exp` brackets `run_exp_ray_to_wad_evm_eq_expTree` returns `expTree x`, the clamp/pin shell around the floored -accumulator `r1Tree x = shr(68 − k, r0 − MARGIN)`. On the meaningful region the closing shift -`s = 68 − k ∈ [4, 129]` is positive and the shift argument `arg = r0 − MARGIN` is a +accumulator `r1Tree x = shr(67 − k, r0 − MARGIN)` with `MARGIN = 1`. On the meaningful region the +closing shift `s = 67 − k ∈ [2, 127]` is positive and the shift argument `arg = r0 − MARGIN` is a nonnegative canonical word, so the runtime result is exactly the integer floor `⌊arg / 2^s⌋` of the *real* pre-floor accumulator ``` -A = (r0 − MARGIN) / 2^(68 − k). +A = (r0 − MARGIN) / 2^(67 − k). ``` The two floor facts `(r : Real) ≤ A` and `A < (r : Real) + 1` (i.e. `r = ⌊A⌋`) are established here @@ -87,10 +87,10 @@ theorem shr_real_floor {W s : Nat} (hs : s < 256) (hWw : W < 2 ^ 256) (hWnn : 0 /-! ## The runtime accumulator as a real number For `x > 0` in the meaningful region the result is the body word, `expTree x = r1Tree x`, with -`r1Tree x = evmShr (68 − k) (r0 − MARGIN)`. Its real pre-floor accumulator is +`r1Tree x = evmShr (67 − k) (r0 − MARGIN)`. Its real pre-floor accumulator is ``` -A x = int256 (r0 − MARGIN) / 2^(68 − k). +A x = int256 (r0 − MARGIN) / 2^(67 − k). ``` -/ diff --git a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean index 205bdb32c..64df92e41 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean @@ -43,8 +43,8 @@ abbrev foldShift : Nat := 0x43 abbrev scaleQ67 : Nat := 0x6f05b59d3b2000000000000000000000 abbrev scaleMaxClz : Nat := 0x81 abbrev marginWord : Nat := 0x1 -abbrev xHiMulExpRay : Nat := 0x0116d70f49dec622d4bda70c52 -abbrev xLoZeroMulExpRay : Nat := 0xfffffffffffffffffffffffffffffffffffffffee270ddd64709e8aac2676ec3 +abbrev mulExpRayHi : Nat := 0x119146ae9d22b7454e84ce34c +abbrev mulExpRayZeroMax : Nat := 0xfffffffffffffffffffffffffffffffffffffffee270ddd64709e8aac2676ec3 theorem scaleQ67_eq : (scaleQ67 : Int) = 3814697265625 * 2 ^ 85 := by unfold scaleQ67; norm_num @@ -63,21 +63,21 @@ theorem int256_C0thresh : int256 C0thresh = 45401140326676417766828703956 := by unfold C0thresh int256 norm_num -theorem int256_xHiMulExpRay : int256 xHiMulExpRay = 86296823979713191022445399122 := by - unfold xHiMulExpRay int256 +theorem int256_mulExpRayHi : int256 mulExpRayHi = 86989971160273136331862631244 := by + unfold mulExpRayHi int256 norm_num -theorem int256_xLoZeroMulExpRay : - int256 xLoZeroMulExpRay = -88376265521393026950697095485 := by - unfold xLoZeroMulExpRay int256 +theorem int256_mulExpRayZeroMax : + int256 mulExpRayZeroMax = -88376265521393026950697095485 := by + unfold mulExpRayZeroMax int256 norm_num -theorem xHiMulExpRay_lt : xHiMulExpRay < 2 ^ 256 := by - unfold xHiMulExpRay +theorem mulExpRayHi_lt : mulExpRayHi < 2 ^ 256 := by + unfold mulExpRayHi norm_num -theorem xLoZeroMulExpRay_lt : xLoZeroMulExpRay < 2 ^ 256 := by - unfold xLoZeroMulExpRay +theorem mulExpRayZeroMax_lt : mulExpRayZeroMax < 2 ^ 256 := by + unfold mulExpRayZeroMax norm_num end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean index 7c5f31be9..fdef523eb 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -4,8 +4,9 @@ import ExpProof.Mono.Tree # `mulExpRay` runtime normal form The dynamic-scale entrypoint shares the exponent kernel with `expRayToWad`. This file names the -extra word computations around that kernel: absolute-value/sign extraction, scale shift selection, -dynamic closing shift, and sign reapplication. +extra word computations around that kernel: absolute-value/sign extraction, scale-headroom +selection, the dynamic closing shift, the panic-guard word, and the closing `sgn(y)` multiply +that both reapplies the sign and collapses the zero multiplier. -/ namespace ExpYul @@ -35,19 +36,16 @@ def scaleShiftTree (ay : Nat) : Nat := def mulScaleTree (y : Nat) : Nat := evmShl (scaleShiftTree (absTree y)) (absTree y) -/-- Dynamic closing shift `S - k`. -/ +/-- Dynamic closing shift `S - k`, shared by the guard and the kernel call. -/ def mulShiftTree (y x : Nat) : Nat := evmSub (scaleShiftTree (absTree y)) (kTree x) /-- The branch word for the `Panic(17)` guard. -/ def mulExpGuardTree (y x : Nat) : Nat := - let ay := absTree y - let s := scaleShiftTree ay - let k := kTree x - let outOfRange := evmOr (evmGt ay scaleQ67) (evmIszero (evmSlt x xHiMulExpRay)) + let outOfRange := evmOr (evmGt (absTree y) scaleQ67) (evmIszero (evmSlt x mulExpRayHi)) let inaccurate := - evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x xLoZeroMulExpRay)) - (evmSgt k (evmSub s 2)) + evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) + (evmSlt (mulShiftTree y x) 2) evmOr outOfRange inaccurate /-- The dynamic-scaled quotient before the closing shift. -/ @@ -55,16 +53,21 @@ def r0MulTree (y x : Nat) : Nat := evmDiv (evmMul (mulScaleTree y) (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) -/-- The nonnegative magnitude returned by the shared kernel before the sign mask is applied. -/ +/-- The nonnegative magnitude returned by the shared kernel before the `sgn(y)` multiply. -/ def mulMagnitudeTree (y x : Nat) : Nat := evmAdd (evmIszero x) - (evmMul (evmSlt xLoZeroMulExpRay x) + (evmMul (evmSlt mulExpRayZeroMax x) (evmShr (mulShiftTree y x) (evmSub (r0MulTree y x) marginWord))) -/-- Signed result word after applying `y`'s sign mask. -/ +/-- `sgn(y)` as a word: the sign mask (`-1`) for negative inputs, `1` for positive inputs, and +`0` for a zero multiplier. -/ +def sgnTree (y : Nat) : Nat := + evmOr (signTree y) (evmLt 0 (absTree y)) + +/-- The result word: the kernel magnitude times `sgn(y)`, which reapplies the sign and zeroes +the (unspecified) magnitude of a zero multiplier in one step. -/ def mulExpTree (y x : Nat) : Nat := - let m := mulMagnitudeTree y x - evmSub (evmXor m (signTree y)) (signTree y) + evmMul (mulMagnitudeTree y x) (sgnTree y) theorem absTree_lt (y : Nat) : absTree y < 2 ^ 256 := by unfold absTree @@ -96,6 +99,16 @@ theorem mulMagnitudeTree_lt (y x : Nat) : mulMagnitudeTree y x < 2 ^ 256 := by theorem mulExpTree_lt (y x : Nat) : mulExpTree y x < 2 ^ 256 := by unfold mulExpTree - exact evmSub_lt _ _ + exact FormalYul.Preservation.evmMul_lt_pow256 _ _ + +theorem sgnTree_zero : sgnTree 0 = 0 := by + simp [sgnTree, signTree, absTree, Common.Word.evmXor, evmSar, evmSub, evmLt, evmOr, + u256, WORD_MOD] + +/-- A zero multiplier's result word is zero: `sgn(0) = 0` collapses the kernel output. -/ +theorem mulExpTree_zero (x : Nat) : mulExpTree 0 x = 0 := by + unfold mulExpTree + rw [sgnTree_zero] + simp [evmMul, u256, WORD_MOD] end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/Tree.lean b/formal/exp/ExpProof/ExpProof/Mono/Tree.lean index 586af9d5c..824a3a426 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Tree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Tree.lean @@ -19,7 +19,7 @@ set_option maxRecDepth 100000 def kTree (x : Nat) : Nat := evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)) -/-- Reduced argument `t` in Q128. -/ +/-- Reduced argument `t` in Q129. -/ def tTree (x : Nat) : Nat := evmSar tArgShift (evmSub (evmMul k27Q235 x) (evmMul ln2Q235 (kTree x))) @@ -44,15 +44,15 @@ def odTree (x : Nat) : Nat := (evmAdd od1 (evmShr odShift1 (evmMul od0 v))) v))) v))) v)) -/-- `t * Od(v)` in Q88. -/ +/-- `t * Od(v)` in Q89. -/ def todTree (x : Nat) : Nat := evmSar todShift (evmMul (tTree x) (odTree x)) -/-- `10¹⁸·exp(t)` on the `2⁶⁸` output grid: the numerator is pre-scaled by `10¹⁸·2⁶⁸ = 5¹⁸·2⁸⁶` +/-- `10¹⁸·exp(t)` on the `2⁶⁷` output grid: the numerator is pre-scaled by `10¹⁸·2⁶⁷ = 5¹⁸·2⁸⁵` before the single `DIV`. -/ def r0Tree (x : Nat) : Nat := evmDiv (evmMul scaleQ67 (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) -/-- The floored, octave-scaled, margin-subtracted accumulator on the `2⁶⁸` output grid. -/ +/-- The floored, octave-scaled, margin-subtracted accumulator on the `2⁶⁷` output grid. -/ def r1Tree (x : Nat) : Nat := evmShr (evmSub foldShift (kTree x)) (evmSub (r0Tree x) marginWord) diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index a35eaeff4..db62713ba 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -92,10 +92,18 @@ theorem mulExpRay_run_bracket_zero_of_run {x : Nat} MulExpRayRunBracket 0 x := ⟨0, hrun, mulExpRayBracket_zero_result (int256 x)⟩ -/-- The compiled runtime satisfies the public bracket spec unconditionally for zero magnitude. -/ -theorem mulExpRay_run_bracket_zero (x : Nat) : +/-- The compiled runtime returns zero for a zero multiplier whenever the guard accepts: +`sgn(0) = 0` collapses the kernel output at the tree level. -/ +theorem run_mul_exp_ray_evm_zero_of_guard (x : Nat) + (hguard : mulExpGuardTree 0 x = 0) : + run_mul_exp_ray_evm 0 x = .ok 0 := by + simpa [mulExpTree_zero] using run_mul_exp_ray_evm_eq_tree_of_guard 0 x hguard + +/-- The compiled runtime satisfies the public bracket spec at zero magnitude whenever the guard +accepts. -/ +theorem mulExpRay_run_bracket_zero (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : MulExpRayRunBracket 0 x := - mulExpRay_run_bracket_zero_of_run (run_mul_exp_ray_evm_zero x) + mulExpRay_run_bracket_zero_of_run (run_mul_exp_ray_evm_zero_of_guard x hguard) /-- The `y = 10^18` magnitude target is the existing `expRayToWad` target. -/ theorem mulExpRayMagnitudeTarget_wad (x : Int) : diff --git a/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean b/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean index fd8b5d60e..fef820b05 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Bridge.lean @@ -17,13 +17,6 @@ open ExpRealSpec noncomputable section -set_option maxRecDepth 100000 - -/-- The dynamic real pre-floor accumulator of the shared kernel body. -/ -def mulAccumReal (y x : Nat) : Real := - (int256 (evmSub (r0MulTree y x) marginWord) : Real) / - (2 ^ (mulShiftTree y x) : Real) - /-- The public magnitude bracket follows from the floor step, never-over accumulator bound, and deficit-under-one accumulator bound. -/ theorem mulExpRayMagnitudeBracket_of_accum {y x m : Int} {A : Real} diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean index fc68d0e6a..2559b3f91 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -3,10 +3,12 @@ import ExpProof.Mono.MulTree /-! # `mulExpRay` value and panic domains -The runtime guard partitions canonical calldata into a value path and a `Panic(17)` path. The value -domain keeps the same short-circuits as the implementation: zero multiplier returns before any -range checks, sufficiently small exponents clamp to zero without needing the accuracy guard, and -the scale point is accepted independently of the `k ≤ s - 2` guard. +The runtime guard partitions canonical calldata into a value path and a `Panic(17)` path. Every +multiplier takes the same guard: the magnitude bound, the unconditional upper fence at the first +octave past the deficit envelope, and the accuracy test on the closing shift — the latter waived +at the exact scale point `x = 0` and at or below the zero-clamp cutoff. Each predicate mirrors +one signed comparison of the compiled guard; `int256 (mulShiftTree y x) < 2` is exactly the +runtime's `slt(shift, 2)`. -/ namespace ExpYul @@ -14,8 +16,6 @@ namespace ExpYul open FormalYul open FormalYul.Preservation -set_option maxRecDepth 100000 - /-- ABI words transported into this proof layer. -/ def MulExpRayCanonical (y x : Nat) : Prop := y < 2 ^ 256 ∧ x < 2 ^ 256 @@ -23,61 +23,46 @@ def MulExpRayCanonical (y x : Nat) : Prop := /-- The exact successful-input domain induced by the implementation guard. -/ def MulExpRayValueDomain (y x : Nat) : Prop := MulExpRayCanonical y x ∧ - (int256 y = 0 ∨ - absTree y ≤ scaleQ67 ∧ - int256 x < int256 xHiMulExpRay ∧ - (int256 x ≤ int256 xLoZeroMulExpRay ∨ - int256 x = 0 ∨ - int256 (kTree x) ≤ (scaleShiftTree (absTree y) : Int) - 2)) + absTree y ≤ scaleQ67 ∧ + int256 x < int256 mulExpRayHi ∧ + (int256 x = 0 ∨ + int256 x ≤ int256 mulExpRayZeroMax ∨ + 2 ≤ int256 (mulShiftTree y x)) -/-- The exact nonzero-multiplier panic domain induced by the implementation guard. -/ +/-- The exact panic domain induced by the implementation guard. -/ def MulExpRayPanicDomain (y x : Nat) : Prop := MulExpRayCanonical y x ∧ - int256 y ≠ 0 ∧ - (scaleQ67 < absTree y ∨ - int256 xHiMulExpRay ≤ int256 x ∨ - (int256 x ≠ 0 ∧ - int256 xLoZeroMulExpRay < int256 x ∧ - (scaleShiftTree (absTree y) : Int) - 2 < int256 (kTree x))) + (scaleQ67 < absTree y ∨ + int256 mulExpRayHi ≤ int256 x ∨ + (int256 x ≠ 0 ∧ + int256 mulExpRayZeroMax < int256 x ∧ + int256 (mulShiftTree y x) < 2)) /-- Canonical inputs are either accepted by the value guard or rejected by the panic guard. -/ theorem mulExpRay_value_or_panic_of_canonical {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := by - by_cases hy0 : int256 y = 0 - · exact Or.inl ⟨hcanon, Or.inl hy0⟩ - · by_cases hscale : absTree y ≤ scaleQ67 - · by_cases hxhi : int256 x < int256 xHiMulExpRay - · by_cases hxlo : int256 x ≤ int256 xLoZeroMulExpRay - · exact Or.inl ⟨hcanon, Or.inr ⟨hscale, hxhi, Or.inl hxlo⟩⟩ - · by_cases hx0 : int256 x = 0 - · exact Or.inl ⟨hcanon, Or.inr ⟨hscale, hxhi, Or.inr (Or.inl hx0)⟩⟩ - · by_cases hk : - int256 (kTree x) ≤ (scaleShiftTree (absTree y) : Int) - 2 - · exact Or.inl ⟨hcanon, Or.inr ⟨hscale, hxhi, Or.inr (Or.inr hk)⟩⟩ - · exact Or.inr ⟨hcanon, hy0, - Or.inr (Or.inr ⟨hx0, by omega, by omega⟩)⟩ - · exact Or.inr ⟨hcanon, hy0, Or.inr (Or.inl (by omega))⟩ - · exact Or.inr ⟨hcanon, hy0, Or.inl (by omega)⟩ + by_cases hscale : absTree y ≤ scaleQ67 + · by_cases hxhi : int256 x < int256 mulExpRayHi + · by_cases hx0 : int256 x = 0 + · exact Or.inl ⟨hcanon, hscale, hxhi, Or.inl hx0⟩ + · by_cases hxlo : int256 x ≤ int256 mulExpRayZeroMax + · exact Or.inl ⟨hcanon, hscale, hxhi, Or.inr (Or.inl hxlo)⟩ + · by_cases hshift : 2 ≤ int256 (mulShiftTree y x) + · exact Or.inl ⟨hcanon, hscale, hxhi, Or.inr (Or.inr hshift)⟩ + · exact Or.inr ⟨hcanon, Or.inr (Or.inr ⟨hx0, by omega, by omega⟩)⟩ + · exact Or.inr ⟨hcanon, Or.inr (Or.inl (by omega))⟩ + · exact Or.inr ⟨hcanon, Or.inl (by omega)⟩ /-- The accepted and rejected guard domains are disjoint. -/ theorem mulExpRay_value_not_panic {y x : Nat} : MulExpRayValueDomain y x → ¬ MulExpRayPanicDomain y x := by intro hv hp - rcases hv with ⟨_, hy0 | ⟨hscale, hxhi, hxlo | hx0 | hk⟩⟩ - · exact hp.2.1 hy0 - · rcases hp with ⟨_, _, hpguard⟩ - rcases hpguard with hbadScale | hbadHi | ⟨_, hbadLo, _⟩ - · omega - · omega - · omega - · rcases hp with ⟨_, _, hpguard⟩ - rcases hpguard with hbadScale | hbadHi | ⟨hxne, _, _⟩ - · omega - · omega + obtain ⟨_, hscale, hxhi, hlive⟩ := hv + obtain ⟨_, hbadScale | hbadHi | ⟨hxne, hbadLo, hbadShift⟩⟩ := hp + · omega + · omega + · rcases hlive with hx0 | hxlo | hshift · exact hxne hx0 - · rcases hp with ⟨_, _, hpguard⟩ - rcases hpguard with hbadScale | hbadHi | ⟨_, _, hbadK⟩ - · omega · omega · omega diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index a3358ad9a..9ac706516 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -6,11 +6,11 @@ import FormalYul.Preservation /-! # Per-function "direct" reductions for the trivial solc ABI/cleanup helpers -These functions (`cleanup_*`, `identity`, `convert_*`, the constant accessor, `zero_value_*`) are -the solc-emitted plumbing called from `fun_expRayToWad`'s overflow guard and panic-code path. -Each is a one-liner; the directs step the interpreter through them. They are branch-agnostic — -the value path also evaluates the guard (to decide *not* to revert) — so they live here, shared by -both `Seam/Revert.lean` and the value-path seam. +These functions (`cleanup_*`, `identity`, `convert_*`, the constant accessors, `zero_value_*`) +are the solc-emitted plumbing called from the guards and panic-code paths of `fun_expRayToWad` +and `fun_mulExpRay`. Each is a one-liner; the directs step the interpreter through them. They are +branch-agnostic — the value paths also evaluate the guards (to decide *not* to revert) — so they +live here, shared by `Seam/Revert.lean` and the value-path seams. -/ namespace ExpYul @@ -289,7 +289,7 @@ theorem call_constant__EXP_RAY_TO_WAD_HI_direct rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__EXP_RAY_TO_WAD_HI] - simp only [yulFunction_constant__EXP_RAY_TO_WAD_HI, yulFunction_constant__EXP_RAY_TO_WAD_HI_132, + simp only [yulFunctionBody_constant__EXP_RAY_TO_WAD_HI, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -460,7 +460,7 @@ theorem call_constant__SCALE_MAX_direct rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX] - simp only [yulFunction_constant__SCALE_MAX, yulFunction_constant__SCALE_MAX_126, + simp only [yulFunctionBody_constant__SCALE_MAX, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -492,7 +492,7 @@ theorem call_constant__WAD_ZERO_MAX_direct rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__WAD_ZERO_MAX] - simp only [yulFunction_constant__WAD_ZERO_MAX, yulFunction_constant__WAD_ZERO_MAX_136, + simp only [yulFunctionBody_constant__WAD_ZERO_MAX, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -638,7 +638,7 @@ theorem call_fun__octave_direct rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__octave] - simp only [yulFunction_fun__octave, yulFunction_fun__octave_310, + simp only [yulFunctionBody_fun__octave, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -745,7 +745,7 @@ theorem call_constant_ARITHMETIC_OVERFLOW_direct rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant_ARITHMETIC_OVERFLOW] - simp only [yulFunction_constant_ARITHMETIC_OVERFLOW, yulFunction_constant_ARITHMETIC_OVERFLOW_62, + simp only [yulFunctionBody_constant_ARITHMETIC_OVERFLOW, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -888,19 +888,19 @@ theorem call_cleanup_t_rational_129_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_cleanup_t_rational_X_HI_direct +theorem call_cleanup_t_rational_MUL_EXP_RAY_HI_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] - (.some "cleanup_t_rational_86296823979713191022445399122_by_1") + (.some "cleanup_t_rational_86989971160273136331862631244_by_1") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_cleanup_t_rational_86296823979713191022445399122_by_1] - simp only [yulFunction_cleanup_t_rational_86296823979713191022445399122_by_1, + lookup_cleanup_t_rational_86989971160273136331862631244_by_1] + simp only [yulFunction_cleanup_t_rational_86989971160273136331862631244_by_1, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -910,7 +910,7 @@ theorem call_cleanup_t_rational_X_HI_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_cleanup_t_rational_X_LO_ZERO_direct +theorem call_cleanup_t_rational_MUL_EXP_RAY_ZERO_MAX_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : @@ -1052,41 +1052,41 @@ theorem call_convert_129_to_uint256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_convert_X_HI_to_int256_direct +theorem call_convert_MUL_EXP_RAY_HI_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word xHiMulExpRay] - (.some "convert_t_rational_86296823979713191022445399122_by_1_to_t_int256") + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word mulExpRayHi] + (.some "convert_t_rational_86989971160273136331862631244_by_1_to_t_int256") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xHiMulExpRay]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayHi]) := by rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_convert_t_rational_86296823979713191022445399122_by_1_to_t_int256] - simp only [yulFunction_convert_t_rational_86296823979713191022445399122_by_1_to_t_int256, + lookup_convert_t_rational_86989971160273136331862631244_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_86989971160273136331862631244_by_1_to_t_int256, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h1 := - call_cleanup_t_rational_X_HI_direct (v := xHiMulExpRay) (fuel := fuel + extra) (extra := 92) + call_cleanup_t_rational_MUL_EXP_RAY_HI_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 92) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word xHiMulExpRay) + (store := Finmap.insert "value" (FormalYul.word mulExpRayHi) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h2 := - call_identity_direct (v := xHiMulExpRay) (fuel := fuel + extra) (extra := 94) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word xHiMulExpRay) + call_identity_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word mulExpRayHi) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h3 := - call_cleanup_t_int256_direct (v := xHiMulExpRay) (fuel := fuel + extra) (extra := 96) + call_cleanup_t_int256_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 96) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word xHiMulExpRay) + (store := Finmap.insert "value" (FormalYul.word mulExpRayHi) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) - simp [FormalYul.word, xHiMulExpRay] at h1 h2 h3 + simp [FormalYul.word, mulExpRayHi] at h1 h2 h3 simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -1094,16 +1094,16 @@ theorem call_convert_X_HI_to_int256_direct EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, xHiMulExpRay, h1, h2, h3] + Finmap.lookup_insert, FormalYul.word, mulExpRayHi, h1, h2, h3] -theorem call_convert_X_LO_ZERO_to_int256_direct +theorem call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word xLoZeroMulExpRay] + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word mulExpRayZeroMax] (.some "convert_t_rational_minus_88376265521393026950697095485_by_1_to_t_int256") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xLoZeroMulExpRay]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayZeroMax]) := by rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, @@ -1114,24 +1114,24 @@ theorem call_convert_X_LO_ZERO_to_int256_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h1 := - call_cleanup_t_rational_X_LO_ZERO_direct (v := xLoZeroMulExpRay) (fuel := fuel + extra) + call_cleanup_t_rational_MUL_EXP_RAY_ZERO_MAX_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 92) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word xLoZeroMulExpRay) + (store := Finmap.insert "value" (FormalYul.word mulExpRayZeroMax) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h2 := - call_identity_direct (v := xLoZeroMulExpRay) (fuel := fuel + extra) (extra := 94) + call_identity_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 94) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word xLoZeroMulExpRay) + (store := Finmap.insert "value" (FormalYul.word mulExpRayZeroMax) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h3 := - call_cleanup_t_int256_direct (v := xLoZeroMulExpRay) (fuel := fuel + extra) (extra := 96) + call_cleanup_t_int256_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 96) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word xLoZeroMulExpRay) + (store := Finmap.insert "value" (FormalYul.word mulExpRayZeroMax) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) - simp [FormalYul.word, xLoZeroMulExpRay] at h1 h2 h3 + simp [FormalYul.word, mulExpRayZeroMax] at h1 h2 h3 simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -1139,79 +1139,79 @@ theorem call_convert_X_LO_ZERO_to_int256_direct EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, xLoZeroMulExpRay, h1, h2, h3] + Finmap.lookup_insert, FormalYul.word, mulExpRayZeroMax, h1, h2, h3] -theorem call_constant__X_HI_direct +theorem call_constant__MUL_EXP_RAY_HI_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant__X_HI_139") + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__MUL_EXP_RAY_HI) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xHiMulExpRay]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayHi]) := by rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__X_HI_139] - simp only [yulFunction_constant__X_HI_139, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__MUL_EXP_RAY_HI] + simp only [yulFunctionBody_constant__MUL_EXP_RAY_HI, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hconv := - call_convert_X_HI_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) + call_convert_MUL_EXP_RAY_HI_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) (shared := shared) - (store := Finmap.insert "expr_138" (FormalYul.word xHiMulExpRay) + (store := Finmap.insert "expr_138" (FormalYul.word mulExpRayHi) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) - simp [FormalYul.word, xHiMulExpRay] at hconv + simp [FormalYul.word, mulExpRayHi] at hconv simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, xHiMulExpRay, hconv] + Finmap.lookup_insert, FormalYul.word, mulExpRayHi, hconv] -theorem call_constant__X_LO_ZERO_direct +theorem call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant__X_LO_ZERO_143") + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__MUL_EXP_RAY_ZERO_MAX) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word xLoZeroMulExpRay]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayZeroMax]) := by rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__X_LO_ZERO_143] - simp only [yulFunction_constant__X_LO_ZERO_143, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__MUL_EXP_RAY_ZERO_MAX] + simp only [yulFunctionBody_constant__MUL_EXP_RAY_ZERO_MAX, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hconv := - call_convert_X_LO_ZERO_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) + call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) (shared := shared) - (store := Finmap.insert "expr_142" (FormalYul.word xLoZeroMulExpRay) + (store := Finmap.insert "expr_142" (FormalYul.word mulExpRayZeroMax) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) - simp [FormalYul.word, xLoZeroMulExpRay] at hconv + simp [FormalYul.word, mulExpRayZeroMax] at hconv simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, xLoZeroMulExpRay, hconv] + Finmap.lookup_insert, FormalYul.word, mulExpRayZeroMax, hconv] theorem call_constant__SCALE_MAX_CLZ_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some "constant__SCALE_MAX_CLZ_129") + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__SCALE_MAX_CLZ) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word scaleMaxClz]) := by rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX_CLZ_129] - simp only [yulFunction_constant__SCALE_MAX_CLZ_129, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX_CLZ] + simp only [yulFunctionBody_constant__SCALE_MAX_CLZ, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1276,7 +1276,7 @@ theorem call_fun_clz_direct rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_clz] - simp only [yulFunction_fun_clz, yulFunction_fun_clz_96, + simp only [yulFunctionBody_fun_clz, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1382,7 +1382,7 @@ theorem call_fun_or_direct rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_or] - simp only [yulFunction_fun_or, yulFunction_fun_or_12, + simp only [yulFunctionBody_fun_or, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1409,7 +1409,7 @@ theorem call_fun_and_direct rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_and] - simp only [yulFunction_fun_and, yulFunction_fun_and_23, + simp only [yulFunctionBody_fun_and, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 4d1b68232..642c140b0 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -2,13 +2,16 @@ import ExpProof.ExpYulProof import Common.Word import ExpProof.Seam.Helpers import ExpProof.Seam.Dispatcher +import ExpProof.Seam.Value import FormalYul.Preservation /-! # Value-path reductions for `mulExpRay` -This file discharges the concrete zero-magnitude path, which returns before the dynamic scale, -octave, range guard, and kernel. +Every multiplier takes the same straight-line path: headroom, octave, closing shift, the guard +word, the shared kernel, and the closing `sgn(y)` multiply. One reduction covers all inputs whose +guard word is zero; a zero multiplier needs no separate path because `sgn(0) = 0` collapses the +kernel output at the tree level. -/ namespace ExpYul @@ -19,36 +22,198 @@ open Common.Word set_option maxRecDepth 100000 -set_option maxHeartbeats 4000000 in -/-- `fun_mulExpRay(0, x)` returns `0` before evaluating scale, octave, range, or kernel code. -/ -theorem call_fun_mulExpRay_zero_direct - (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) +set_option maxHeartbeats 12000000 in +/-- `fun_mulExpRay(y, x)` on the value path returns the signed dynamic-scale tree. -/ +theorem call_fun_mulExpRay_direct + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 500)) [FormalYul.word 0, FormalYul.word x] + some (FormalYul.accountFor yulContract)) + (hguard : mulExpGuardTree y x = 0) : + EvmYul.Yul.call (fuel + (extra + 2200)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by - rw [show fuel + (extra + 500) = (fuel + extra) + 500 by omega] + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (mulExpTree y x)]) := by + rw [show fuel + (extra + 2200) = (fuel + extra) + 2200 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_mulExpRay] - simp only [yulFunction_fun_mulExpRay, yulFunction_fun_mulExpRay_301, + simp only [yulFunctionBody_fun_mulExpRay, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + let sign := signTree y + let ay := absTree y + let s0 := evmSub (evmClz ay) scaleMaxClz + let s := evmSub s0 (evmGt (evmShl s0 ay) scaleQ67) + let k := kTree x + let shift := evmSub s k + let scale := evmShl s ay have hzeroInit := - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 476) + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2176) + (shared := shared) (hlookup := hlookup) + have hzeroUint1 := + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2173) + (shared := shared) (hlookup := hlookup) + have hzeroUint2 := + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2170) + (shared := shared) (hlookup := hlookup) + have hclz := + call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) + (shared := shared) (hlookup := hlookup) + have hscaleMaxClz := + call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 2023) + (shared := shared) (hlookup := hlookup) + have hwrapS0 := + call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) + (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) + have hscaleMax1 := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2020) + (shared := shared) (hlookup := hlookup) + have hoctave := + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2055) + (shared := shared) (hlookup := hlookup) + have hconvertS := + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2051) + (shared := shared) (hlookup := hlookup) + have hwrapShift := + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2088) + (shared := shared) (hlookup := hlookup) + have hscaleMax2 := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2004) + (shared := shared) (hlookup := hlookup) + have hcleanupScaleMax := + call_cleanup_t_uint256_direct (v := scaleQ67) (fuel := fuel + extra) (extra := 2141) + (shared := shared) (hlookup := hlookup) + have hcleanupAyGuard := + call_cleanup_t_uint256_direct (v := ay) (fuel := fuel + extra) (extra := 2139) + (shared := shared) (hlookup := hlookup) + have hHi := + call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 1998) (shared := shared) (hlookup := hlookup) - have hcleanupY := - call_cleanup_t_int256_direct (v := 0) (fuel := fuel + extra) (extra := 467) + have hcleanupHi := + call_cleanup_t_int256_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 2133) (shared := shared) (hlookup := hlookup) - have hconvertCmp := - call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 369) + have hcleanupXForHi := + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2131) (shared := shared) (hlookup := hlookup) - have hconvertRet := - call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 367) + have hOrOut := + call_fun_or_direct (a := evmGt ay scaleQ67) (b := evmIszero (evmSlt x mulExpRayHi)) + (fuel := fuel + extra) (extra := 2076) (shared := shared) (hlookup := hlookup) + have hconvertZeroEq := + call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 2027) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hcleanupY hconvertCmp hconvertRet + have hcleanupXEq := + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2125) + (shared := shared) (hlookup := hlookup) + have hZM1 := + call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1986) + (shared := shared) (hlookup := hlookup) + have hcleanupZM := + call_cleanup_t_int256_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 2123) + (shared := shared) (hlookup := hlookup) + have hcleanupXForLo := + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2121) + (shared := shared) (hlookup := hlookup) + have hAndLo := + call_fun_and_direct (a := evmIszero (evmEq x 0)) (b := evmSgt x mulExpRayZeroMax) + (fuel := fuel + extra) (extra := 2064) (shared := shared) (hlookup := hlookup) + have hconvertTwo := + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2017) + (shared := shared) (hlookup := hlookup) + have hcleanupShift := + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2115) + (shared := shared) (hlookup := hlookup) + have hAndAccuracy := + call_fun_and_direct + (a := evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) + (b := evmSlt shift 2) (fuel := fuel + extra) (extra := 2058) + (shared := shared) (hlookup := hlookup) + have hOrGuard := + call_fun_or_direct + (a := evmOr (evmGt ay scaleQ67) (evmIszero (evmSlt x mulExpRayHi))) + (b := evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) + (evmSlt shift 2)) + (fuel := fuel + extra) (extra := 2057) (shared := shared) (hlookup := hlookup) + have hscaleShift := + call_shift_left_t_uint256_t_uint256_direct (value := ay) (bits := s) + (fuel := fuel + extra) (extra := 1947) (shared := shared) (hlookup := hlookup) + have hconvertShiftOut := + call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2004) + (shared := shared) (hlookup := hlookup) + have hZM2 := + call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1963) + (shared := shared) (hlookup := hlookup) + have hkernel := + call_fun__expRayKernel_direct (x := x) (k := k) (scale := scale) (shift := shift) + (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1422) + (shared := shared) (hlookup := hlookup) + have hconvertOut := + call_convert_uint256_to_int256_direct (v := mulExpTree y x) (fuel := fuel + extra) + (extra := 1997) (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS0 + simp only [Nat.reduceAdd, FormalYul.word] at hscaleMax1 hscaleMax2 + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave + simp only [Nat.reduceAdd, FormalYul.word, s, s0, ay, absTree, signTree, scaleMaxClz, + scaleQ67] at hconvertS + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, s0, ay, absTree, signTree, scaleMaxClz, + scaleQ67] at hwrapShift + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, + scaleQ67] at hcleanupScaleMax hcleanupAyGuard + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, + mulExpRayHi] at hHi + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hcleanupHi + simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, ay, absTree, signTree, scaleQ67, + mulExpRayHi] at hOrOut + simp only [Nat.reduceAdd, FormalYul.word] at hconvertZeroEq hcleanupXEq + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, + mulExpRayZeroMax] at hZM1 hZM2 + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayZeroMax] at hcleanupZM + simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForLo + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, + mulExpRayZeroMax] at hAndLo + simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo + simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, s0, ay, absTree, signTree, + scaleMaxClz, scaleQ67] at hcleanupShift + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, k, kTree, shift, s, s0, ay, absTree, + signTree, scaleMaxClz, scaleQ67, mulExpRayZeroMax] at hAndAccuracy + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, s0, ay, absTree, + signTree, scaleMaxClz, scaleQ67, mulExpRayHi, mulExpRayZeroMax] at hOrGuard + simp only [Nat.reduceAdd, FormalYul.word, s, s0, ay, absTree, signTree, scaleMaxClz, + scaleQ67] at hscaleShift + simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, s0, ay, absTree, signTree, + scaleMaxClz, scaleQ67] at hconvertShiftOut + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, scale, shift, s, s0, ay, absTree, + signTree, scaleMaxClz, scaleQ67, mulExpRayZeroMax, evmShl_one_c0] at hkernel + simp only [Nat.reduceAdd, FormalYul.word, + mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, + tTree, vTree, evTree, odTree, todTree, kTree, scaleShiftTree, absTree, signTree, + tArgShift, k27Q235, ln2Q235, squareShift, + ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, + od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, + todShift, marginWord, scaleQ67, scaleMaxClz, mulExpRayZeroMax] at hconvertOut + have hguardUnfold : + evmOr + (evmOr + (evmGt (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)) + 147573952589676412928000000000000000000) + (evmIszero (evmSlt x 86989971160273136331862631244))) + (evmAnd + (evmAnd (evmIszero (evmEq x 0)) + (evmSgt x 115792089237316195423570985008687907853269984665552187773936190980962432544451)) + (evmSlt + (evmSub + (evmSub (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) + (evmGt + (evmShl (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) + (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) + 147573952589676412928000000000000000000)) + (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) + 2)) = 0 := by + simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, scaleQ67, + scaleMaxClz, mulExpRayHi, mulExpRayZeroMax] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -57,31 +222,58 @@ theorem call_fun_mulExpRay_zero_direct EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, - FormalYul.Preservation.call_on_checkpoint, Finmap.lookup_insert, FormalYul.word, - hzeroInit, hcleanupY, hconvertCmp, hconvertRet] + hguard, hguardUnfold, + hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS0, + hscaleMax1, hoctave, hconvertS, hwrapShift, hscaleMax2, hcleanupScaleMax, hcleanupAyGuard, + hHi, hcleanupHi, hcleanupXForHi, hOrOut, hconvertZeroEq, hcleanupXEq, hZM1, hcleanupZM, + hcleanupXForLo, hAndLo, hconvertTwo, hcleanupShift, hAndAccuracy, hOrGuard, hscaleShift, + hconvertShiftOut, hZM2, hkernel, hconvertOut, + FormalYul.Preservation.uint256_ofNat_eq_eq_word_evmEq, + FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, + FormalYul.Preservation.uint256_ofNat_lt_eq_word_evmLt, + FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, + FormalYul.Preservation.uint256_ofNat_mul_eq_word_evmMul, + FormalYul.Preservation.uint256_ofNat_or_eq_word_evmOr, + FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl, + Common.Word.uint256_ofNat_xor_eq_word_evmXor, + Common.Word.uint256_ofNat_sar_eq_word_evmSar, + uint256_ofNat_slt_eq_word_evmSlt, + uint256_ofNat_sgt_eq_word_evmSgt, + uint256_ofNat_iszero_eq_word_evmIszero, + evmShl_one_c0, + mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, + tTree, vTree, evTree, odTree, todTree, + tArgShift, k27Q235, ln2Q235, squareShift, + ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, + od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, + todShift, marginWord, + mulExpGuardTree, scaleShiftTree, absTree, signTree, kTree, + scaleQ67, scaleMaxClz, mulExpRayHi, mulExpRayZeroMax, + sign, ay, s0, s, k, scale, shift] -set_option maxHeartbeats 4000000 in -/-- `fun_wrap_mulExpRay(0, x)` forwards to `fun_mulExpRay`, giving `0`. -/ -theorem call_fun_wrap_mulExpRay_zero_direct - (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) +set_option maxHeartbeats 12000000 in +/-- `fun_wrap_mulExpRay(y, x)` forwards to the value path. -/ +theorem call_fun_wrap_mulExpRay_direct + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word 0, FormalYul.word x] + some (FormalYul.accountFor yulContract)) + (hguard : mulExpGuardTree y x = 0) : + EvmYul.Yul.call (fuel + (extra + 2300)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by - rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (mulExpTree y x)]) := by + rw [show fuel + (extra + 2300) = (fuel + extra) + 2300 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_mulExpRay] - simp only [yulFunction_fun_wrap_mulExpRay, yulFunction_fun_wrap_mulExpRay_363, + simp only [yulFunctionBody_fun_wrap_mulExpRay, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hinner := - call_fun_mulExpRay_zero_direct (x := x) (fuel := fuel + extra) (extra := 589) - (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hinner + call_fun_mulExpRay_direct (y := y) (x := x) (fuel := fuel + extra) (extra := 89) + (shared := shared) (hlookup := hlookup) (hguard := hguard) + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_mulExpRay] at hinner simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, @@ -90,71 +282,72 @@ theorem call_fun_wrap_mulExpRay_zero_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 1076) + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2276) (shared := shared) (hlookup := hlookup), hinner] set_option maxHeartbeats 12000000 in -/-- The external `mulExpRay` entrypoint at `y = 0` ABI-encodes and returns `0`. -/ -theorem external_fun_wrap_mulExpRay_zero_calldata_result - (x : Nat) (store : EvmYul.Yul.VarStore) : +/-- The external `mulExpRay` entrypoint ABI-encodes and returns the value tree. -/ +theorem external_fun_wrap_mulExpRay_calldata_result + (y x : Nat) (store : EvmYul.Yul.VarStore) + (hguard : mulExpGuardTree y x = 0) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) - (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) store) + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) store) with | .error (.YulHalt state _) => FormalYul.resultWord (FormalYul.returnOf state) | .error .Revert => .error "revert" | .error err => .error (reprStr err) | .ok (state, _) => FormalYul.resultWord (FormalYul.returnOf state)) : Except String Nat) = - .ok 0 := by + .ok (mulExpTree y x) := by rw [EvmYul.Yul.call.eq_def] simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_mulExpRay] - simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_363, + simp only [yulFunctionBody_external_fun_wrap_mulExpRay, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] let baseStore := - Finmap.insert "ret_0" (FormalYul.word 0) - (Finmap.insert "param_0" (FormalYul.word 0) + Finmap.insert "ret_0" (FormalYul.word (mulExpTree y x)) + (Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) let memPos := - ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) baseStore).toMachineState.mload (FormalYul.word 64)).1 let memShared := - { mulExpSharedAfterFreePtr 0 x with + { mulExpSharedAfterFreePtr y x with toMachineState := - ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) baseStore).toMachineState.mload (FormalYul.word 64)).2 } let encStore := Finmap.insert "memPos" memPos baseStore have hdecode := - call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := 0) (x := x) + call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := y) (x := x) (fuel := 0) (extra := 999464) - (shared := mulExpSharedAfterFreePtr 0 x) + (shared := mulExpSharedAfterFreePtr y x) (store := (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) - (hdata := mulExpSharedAfterFreePtr_calldata 0 x) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) + (hdata := mulExpSharedAfterFreePtr_calldata y x) simp only [Nat.reduceAdd, FormalYul.word] at hdecode have hwrap := - call_fun_wrap_mulExpRay_zero_direct (x := x) (fuel := 0) (extra := 998883) - (shared := mulExpSharedAfterFreePtr 0 x) - (store := Finmap.insert "param_0" (FormalYul.word 0) + call_fun_wrap_mulExpRay_direct (y := y) (x := x) (fuel := 0) (extra := 997683) + (shared := mulExpSharedAfterFreePtr y x) + (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) - simp only [Nat.reduceAdd, FormalYul.word] at hwrap + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hguard := hguard) + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap have halloc := - call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr 0 x) - (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr y x) + (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup y x) simp only [FormalYul.word, baseStore] at halloc have hencode := call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct - (headStart := memPos) (v := 0) (fuel := 999831) + (headStart := memPos) (v := mulExpTree y x) (fuel := 999831) (shared := memShared) (store := encStore) - (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup 0 x]) + (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup y x]) simp [FormalYul.word, memShared, encStore, memPos, baseStore] at hencode simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, @@ -171,72 +364,78 @@ theorem external_fun_wrap_mulExpRay_zero_calldata_result Finmap.lookup_insert, Finmap.lookup_insert_of_ne, hdecode, hwrap, halloc, hencode] have hmload : - ((mulExpSharedAfterFreePtr 0 x).mload (EvmYul.UInt256.ofNat 64)).1 = + ((mulExpSharedAfterFreePtr y x).mload (EvmYul.UInt256.ofNat 64)).1 = EvmYul.UInt256.ofNat 128 := by - simpa [FormalYul.word] using mulExpSharedAfterFreePtr_mload64 0 x + simpa [FormalYul.word] using mulExpSharedAfterFreePtr_mload64 y x rw [hmload] have hretLen : EvmYul.UInt256.ofNat 128 + EvmYul.UInt256.ofNat 32 - EvmYul.UInt256.ofNat 128 = FormalYul.word 32 := by decide rw [hretLen] rw [FormalYul.Preservation.resultWord_evmReturn_mstore_word] - rfl + have hnat : + (EvmYul.UInt256.ofNat (mulExpTree y x)).toNat = mulExpTree y x := by + change FormalYul.wordNat (EvmYul.UInt256.ofNat (mulExpTree y x)) = mulExpTree y x + exact (FormalYul.Preservation.wordNat_ofNat (mulExpTree y x)).trans + (FormalYul.Preservation.u256_eq_of_lt _ (mulExpTree_lt y x)) + rw [hnat] set_option maxHeartbeats 12000000 in -/-- The external `mulExpRay` entrypoint at `y = 0` halts (returns). -/ -theorem external_fun_wrap_mulExpRay_zero_calldata_halts - (x : Nat) (store : EvmYul.Yul.VarStore) : +/-- The external `mulExpRay` entrypoint on the value path halts (returns). -/ +theorem external_fun_wrap_mulExpRay_calldata_halts + (y x : Nat) (store : EvmYul.Yul.VarStore) + (hguard : mulExpGuardTree y x = 0) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) - (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) store) = + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) store) = .error (.YulHalt state value) := by rw [EvmYul.Yul.call.eq_def] simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_mulExpRay] - simp only [yulFunction_external_fun_wrap_mulExpRay, yulFunction_external_fun_wrap_mulExpRay_363, + simp only [yulFunctionBody_external_fun_wrap_mulExpRay, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] let baseStore := - Finmap.insert "ret_0" (FormalYul.word 0) - (Finmap.insert "param_0" (FormalYul.word 0) + Finmap.insert "ret_0" (FormalYul.word (mulExpTree y x)) + (Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) let memPos := - ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) baseStore).toMachineState.mload (FormalYul.word 64)).1 let memShared := - { mulExpSharedAfterFreePtr 0 x with + { mulExpSharedAfterFreePtr y x with toMachineState := - ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) baseStore).toMachineState.mload + ((EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) baseStore).toMachineState.mload (FormalYul.word 64)).2 } let encStore := Finmap.insert "memPos" memPos baseStore have hdecode := - call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := 0) (x := x) + call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := y) (x := x) (fuel := 0) (extra := 999464) - (shared := mulExpSharedAfterFreePtr 0 x) + (shared := mulExpSharedAfterFreePtr y x) (store := (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) - (hdata := mulExpSharedAfterFreePtr_calldata 0 x) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) + (hdata := mulExpSharedAfterFreePtr_calldata y x) simp only [Nat.reduceAdd, FormalYul.word] at hdecode have hwrap := - call_fun_wrap_mulExpRay_zero_direct (x := x) (fuel := 0) (extra := 998883) - (shared := mulExpSharedAfterFreePtr 0 x) - (store := Finmap.insert "param_0" (FormalYul.word 0) + call_fun_wrap_mulExpRay_direct (y := y) (x := x) (fuel := 0) (extra := 997683) + (shared := mulExpSharedAfterFreePtr y x) + (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) - simp only [Nat.reduceAdd, FormalYul.word] at hwrap + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hguard := hguard) + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap have halloc := - call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr 0 x) - (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup 0 x) + call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr y x) + (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup y x) simp only [FormalYul.word, baseStore] at halloc have hencode := call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct - (headStart := memPos) (v := 0) (fuel := 999831) + (headStart := memPos) (v := mulExpTree y x) (fuel := 999831) (shared := memShared) (store := encStore) - (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup 0 x]) + (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup y x]) simp [FormalYul.word, memShared, encStore, memPos, baseStore] at hencode simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, @@ -254,16 +453,19 @@ theorem external_fun_wrap_mulExpRay_zero_calldata_halts hdecode, hwrap, halloc, hencode] set_option maxHeartbeats 12000000 in -/-- Result, starting from the exact state the dispatcher hands the external `mulExpRay` function. -/ -theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_result (x : Nat) : +/-- Result, starting from the exact state the dispatcher hands the external `mulExpRay` +function. -/ +theorem external_fun_wrap_mulExpRay_dispatcher_state_result + (y x : Nat) + (hguard : mulExpGuardTree y x = 0) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok (EvmYul.SharedState.mk (FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState ((FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) (Finmap.insert "selector" (EvmYul.UInt256.shiftRight @@ -271,9 +473,9 @@ theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_result (x : Nat) : (EvmYul.Yul.State.Ok (EvmYul.SharedState.mk (FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState ((FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) @@ -285,29 +487,33 @@ theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_result (x : Nat) : | .error err => .error (reprStr err) | .ok (state, _) => FormalYul.resultWord (FormalYul.returnOf state)) : Except String Nat) = - .ok 0 := by + .ok (mulExpTree y x) := by rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr_raw] - exact external_fun_wrap_mulExpRay_zero_calldata_result x + exact external_fun_wrap_mulExpRay_calldata_result y x (store := Finmap.insert "selector" (EvmYul.UInt256.shiftRight (EvmYul.State.calldataload - (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) + hguard set_option maxHeartbeats 12000000 in -/-- Halt, starting from the exact state the dispatcher hands the external `mulExpRay` function. -/ -theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_halts (x : Nat) : +/-- Halt, starting from the exact state the dispatcher hands the external `mulExpRay` +function. -/ +theorem external_fun_wrap_mulExpRay_dispatcher_state_halts + (y x : Nat) + (hguard : mulExpGuardTree y x = 0) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok (EvmYul.SharedState.mk (FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState ((FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) (Finmap.insert "selector" (EvmYul.UInt256.shiftRight @@ -315,9 +521,9 @@ theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_halts (x : Nat) : (EvmYul.Yul.State.Ok (EvmYul.SharedState.mk (FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).toState + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState ((FormalYul.sharedFor yulContract - (selector_mulExpRay ++ FormalYul.encodeWords [0, x])).mstore + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) @@ -325,27 +531,30 @@ theorem external_fun_wrap_mulExpRay_zero_dispatcher_state_halts (x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore))) = .error (.YulHalt state value) := by rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr_raw] - exact external_fun_wrap_mulExpRay_zero_calldata_halts x + exact external_fun_wrap_mulExpRay_calldata_halts y x (store := Finmap.insert "selector" (EvmYul.UInt256.shiftRight (EvmYul.State.calldataload - (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr 0 x) + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) + hguard set_option maxHeartbeats 12000000 in -/-- **Zero-magnitude exactness.** `mulExpRay(0, x)` returns `0` for every exponent word. -/ -theorem run_mul_exp_ray_evm_zero (x : Nat) : - run_mul_exp_ray_evm 0 x = .ok 0 := by +/-- **Value path.** When the guard word is zero, the compiled runtime returns the signed +dynamic-scale arithmetic tree — for every multiplier, including zero. -/ +theorem run_mul_exp_ray_evm_eq_tree_of_guard (y x : Nat) + (hguard : mulExpGuardTree y x = 0) : + run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := by obtain ⟨haltState, _haltValue, hhalt⟩ := - external_fun_wrap_mulExpRay_zero_dispatcher_state_halts x - have hresult := external_fun_wrap_mulExpRay_zero_dispatcher_state_result x + external_fun_wrap_mulExpRay_dispatcher_state_halts y x hguard + have hresult := external_fun_wrap_mulExpRay_dispatcher_state_result y x hguard rw [hhalt] at hresult have hReturn : FormalYul.Preservation.DispatcherReturn yulContract - (FormalYul.calldata selector_mulExpRay [0, x]) 999998 (FormalYul.returnOf haltState) := by + (FormalYul.calldata selector_mulExpRay [y, x]) 999998 (FormalYul.returnOf haltState) := by apply FormalYul.Preservation.dispatcherReturn_of_exec_halt (hdispatcher := yulContract_dispatcher) refine ⟨haltState, _haltValue, ?_, rfl⟩ @@ -364,13 +573,13 @@ theorem run_mul_exp_ray_evm_zero (x : Nat) : EvmYul.Yul.State.store, Finmap.lookup_insert, FormalYul.word, call_shift_right_224_unsigned_direct] - rw [selectSwitchCase_mulExpRay_sharedFor_mk_raw 0 x] + rw [selectSwitchCase_mulExpRay_sharedFor_mk_raw y x] simp +decide [hhalt, EvmYul.Yul.exec.eq_def, EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.multifill'] unfold run_mul_exp_ray_evm exact FormalYul.Preservation.callWord_ok_of_dispatcherReturn_result_1000000 - (contract := yulContract) (selector := selector_mulExpRay) (args := [0, x]) + (contract := yulContract) (selector := selector_mulExpRay) (args := [y, x]) (hReturn := hReturn) (by simpa using hresult) end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean index 60b3a4985..37b7c1775 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean @@ -44,7 +44,7 @@ theorem call_fun_panic_revert_direct rw [show fuel + (extra + 600) = (fuel + extra) + 600 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_panic] - simp only [yulFunction_fun_panic, yulFunction_fun_panic_53, + simp only [yulFunctionBody_fun_panic, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -72,7 +72,7 @@ theorem call_fun_expRayToWad_revert_direct rw [show fuel + (extra + 1000) = (fuel + extra) + 1000 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad] - simp only [yulFunction_fun_expRayToWad, yulFunction_fun_expRayToWad_190, + simp only [yulFunctionBody_fun_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -122,7 +122,7 @@ theorem call_fun_wrap_expRayToWad_revert_direct rw [show fuel + (extra + 1200) = (fuel + extra) + 1200 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -155,7 +155,7 @@ theorem external_fun_wrap_expRayToWad_calldata_revert rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_external_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Seam/Value.lean b/formal/exp/ExpProof/ExpProof/Seam/Value.lean index d8d190e19..266cf9875 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Value.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Value.lean @@ -47,7 +47,7 @@ theorem call_fun__expRayKernel_zero_direct rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayKernel] - simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_328, + simp only [yulFunctionBody_fun__expRayKernel, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -76,7 +76,7 @@ theorem call_fun_expRayToWad_zero_direct rw [show fuel + (extra + 900) = (fuel + extra) + 900 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad] - simp only [yulFunction_fun_expRayToWad, yulFunction_fun_expRayToWad_190, + simp only [yulFunctionBody_fun_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -143,7 +143,7 @@ theorem call_fun_wrap_expRayToWad_zero_direct rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -181,7 +181,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_result rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_external_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -264,7 +264,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_external_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -477,7 +477,7 @@ theorem call_fun__expRayKernel_direct rw [show fuel + (extra + 700) = (fuel + extra) + 700 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun__expRayKernel] - simp only [yulFunction_fun__expRayKernel, yulFunction_fun__expRayKernel_328, + simp only [yulFunctionBody_fun__expRayKernel, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -541,7 +541,7 @@ theorem call_fun_expRayToWad_direct rw [show fuel + (extra + 900) = (fuel + extra) + 900 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_expRayToWad] - simp only [yulFunction_fun_expRayToWad, yulFunction_fun_expRayToWad_190, + simp only [yulFunctionBody_fun_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -654,7 +654,7 @@ theorem call_fun_wrap_expRayToWad_direct rw [show fuel + (extra + 1100) = (fuel + extra) + 1100 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_expRayToWad] - simp only [yulFunction_fun_wrap_expRayToWad, yulFunction_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -714,7 +714,7 @@ theorem external_fun_wrap_expRayToWad_calldata_result rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_external_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -815,7 +815,7 @@ theorem external_fun_wrap_expRayToWad_calldata_halts rw [EvmYul.Yul.call.eq_def] simp only [expSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, lookup_external_fun_wrap_expRayToWad] - simp only [yulFunction_external_fun_wrap_expRayToWad, yulFunction_external_fun_wrap_expRayToWad_347, + simp only [yulFunctionBody_external_fun_wrap_expRayToWad, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 3fbab2338..a62c576f1 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -96,10 +96,19 @@ example (x1 x2 : Nat) /-! ## `mulExpRay` The public spec for `mulExpRay` is a signed magnitude bracket plus monotonicity predicates in both -arguments. Positive multipliers are nondecreasing in `x`; negative multipliers are nonincreasing in -`x`; for fixed `x`, signed results are nondecreasing in `y`; and joint monotonicity is stated -piecewise over the two sign regions and the sign-crossing case. The runtime facade below reduces -successful-run bracket and monotonicity statements to the compiled arithmetic tree `mulExpTree`. +arguments. Discharged today, axiom-clean: + +* the guard-domain partition of canonical calldata into exact value and panic domains; +* the value path: whenever the guard word is zero, the compiled runtime returns the signed + dynamic-scale arithmetic tree (`run_mul_exp_ray_evm_eq_tree_of_guard`) — one reduction for + every multiplier, including zero, whose result the `sgn(0)` multiply collapses to zero + (`run_mul_exp_ray_evm_zero_of_guard`); +* the real-target monotonicity facts and the bracket/sign-reapplication glue. + +Still open, visible below as explicit hypotheses of the facade lemmas: the guard-word ↔ domain +bridge, the `Panic(17)` revert theorem on the panic domain, and the bracket and monotonicity of +the tree itself (which need the `Floor` certificates generalized from the fixed wad scale to the +dynamic scale). -/ /-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ @@ -159,13 +168,19 @@ example {y1 y2 x1 x2 : Nat} example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := mulExpRayBracket_zero_result x -/-- The compiled runtime returns zero for every exponent when the multiplier is zero. -/ -example (x : Nat) : run_mul_exp_ray_evm 0 x = .ok 0 := - run_mul_exp_ray_evm_zero x +/-- The value path returns the compiled arithmetic tree whenever the guard word is zero. -/ +example (y x : Nat) (hguard : mulExpGuardTree y x = 0) : + run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := + run_mul_exp_ray_evm_eq_tree_of_guard y x hguard -/-- The compiled runtime satisfies the public bracket spec unconditionally at zero magnitude. -/ -example (x : Nat) : MulExpRayRunBracket 0 x := - mulExpRay_run_bracket_zero x +/-- The compiled runtime returns zero for a zero multiplier whenever the guard accepts. -/ +example (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : run_mul_exp_ray_evm 0 x = .ok 0 := + run_mul_exp_ray_evm_zero_of_guard x hguard + +/-- The compiled runtime satisfies the public bracket spec at zero magnitude whenever the guard +accepts. -/ +example (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : MulExpRayRunBracket 0 x := + mulExpRay_run_bracket_zero x hguard /-- The accumulator floor and target bounds imply the public magnitude bracket. -/ example {y x m : Int} {A : Real} @@ -256,9 +271,13 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRayBracket_zero_result -/-- info: 'ExpYul.run_mul_exp_ray_evm_zero' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.run_mul_exp_ray_evm_eq_tree_of_guard' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_eq_tree_of_guard + +/-- info: 'ExpYul.run_mul_exp_ray_evm_zero_of_guard' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms run_mul_exp_ray_evm_zero +#print axioms run_mul_exp_ray_evm_zero_of_guard /-- info: 'ExpYul.mulExpRay_run_bracket_zero' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index 662ba688b..a9794b4b0 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -576,6 +576,9 @@ def aliasFunctionDefName (stable : String) : String := def aliasFunctionNameName (stable : String) : String := "yulName_" ++ sanitizeIdent stable +def aliasFunctionBodyName (stable : String) : String := + "yulFunctionBody_" ++ sanitizeIdent stable + def findFunction (functions : List FunctionSource) (name : String) : Except String FunctionSource := match functions.find? (fun fn => fn.name = name) with | some fn => .ok fn @@ -624,19 +627,29 @@ def aliasByCallPrefix let original ← callWithPrefixFrom functions caller pfx .ok { stable, original } -def renderGeneratedAlias (entry : GeneratedAlias) : String := - "\n/-- Stable generated alias for solc-emitted function `" ++ entry.original ++ "`. -/\n" ++ - "abbrev " ++ aliasFunctionDefName entry.stable ++ - " : EvmYul.Yul.Ast.FunctionDefinition := " ++ functionDefName entry.original ++ "\n\n" ++ - "abbrev " ++ aliasFunctionNameName entry.stable ++ " := " ++ reprStr entry.original ++ "\n\n" ++ - "@[simp]\n" ++ - "theorem lookup_" ++ sanitizeIdent entry.stable ++ " :\n" ++ - " yulFunctions.lookup " ++ aliasFunctionNameName entry.stable ++ - " = some " ++ aliasFunctionDefName entry.stable ++ " := by\n" ++ - " unfold " ++ aliasFunctionNameName entry.stable ++ "\n" ++ - " unfold " ++ aliasFunctionDefName entry.stable ++ "\n" ++ - " unfold yulFunctions\n" ++ - " simp [Finmap.lookup_insert]\n" +def renderGeneratedAlias (functions : List FunctionSource) (entry : GeneratedAlias) : + Except String String := do + let fn ← findFunction functions entry.original + .ok <| + "\n/-- Stable generated alias for solc-emitted function `" ++ entry.original ++ "`. -/\n" ++ + "abbrev " ++ aliasFunctionDefName entry.stable ++ + " : EvmYul.Yul.Ast.FunctionDefinition := " ++ functionDefName entry.original ++ "\n\n" ++ + "abbrev " ++ aliasFunctionNameName entry.stable ++ " := " ++ reprStr entry.original ++ "\n\n" ++ + "@[simp]\n" ++ + "theorem lookup_" ++ sanitizeIdent entry.stable ++ " :\n" ++ + " yulFunctions.lookup " ++ aliasFunctionNameName entry.stable ++ + " = some " ++ aliasFunctionDefName entry.stable ++ " := by\n" ++ + " unfold " ++ aliasFunctionNameName entry.stable ++ "\n" ++ + " unfold " ++ aliasFunctionDefName entry.stable ++ "\n" ++ + " unfold yulFunctions\n" ++ + " simp [Finmap.lookup_insert]\n\n" ++ + "/-- Suffix-free unfolding of `" ++ aliasFunctionDefName entry.stable ++ "` to its Yul\n" ++ + "body, so proofs stepping through it never name the solc-numbered definition. -/\n" ++ + "theorem " ++ aliasFunctionBodyName entry.stable ++ " :\n" ++ + " " ++ aliasFunctionDefName entry.stable ++ " =\n" ++ + " := rfl\n" def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : Except String (List GeneratedAlias) := do @@ -755,7 +768,10 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", aliasByPrefix functions "constant__EXP_RAY_TO_WAD_HI" "constant__EXP_RAY_TO_WAD_HI_", aliasByPrefixExcluding functions "constant__SCALE_MAX" "constant__SCALE_MAX_" "constant__SCALE_MAX_CLZ_", + aliasByPrefix functions "constant__SCALE_MAX_CLZ" "constant__SCALE_MAX_CLZ_", aliasByPrefix functions "constant__WAD_ZERO_MAX" "constant__WAD_ZERO_MAX_", + aliasByPrefix functions "constant__MUL_EXP_RAY_HI" "constant__MUL_EXP_RAY_HI_", + aliasByPrefix functions "constant__MUL_EXP_RAY_ZERO_MAX" "constant__MUL_EXP_RAY_ZERO_MAX_", aliasByPrefix functions "constant_ARITHMETIC_OVERFLOW" "constant_ARITHMETIC_OVERFLOW_", aliasByPrefix functions "fun_panic" "fun_panic_", aliasByPrefix functions "fun_or" "fun_or_", @@ -766,6 +782,7 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : def renderProof (kind : ModelKind) (contract : ParsedContract) (output : String) : Except String String := do let functions := contract.functions let aliases ← generatedAliases kind functions + let renderedAliases ← aliases.mapM (renderGeneratedAlias functions) let runtimeModule := moduleNameFromOutput output ++ "Runtime" .ok <| "import FormalYul.Preservation\n" ++ @@ -778,7 +795,7 @@ def renderProof (kind : ModelKind) (contract : ParsedContract) (output : String) "@[simp]\n" ++ "theorem yulContract_functions : yulContract.functions = yulFunctions := rfl\n" ++ joinLines (functions.map renderLookupLemma) ++ "\n" ++ - joinLines (aliases.map renderGeneratedAlias) ++ "\n" ++ + joinLines renderedAliases ++ "\n" ++ "end " ++ kind.namespaceName ++ "\n" def validateSelectorCase (dispatcherStx : Syntax) (selector : String) : Except String Unit := From 8c217ced3e9d967882cf24f7386928f77d780a0f Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 22:43:15 +0200 Subject: [PATCH 064/107] Document why mulExpRay is monotone in the multiplier A unit step in abs(y) can drop the scale headroom by one bit. At a bit-length boundary the scale does not decrease while the closing shift shrinks, so the result rises. At a headroom-correction boundary the scale halves against a one-bit-coarser output grid, and the naive error envelope admits a one-unit backward slip of the pre-shift numerator; the slip only occurs when the scaled quotient is even, which makes the compared numerator odd, so it cannot cross the (even) closing modulus and the floored result never decreases. The new tests sweep every reachable correction boundary deterministically and fuzz both boundary families, positive and negative. Co-Authored-By: Claude Fable 5 --- src/vendor/Exp.sol | 15 +++++++++++++++ test/0.8.34/Exp.t.sol | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index fa6a0f225..c666aac07 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -122,6 +122,21 @@ library Exp { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } + // Monotonicity in y at a fixed accepted x: within one headroom class (fixed s) the + // magnitude is a composition of nondecreasing maps of ay. A unit step in ay can + // lower s by one in two ways, both order-preserving: + // - at a bit-length boundary (ay reaching 2ᴸ), the scale ay << s does not decrease + // while the closing shift shrinks by one, so both effects raise the result; + // - at a headroom-correction boundary (ay << s crossing _SCALE_MAX), the scale + // halves: scale′ = (scale + 2ˢ)/2. With P = scale⋅n/d, c = 2ˢ⋅n/d > 1 (s ≥ 1 and + // n/d > 1/√2 - ε), b = ⌊P⌋ mod 2, and f = frac(P), the two pre-shift numerators + // compared on the common 2ˢ⁻ᵏ grid satisfy + // (2⋅⌊(P + c)/2⌋ - 2) - (⌊P⌋ - 1) = 2⋅⌊(b + f + c)/2⌋ - b - 1, + // which is ≥ 0 when ⌊P⌋ is odd and ≥ -1 when ⌊P⌋ is even; in the -1 case + // ⌊P⌋ - 1 is odd, so losing one unit cannot cross a multiple of the closing + // modulus 2ˢ⁻ᵏ (even, since the guard keeps k ≤ s - 2), and the floored result + // is unchanged. The x = 0 pin (exact) and the zero clamp (constant) preserve + // order trivially, and the sign reapplication mirrors the argument to y < 0. uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), _MUL_EXP_RAY_ZERO_MAX); // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale // is zero) in one branchless step: diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index 0c97de970..29866172c 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -300,4 +300,42 @@ contract ExpTest is Test { x = bound(x, _X_LO_ZERO + 1, _TOO_BIG - 2); assertGe(Exp.mulExpRay(y, x + 1), Exp.mulExpRay(y, x), "adjacent monotonicity"); } + + /// Monotonicity in y is tightest where a unit step in abs(y) crosses a headroom-correction + /// boundary (abs(y) << s crossing _SCALE_MAX): the scale halves against a one-bit-coarser + /// output grid, and only the parity of the scaled quotient keeps the floor from slipping + /// backward. Sweep every reachable boundary at its deepest accepted octaves. + function testMulExpRayMonotoneYHeadroomBoundaries() external pure { + for (uint256 s0 = 1; s0 <= 126; ++s0) { + int256 q = int256(_SCALE_MAX >> s0); + int256 kmax = int256(s0) - 3; + for (int256 k = kmax; k >= kmax - 2 && k >= -60; --k) { + int256 xb = _octaveStart(k); + for (int256 x = xb; x <= xb + 2; ++x) { + assertLe(Exp.mulExpRay(q, x), Exp.mulExpRay(q + 1, x), "y-monotonicity"); + assertGe(Exp.mulExpRay(-q, x), Exp.mulExpRay(-(q + 1), x), "negative mirror"); + } + } + } + } + + /// Fuzz the headroom-correction boundaries across the full accepted exponent range. + function testFuzzMulExpRayMonotoneYHeadroom(uint256 us, int256 x) external pure { + uint256 s0 = bound(us, 1, 126); + int256 q = int256(_SCALE_MAX >> s0); + // The deepest x accepted by both magnitudes: octave count at most s0 - 3. + x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s0) - 2) - 1); + assertLe(Exp.mulExpRay(q, x), Exp.mulExpRay(q + 1, x), "y-monotonicity across headroom"); + assertGe(Exp.mulExpRay(-q, x), Exp.mulExpRay(-(q + 1), x), "negative mirror"); + } + + /// Adjacent multipliers anywhere in the supported range, with the exponent bounded to the + /// octaves both headrooms accept. + function testFuzzMulExpRayMonotoneYAdjacent(uint256 uy, int256 x) external pure { + int256 y = int256(bound(uy, 1, _SCALE_MAX - 1)); + uint256 s = Clz.clz(uint256(y) + 1) - 129; + if (uint256(y + 1) << s > _SCALE_MAX) --s; + x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s) - 1) - 1); + assertLe(Exp.mulExpRay(y, x), Exp.mulExpRay(y + 1, x), "adjacent y-monotonicity"); + } } From 3b893a11deb30c6941a3d1b7228d0740d264563e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 9 Jul 2026 23:24:19 +0200 Subject: [PATCH 065/107] Prove the mulExpRay runtime surface on its exact domains The guard word is the if-encoding of the exact panic condition (mulExpGuardTree_eq_ite), so canonical calldata splits into the exact value and panic domains and the two run-level theorems follow: accepted inputs return the compiled arithmetic tree (run_mul_exp_ray_evm_eq_tree) and rejected inputs revert (run_mul_exp_ray_evm_revert), the latter by stepping the interpreter through the guard branch into fun_panic(ARITHMETIC_OVERFLOW). Two accepted subdomains carry their public bracket without the polynomial certificates: at the scale point the kernel's rational is exactly one and the run returns the multiplier (run_mul_exp_ray_evm_scale_point, with sign and magnitude word semantics proved through the xor/sar split and the headroom-selection spec), and at or below the zero cutoff the run returns zero while every supported magnitude keeps the real target below one via log 2 < 0.6931471808 (run_mul_exp_ray_evm_clamped, clamped_target_lt_one). The signpost gates each theorem to the standard axioms and records the remaining obligations: the live-region bracket and the runtime monotonicity statements, which need the Floor certificates generalized from the wad scale to the dynamic scale. Co-Authored-By: Claude Fable 5 Co-Authored-By: Codex --- formal/README.md | 2 +- formal/exp/ExpProof/ExpProof/Mul.lean | 11 + formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 101 ++++ formal/exp/ExpProof/ExpProof/Mul/Shell.lean | 554 ++++++++++++++++++ .../exp/ExpProof/ExpProof/Mul/WordBridge.lean | 61 ++ .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 374 ++++++++++++ formal/exp/ExpProof/ExpProof/Theorems.lean | 94 ++- 7 files changed, 1184 insertions(+), 13 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Mul/Shell.lean create mode 100644 formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean create mode 100644 formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean diff --git a/formal/README.md b/formal/README.md index 1ac7d3cd1..58d3a4f4f 100644 --- a/formal/README.md +++ b/formal/README.md @@ -11,7 +11,7 @@ Machine-checked Lean 4 correctness proofs for root math libraries in 0x Settler. | `cbrt/CbrtProof` | `src/vendor/Cbrt.sol` | `_cbrt`, `cbrt`, `cbrtUp` correct on uint256 | | `cbrt/Cbrt512Proof` | `src/utils/512Math.sol` | `_cbrt` (512-bit) correct: `cbrt(x_hi * 2^256 + x_lo) = icbrt(x)` | | `ln/LnProof` | `src/vendor/Ln.sol` | `lnWadToRay`, `lnWad` correct vs. `Real.log`, monotone, with a 1.6986-ulp error bound | -| `exp/ExpProof` | `src/vendor/Exp.sol` | `expRayToWad` correct vs. `Real.exp`: never over, floor-or-one-less, monotone, and the central `lnWadToRay` round trip | +| `exp/ExpProof` | `src/vendor/Exp.sol` | `expRayToWad` correct vs. `Real.exp`: never over, floor-or-one-less, monotone, and the central `lnWadToRay` round trip. `mulExpRay`: exact accept/revert domains, value path to the compiled tree, and the bracket at the scale point and the zero clamp; the live-region bracket and monotonicity still need the certificates generalized to the dynamic scale | ## Method diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index db62713ba..f91004853 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -2,6 +2,7 @@ import ExpProof.Mono.MulTree import ExpProof.ExpYulRuntime import ExpProof.Spec.RealExp import ExpProof.Seam.MulValue +import ExpProof.Seam.MulRevert import ExpProof.Mul.Domain import ExpProof.Mul.Bridge @@ -105,6 +106,16 @@ theorem mulExpRay_run_bracket_zero (x : Nat) (hguard : mulExpGuardTree 0 x = 0) MulExpRayRunBracket 0 x := mulExpRay_run_bracket_zero_of_run (run_mul_exp_ray_evm_zero_of_guard x hguard) +/-- **Value path on the domain.** Accepted inputs return the compiled arithmetic tree. -/ +theorem run_mul_exp_ray_evm_eq_tree {y x : Nat} (h : MulExpRayValueDomain y x) : + run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := + run_mul_exp_ray_evm_eq_tree_of_guard y x ((valueDomain_iff_guard_eq_zero h.1).mp h) + +/-- **Panic revert.** Rejected inputs revert. -/ +theorem run_mul_exp_ray_evm_revert {y x : Nat} (h : MulExpRayPanicDomain y x) : + run_mul_exp_ray_evm y x = .error "revert" := + run_mul_exp_ray_evm_revert_of_guard y x ((panicDomain_iff_guard_eq_one h.1).mp h) + /-- The `y = 10^18` magnitude target is the existing `expRayToWad` target. -/ theorem mulExpRayMagnitudeTarget_wad (x : Int) : mulExpRayMagnitudeTarget (10 ^ 18) x = expRayToWadTarget x := by diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean index 2559b3f91..b278fb562 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -1,4 +1,5 @@ import ExpProof.Mono.MulTree +import ExpProof.Mul.WordBridge /-! # `mulExpRay` value and panic domains @@ -76,4 +77,104 @@ theorem mulExpRay_value_iff_not_panic {y x : Nat} (hcanon : MulExpRayCanonical y · exact hval · exact False.elim (hnot hpanic) + +/-! ## The guard word as a decidable predicate -/ + +/-- The guard word is the `if`-encoding of the exact panic condition. -/ +theorem mulExpGuardTree_eq_ite {y x : Nat} (hx : x < 2 ^ 256) : + mulExpGuardTree y x = + if scaleQ67 < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ + (int256 x ≠ 0 ∧ int256 mulExpRayZeroMax < int256 x ∧ + int256 (mulShiftTree y x) < 2) then 1 else 0 := by + have hux : u256 x = x := u256_of_lt_pow256 hx + have hab : u256 (absTree y) = absTree y := u256_of_lt_pow256 (absTree_lt y) + have hsh : u256 (mulShiftTree y x) = mulShiftTree y x := + u256_of_lt_pow256 (mulShiftTree_lt y x) + have hhi : u256 mulExpRayHi = mulExpRayHi := u256_of_lt_pow256 mulExpRayHi_lt + have hzm : u256 mulExpRayZeroMax = mulExpRayZeroMax := u256_of_lt_pow256 mulExpRayZeroMax_lt + have hq : u256 scaleQ67 = scaleQ67 := u256_of_lt_pow256 (by unfold scaleQ67; norm_num) + have h0 : u256 0 = 0 := u256_of_lt_pow256 (by norm_num) + have h2 : u256 2 = 2 := u256_of_lt_pow256 (by norm_num) + have hint2 : int256 (u256 2) = 2 := by rw [h2]; unfold int256; norm_num + have hxz : (int256 (u256 x) = 0) = (int256 x = 0) := by rw [hux] + unfold mulExpGuardTree + rw [evmSgt_eq_evmSlt_swap, evmSlt_eq_ite x mulExpRayHi, evmSlt_eq_ite mulExpRayZeroMax x, + evmSlt_eq_ite (mulShiftTree y x) 2, evmGt_eq_ite, evmEq_eq_ite] + rw [hux, hab, hhi, hzm, hq, h0, hsh, hint2] + rw [show (if x = (0 : Nat) then (1 : Nat) else 0) = + if int256 x = 0 then (1 : Nat) else 0 from by + rcases (int256_zero_iff_of_canonical hx) with ⟨h1, h2⟩ + split_ifs with ha hb hb + · rfl + · exact absurd (h2 ha) hb + · exact absurd (h1 hb) ha + · rfl] + rw [evmIszero_ite, evmIszero_ite] + rw [show (if int256 x < int256 mulExpRayHi then (0 : Nat) else 1) = + if int256 mulExpRayHi ≤ int256 x then (1 : Nat) else 0 from by + split_ifs <;> omega] + rw [show (if int256 x = 0 then (0 : Nat) else 1) = + if int256 x ≠ 0 then (1 : Nat) else 0 from by + split_ifs <;> simp_all] + rw [evmAnd_ite, evmAnd_ite, evmOr_ite, evmOr_ite] + congr 1 + simp only [eq_iff_iff] + constructor + · rintro ((h | h) | h) + · exact Or.inl h + · exact Or.inr (Or.inl h) + · exact Or.inr (Or.inr ⟨h.1.1, h.1.2, h.2⟩) + · rintro (h | h | h) + · exact Or.inl (Or.inl h) + · exact Or.inl (Or.inr h) + · exact Or.inr ⟨⟨h.1, h.2.1⟩, h.2.2⟩ + +/-- The guard word is zero exactly on the accepted inputs. -/ +theorem mulExpGuardTree_eq_zero_iff {y x : Nat} (hx : x < 2 ^ 256) : + mulExpGuardTree y x = 0 ↔ + absTree y ≤ scaleQ67 ∧ int256 x < int256 mulExpRayHi ∧ + (int256 x = 0 ∨ int256 x ≤ int256 mulExpRayZeroMax ∨ + 2 ≤ int256 (mulShiftTree y x)) := by + rw [mulExpGuardTree_eq_ite hx, ite_one_zero_eq_zero_iff] + constructor + · intro h + push_neg at h + obtain ⟨h1, h2, h3⟩ := h + refine ⟨by omega, by omega, ?_⟩ + by_cases hx0 : int256 x = 0 + · exact Or.inl hx0 + · by_cases hzm : int256 x ≤ int256 mulExpRayZeroMax + · exact Or.inr (Or.inl hzm) + · exact Or.inr (Or.inr (by have := h3 hx0 (by omega); omega)) + · intro ⟨h1, h2, h3⟩ + push_neg + refine ⟨by omega, by omega, ?_⟩ + intro hx0 hzm + rcases h3 with h | h | h + · exact absurd h hx0 + · omega + · omega + +/-- The guard word is one exactly on the rejected inputs. -/ +theorem mulExpGuardTree_eq_one_iff {y x : Nat} (hx : x < 2 ^ 256) : + mulExpGuardTree y x = 1 ↔ + scaleQ67 < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ + (int256 x ≠ 0 ∧ int256 mulExpRayZeroMax < int256 x ∧ + int256 (mulShiftTree y x) < 2) := by + rw [mulExpGuardTree_eq_ite hx, ite_one_zero_eq_one_iff] + +/-- The value domain is exactly the guard word being zero. -/ +theorem valueDomain_iff_guard_eq_zero {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayValueDomain y x ↔ mulExpGuardTree y x = 0 := by + rw [mulExpGuardTree_eq_zero_iff hcanon.2] + unfold MulExpRayValueDomain + exact ⟨fun h => h.2, fun h => ⟨hcanon, h⟩⟩ + +/-- The panic domain is exactly the guard word being one. -/ +theorem panicDomain_iff_guard_eq_one {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayPanicDomain y x ↔ mulExpGuardTree y x = 1 := by + rw [mulExpGuardTree_eq_one_iff hcanon.2] + unfold MulExpRayPanicDomain + exact ⟨fun h => h.2, fun h => ⟨hcanon, h⟩⟩ + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean new file mode 100644 index 000000000..14f1a5ddc --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean @@ -0,0 +1,554 @@ +import ExpProof.Mul +import Mathlib.Data.Nat.Bitwise +import Mathlib.Data.Complex.ExponentialBounds +import Mathlib.Analysis.SpecialFunctions.Log.Basic + +/-! +# `mulExpRay` shell regions: the scale point and the zero clamp + +Two accepted subdomains admit exact results without the polynomial certificates: at `x = 0` the +kernel's rational is exactly one and the pin returns the magnitude unchanged, and at or below the +zero cutoff the clamp returns zero, which stays inside the bracket because every supported +magnitude times `exp(x/10²⁷)` is below one there. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word +open ExpRealSpec + +set_option maxRecDepth 100000 + +/-! ## Word plumbing -/ + +private theorem u256_self {a : Nat} (h : a < 2 ^ 256) : u256 a = a := u256_of_lt_pow256 h + +private theorem evmSub_small {a b : Nat} (hb : b ≤ a) (ha : a < 2 ^ 256) : + evmSub a b = a - b := by + unfold evmSub + rw [u256_self ha, u256_self (lt_of_le_of_lt hb ha)] + unfold u256 WORD_MOD + omega + +private theorem evmAdd_small {a b : Nat} (ha : a < 2 ^ 256) (hb : b < 2 ^ 256) + (h : a + b < 2 ^ 256) : evmAdd a b = a + b := by + unfold evmAdd + rw [u256_self ha, u256_self hb] + unfold u256 WORD_MOD + omega + +private theorem evmMul_small {a b : Nat} (ha : a < 2 ^ 256) (hb : b < 2 ^ 256) + (h : a * b < 2 ^ 256) : evmMul a b = a * b := by + unfold evmMul + rw [u256_self ha, u256_self hb] + unfold u256 WORD_MOD + omega + +private theorem evmShl_small {s v : Nat} (hs : s < 256) (hv : v < 2 ^ 256) + (h : v * 2 ^ s < 2 ^ 256) : evmShl s v = v * 2 ^ s := by + unfold evmShl + rw [u256_self (lt_trans hs (by norm_num)), u256_self hv, if_pos hs] + unfold u256 WORD_MOD + omega + +private theorem evmShr_small {s v : Nat} (hs : s < 256) (hv : v < 2 ^ 256) : + evmShr s v = v / 2 ^ s := by + unfold evmShr + rw [u256_self (lt_trans hs (by norm_num)), u256_self hv, if_pos hs] + +private theorem evmDiv_exact {a b : Nat} (hb : 0 < b) (ha : a < 2 ^ 256) (hbw : b < 2 ^ 256) + (hab : a * b < 2 ^ 256) : evmDiv (evmMul a b) b = a := by + rw [evmMul_small ha hbw hab] + simp only [evmDiv, u256_self hab, u256_self hbw] + rw [if_neg (by omega : ¬ b = 0)] + exact Nat.mul_div_cancel _ hb + +/-- Xor against a low mask complements below the mask. -/ +private theorem xor_all_ones : ∀ (k y : Nat), y < 2 ^ k → y ^^^ (2 ^ k - 1) = 2 ^ k - 1 - y := by + intro k + induction k with + | zero => + intro y hy + have hy0 : y = 0 := by omega + subst hy0 + rfl + | succ n ih => + intro y hy + have hp : (2 : Nat) ^ (n + 1) = 2 * 2 ^ n := by ring + have hpos : (0 : Nat) < 2 ^ n := Nat.two_pow_pos n + have hdiv : (y ^^^ (2 ^ (n + 1) - 1)) / 2 = (y / 2) ^^^ (2 ^ n - 1) := by + have h1 : (y ^^^ (2 ^ (n + 1) - 1)) >>> 1 = (y >>> 1) ^^^ ((2 ^ (n + 1) - 1) >>> 1) := + Nat.shiftRight_xor_distrib + rw [Nat.shiftRight_eq_div_pow, Nat.shiftRight_eq_div_pow, Nat.shiftRight_eq_div_pow] at h1 + rw [show (2 ^ (n + 1) - 1) / 2 ^ 1 = 2 ^ n - 1 by omega] at h1 + simpa using h1 + have hmod : (y ^^^ (2 ^ (n + 1) - 1)) % 2 = (y + (2 ^ (n + 1) - 1)) % 2 := + Nat.xor_mod_two_eq + have hih := ih (y / 2) (by omega) + have hsplit := Nat.div_add_mod (y ^^^ (2 ^ (n + 1) - 1)) 2 + have hysplit := Nat.div_add_mod y 2 + omega + +/-! ## Sign and magnitude semantics of the tree -/ + +theorem signTree_nonneg {y : Nat} (hy : y < 2 ^ 255) : signTree y = 0 := by + unfold signTree evmSar + rw [u256_self (by norm_num : (255 : Nat) < 2 ^ 256), u256_self (lt_trans hy (by norm_num))] + rw [if_neg (by omega), if_neg (by omega)] + exact Nat.div_eq_of_lt (by omega) + +theorem signTree_neg {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : + signTree y = 2 ^ 256 - 1 := by + unfold signTree evmSar + rw [u256_self (by norm_num : (255 : Nat) < 2 ^ 256), u256_self hy] + rw [if_pos (by omega), if_neg (by omega)] + unfold WORD_MOD + rw [Nat.div_eq_of_lt (by omega)] + omega + +theorem absTree_nonneg {y : Nat} (hy : y < 2 ^ 255) : absTree y = y := by + unfold absTree + rw [signTree_nonneg hy] + unfold Common.Word.evmXor + rw [u256_self (lt_trans hy (by norm_num)), u256_self (by norm_num : (0 : Nat) < 2 ^ 256)] + rw [Nat.xor_zero] + exact evmSub_small (by omega) (lt_trans hy (by norm_num)) + +theorem absTree_neg {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : + absTree y = 2 ^ 256 - y := by + unfold absTree + rw [signTree_neg hlo hy] + unfold Common.Word.evmXor + rw [u256_self hy, u256_self (by norm_num : 2 ^ 256 - 1 < 2 ^ 256)] + rw [xor_all_ones 256 y hy] + unfold evmSub + rw [u256_self (by omega : 2 ^ 256 - 1 - y < 2 ^ 256), + u256_self (by norm_num : 2 ^ 256 - 1 < 2 ^ 256)] + unfold u256 WORD_MOD + omega + +/-- The magnitude word is the absolute value of the signed interpretation. -/ +theorem absTree_eq_natAbs {y : Nat} (hy : y < 2 ^ 256) : + absTree y = (int256 y).natAbs := by + by_cases hsign : y < 2 ^ 255 + · rw [absTree_nonneg hsign] + unfold int256 + rw [if_pos hsign] + exact (Int.natAbs_natCast y).symm + · rw [absTree_neg (by omega) hy] + unfold int256 + rw [if_neg hsign] + have hyi : (y : Int) < 2 ^ 256 := by exact_mod_cast hy + have hyl : (2 ^ 255 : Int) ≤ (y : Int) := by exact_mod_cast (by omega : 2 ^ 255 ≤ y) + omega + +theorem sgnTree_pos {y : Nat} (hpos : 0 < y) (hy : y < 2 ^ 255) : sgnTree y = 1 := by + unfold sgnTree + rw [signTree_nonneg hy, absTree_nonneg hy] + unfold evmLt evmOr + rw [u256_self (by norm_num : (0 : Nat) < 2 ^ 256), u256_self (lt_trans hy (by norm_num))] + rw [if_pos hpos] + norm_num [u256, WORD_MOD] + +theorem sgnTree_neg {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : + sgnTree y = 2 ^ 256 - 1 := by + unfold sgnTree + rw [signTree_neg hlo hy] + have hb : evmLt 0 (absTree y) < 2 ^ 256 := by + unfold evmLt + split_ifs <;> norm_num + unfold evmOr + rw [u256_self (by norm_num : 2 ^ 256 - 1 < 2 ^ 256), u256_self hb] + have h1 : (2 ^ 256 - 1 : Nat) ≤ (2 ^ 256 - 1) ||| evmLt 0 (absTree y) := Nat.left_le_or + have h2 : (2 ^ 256 - 1 : Nat) ||| evmLt 0 (absTree y) < 2 ^ 256 := + Nat.or_lt_two_pow (by norm_num) hb + omega + +/-- With a positive multiplier, the result word is the kernel magnitude. -/ +theorem mulExpTree_pos {y x : Nat} (hpos : 0 < y) (hy : y < 2 ^ 255) : + mulExpTree y x = mulMagnitudeTree y x := by + unfold mulExpTree + rw [sgnTree_pos hpos hy] + rw [evmMul_small (mulMagnitudeTree_lt y x) (by norm_num) (by + have := mulMagnitudeTree_lt y x; omega)] + omega + +/-- With a negative multiplier and a positive magnitude, the result word is its negation. -/ +theorem mulExpTree_negative {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) + (hm : 0 < mulMagnitudeTree y x) : + mulExpTree y x = 2 ^ 256 - mulMagnitudeTree y x := by + unfold mulExpTree + rw [sgnTree_neg hlo hy] + have hmlt : mulMagnitudeTree y x < 2 ^ 256 := mulMagnitudeTree_lt y x + unfold evmMul + rw [u256_self hmlt, u256_self (by norm_num : 2 ^ 256 - 1 < 2 ^ 256)] + obtain ⟨k, hk⟩ : ∃ k, mulMagnitudeTree y x = k + 1 := ⟨mulMagnitudeTree y x - 1, by omega⟩ + rw [hk] at hmlt ⊢ + have key : (k + 1) * (2 ^ 256 - 1) = k * 2 ^ 256 + (2 ^ 256 - (k + 1)) := by + have h2 : (0 : Nat) < 2 ^ 256 := by norm_num + omega + rw [key] + unfold u256 WORD_MOD + rw [Nat.add_comm (k * 2 ^ 256), Nat.add_mul_mod_self_right] + exact Nat.mod_eq_of_lt (by omega) + +/-! ## The scale headroom realizes the scale exactly -/ + +theorem mulScaleTree_spec {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : + scaleShiftTree (absTree y) < 256 ∧ + mulScaleTree y = absTree y * 2 ^ scaleShiftTree (absTree y) ∧ + mulScaleTree y ≤ scaleQ67 := by + have haylt : absTree y < 2 ^ 256 := absTree_lt y + rcases Nat.eq_zero_or_pos (absTree y) with h0 | hpos + · have hclz : evmClz 0 = 256 := by + unfold evmClz + rw [u256_self (by norm_num)] + simp + have hs0 : evmSub 256 scaleMaxClz = 127 := by + rw [evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] + unfold scaleMaxClz + norm_num + have hshl : evmShl 127 (0 : Nat) = 0 := by + rw [evmShl_small (by norm_num) (by norm_num) (by norm_num)] + ring + have hgt : evmGt (0 : Nat) scaleQ67 = 0 := by + unfold evmGt + rw [u256_self (by norm_num), u256_self (by unfold scaleQ67; norm_num), if_neg (by omega)] + have hsub : evmSub 127 (0 : Nat) = 127 := evmSub_small (by omega) (by norm_num) + have hsst : scaleShiftTree (absTree y) = 127 := by + unfold scaleShiftTree + simp only [h0, hclz, hs0, hshl, hgt, hsub] + have hscale : mulScaleTree y = 0 := by + unfold mulScaleTree + rw [hsst, h0, hshl] + rw [hsst, hscale, h0] + exact ⟨by norm_num, by ring, by unfold scaleQ67; norm_num⟩ + · have hlog : Nat.log2 (absTree y) ≤ 126 := by + have h1 : 2 ^ Nat.log2 (absTree y) ≤ absTree y := Nat.log2_self_le (by omega) + have hQ : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num + by_contra h + push_neg at h + have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 (absTree y) := + Nat.pow_le_pow_right (by norm_num) h + omega + have hlt : absTree y < 2 ^ (Nat.log2 (absTree y) + 1) := Nat.lt_log2_self + have hclz : evmClz (absTree y) = 255 - Nat.log2 (absTree y) := by + unfold evmClz + rw [u256_self haylt, if_neg (by omega)] + have hs0eq : evmSub (evmClz (absTree y)) scaleMaxClz = 126 - Nat.log2 (absTree y) := by + rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] + unfold scaleMaxClz + omega + have hfit : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) < 2 ^ 127 := by + calc absTree y * 2 ^ (126 - Nat.log2 (absTree y)) + < 2 ^ (Nat.log2 (absTree y) + 1) * 2 ^ (126 - Nat.log2 (absTree y)) := + mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) + _ = 2 ^ (Nat.log2 (absTree y) + 1 + (126 - Nat.log2 (absTree y))) := by + rw [← pow_add] + _ ≤ 2 ^ 127 := Nat.pow_le_pow_right (by norm_num) (by omega) + have hshl : evmShl (126 - Nat.log2 (absTree y)) (absTree y) = + absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := + evmShl_small (by omega) haylt (lt_trans hfit (by norm_num)) + by_cases hover : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) > scaleQ67 + · have hgt : evmGt (absTree y * 2 ^ (126 - Nat.log2 (absTree y))) scaleQ67 = 1 := by + unfold evmGt + rw [u256_self (lt_trans hfit (by norm_num)), + u256_self (by unfold scaleQ67; norm_num), if_pos hover] + have hs0pos : 0 < 126 - Nat.log2 (absTree y) := by + rcases Nat.eq_zero_or_pos (126 - Nat.log2 (absTree y)) with h | h + · rw [h] at hover + simp at hover + omega + · exact h + have hsub : evmSub (126 - Nat.log2 (absTree y)) 1 = 126 - Nat.log2 (absTree y) - 1 := + evmSub_small (by omega) (by omega) + have hsst : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) - 1 := by + unfold scaleShiftTree + simp only [hs0eq, hshl, hgt, hsub] + have hfit' : absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) < 2 ^ 126 := by + calc absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) + < 2 ^ (Nat.log2 (absTree y) + 1) * 2 ^ (126 - Nat.log2 (absTree y) - 1) := + mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) + _ = 2 ^ (Nat.log2 (absTree y) + 1 + (126 - Nat.log2 (absTree y) - 1)) := by + rw [← pow_add] + _ ≤ 2 ^ 126 := Nat.pow_le_pow_right (by norm_num) (by omega) + have hshl' : evmShl (126 - Nat.log2 (absTree y) - 1) (absTree y) = + absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) := + evmShl_small (by omega) haylt + (lt_trans hfit' (by norm_num : (2 : Nat) ^ 126 < 2 ^ 256)) + have hscale : mulScaleTree y = absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) := by + unfold mulScaleTree + rw [hsst, hshl'] + rw [hsst, hscale] + have h126 : (2 : Nat) ^ 126 ≤ scaleQ67 := by unfold scaleQ67; norm_num + exact ⟨by omega, rfl, by omega⟩ + · have hgt : evmGt (absTree y * 2 ^ (126 - Nat.log2 (absTree y))) scaleQ67 = 0 := by + unfold evmGt + rw [u256_self (lt_trans hfit (by norm_num)), + u256_self (by unfold scaleQ67; norm_num), if_neg hover] + have hsub : evmSub (126 - Nat.log2 (absTree y)) 0 = 126 - Nat.log2 (absTree y) := + evmSub_small (by omega) (by omega) + have hsst : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) := by + unfold scaleShiftTree + simp only [hs0eq, hshl, hgt, hsub] + have hscale : mulScaleTree y = absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := by + unfold mulScaleTree + rw [hsst, hshl] + rw [hsst, hscale] + exact ⟨by omega, rfl, by omega⟩ + +/-! ## The scale point `x = 0` -/ + +private theorem kTree_zero : kTree 0 = 0 := by + unfold kTree kRoundShift kHalfShift cInvQ192 + norm_num [evmSar, evmAdd, evmShl, evmMul, u256, WORD_MOD] + +private theorem tTree_zero : tTree 0 = 0 := by + unfold tTree tArgShift k27Q235 ln2Q235 + rw [kTree_zero] + norm_num [evmSar, evmSub, evmMul, u256, WORD_MOD] + +private theorem vTree_zero : vTree 0 = 0 := by + unfold vTree squareShift + rw [tTree_zero] + norm_num [evmShr, evmMul, u256, WORD_MOD] + +private theorem evTree_zero : evTree 0 = ev4 := by + unfold evTree ev0 ev1 ev2 ev3 ev4 evShift1 evShift2 evShift3 evShift4 + rw [vTree_zero] + norm_num [evmAdd, evmShr, evmMul, u256, WORD_MOD] + +private theorem odTree_zero : odTree 0 = od4 := by + unfold odTree od0 od1 od2 od3 od4 odShift1 odShift2 odShift3 odShift4 + rw [vTree_zero] + norm_num [evmAdd, evmShr, evmMul, u256, WORD_MOD] + +private theorem todTree_zero : todTree 0 = 0 := by + unfold todTree todShift + rw [tTree_zero] + norm_num [evmSar, evmMul, u256, WORD_MOD] + +private theorem r0MulTree_scale_point {y : Nat} (hy : y < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) : r0MulTree y 0 = mulScaleTree y := by + obtain ⟨_, _, hcap⟩ := mulScaleTree_spec hy habs + unfold r0MulTree + have hnum : evmAdd (evTree 0) (todTree 0) = ev4 := by + rw [evTree_zero, todTree_zero] + exact evmAdd_small (by unfold ev4; norm_num) (by norm_num) (by unfold ev4; norm_num) + have hden : evmSub (evTree 0) (todTree 0) = ev4 := by + rw [evTree_zero, todTree_zero] + have := evmSub_small (Nat.zero_le ev4) (by unfold ev4; norm_num) + simpa using this + rw [hnum, hden] + exact evmDiv_exact (by unfold ev4; norm_num) (mulScaleTree_lt y) (by unfold ev4; norm_num) + (by + calc mulScaleTree y * ev4 ≤ scaleQ67 * ev4 := Nat.mul_le_mul_right _ hcap + _ < 2 ^ 256 := by unfold scaleQ67 ev4; norm_num) + +private theorem mulShiftTree_scale_point (y : Nat) : + mulShiftTree y 0 = scaleShiftTree (absTree y) := by + unfold mulShiftTree + rw [kTree_zero, evmSub_small (Nat.zero_le _) (scaleShiftTree_lt _)] + omega + +theorem mulMagnitudeTree_scale_point {y : Nat} (hy : y < 2 ^ 256) + (hpos : 0 < absTree y) (habs : absTree y ≤ scaleQ67) : + mulMagnitudeTree y 0 = absTree y := by + obtain ⟨hs256, hscale, hcap⟩ := mulScaleTree_spec hy habs + have hQlt : scaleQ67 < 2 ^ 256 := by unfold scaleQ67; norm_num + have hscalepos : 0 < mulScaleTree y := by + rw [hscale] + exact Nat.mul_pos hpos (Nat.two_pow_pos _) + have hslt : evmSlt mulExpRayZeroMax 0 = 1 := by + rw [evmSlt_eq_ite] + rw [u256_self mulExpRayZeroMax_lt, u256_self (by norm_num)] + rw [if_pos (by + rw [int256_mulExpRayZeroMax] + unfold int256 + norm_num)] + have hisz : evmIszero (0 : Nat) = 1 := by + unfold evmIszero + rw [u256_self (by norm_num)] + simp + unfold mulMagnitudeTree marginWord + rw [hslt, hisz, r0MulTree_scale_point hy habs, mulShiftTree_scale_point y] + have haylt : absTree y < 2 ^ 256 := absTree_lt y + have hsub : evmSub (mulScaleTree y) 1 = + absTree y * 2 ^ scaleShiftTree (absTree y) - 1 := by + rw [hscale] + exact evmSub_small (Nat.mul_pos hpos (Nat.two_pow_pos _)) (by omega) + rw [hsub] + have hshr : evmShr (scaleShiftTree (absTree y)) + (absTree y * 2 ^ scaleShiftTree (absTree y) - 1) = absTree y - 1 := by + rw [evmShr_small hs256 (by omega)] + generalize scaleShiftTree (absTree y) = S + obtain ⟨k, hk⟩ : ∃ k, absTree y = k + 1 := ⟨absTree y - 1, by omega⟩ + rw [hk] + have hexp : (k + 1) * 2 ^ S - 1 = 2 ^ S - 1 + 2 ^ S * k := by + have := Nat.two_pow_pos S + have hd : (k + 1) * 2 ^ S = 2 ^ S * k + 2 ^ S := by ring + omega + rw [hexp, Nat.add_mul_div_left _ _ (Nat.two_pow_pos S), + Nat.div_eq_of_lt (by have := Nat.two_pow_pos S; omega : 2 ^ S - 1 < 2 ^ S)] + omega + rw [hshr] + have hmul : evmMul 1 (absTree y - 1) = absTree y - 1 := by + rw [evmMul_small (by norm_num) (by omega) (by omega)] + omega + rw [hmul] + rw [evmAdd_small (by norm_num) (by omega) (by omega)] + omega + +/-- **Scale point (tree).** At `x = 0`, the result word is the multiplier itself. -/ +theorem mulExpTree_scale_point {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : + mulExpTree y 0 = y := by + rcases Nat.eq_zero_or_pos y with h0 | hypos + · subst h0 + exact mulExpTree_zero 0 + · by_cases hneg : y < 2 ^ 255 + · have hpos : 0 < absTree y := by rw [absTree_nonneg hneg]; omega + rw [mulExpTree_pos hypos hneg, mulMagnitudeTree_scale_point hy hpos habs, + absTree_nonneg hneg] + · have hlo : 2 ^ 255 ≤ y := by omega + have hpos : 0 < absTree y := by rw [absTree_neg hlo hy]; omega + rw [mulExpTree_negative hlo hy (by rw [mulMagnitudeTree_scale_point hy hpos habs]; omega), + mulMagnitudeTree_scale_point hy hpos habs, absTree_neg hlo hy] + omega + +/-! ## The zero clamp -/ + +/-- **Clamp (tree).** At or below the zero cutoff, the result word is zero for every +multiplier: the clamp consults only `x`. -/ +theorem mulExpTree_clamped {y x : Nat} (hx : x < 2 ^ 256) + (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : mulExpTree y x = 0 := by + have hzm := int256_mulExpRayZeroMax + have hx0 : x ≠ 0 := by + intro h + subst h + rw [show int256 (0 : Nat) = 0 from by unfold int256; norm_num, hzm] at hclamp + omega + have hslt : evmSlt mulExpRayZeroMax x = 0 := by + rw [evmSlt_eq_ite, u256_self mulExpRayZeroMax_lt, u256_self hx, if_neg (by omega)] + have hisz : evmIszero x = 0 := by + unfold evmIszero + rw [u256_self hx, if_neg hx0] + unfold mulExpTree mulMagnitudeTree + rw [hslt, hisz] + simp [evmMul, evmAdd, u256, WORD_MOD] + +/-! ## Run-level shell theorems -/ + +private theorem int256_zero_word : int256 (0 : Nat) = 0 := by unfold int256; norm_num + +/-- **Scale point.** `mulExpRay(y, 0)` returns `y` for every supported magnitude. -/ +theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : y < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) : + run_mul_exp_ray_evm y 0 = .ok y := by + have hguard : mulExpGuardTree y 0 = 0 := by + rw [mulExpGuardTree_eq_zero_iff (by norm_num)] + refine ⟨habs, ?_, Or.inl int256_zero_word⟩ + rw [int256_mulExpRayHi, int256_zero_word] + norm_num + have h := run_mul_exp_ray_evm_eq_tree_of_guard y 0 hguard + rwa [mulExpTree_scale_point hy habs] at h + +/-- **Clamp.** `mulExpRay(y, x)` returns zero at or below the zero cutoff, for every supported +magnitude. -/ +theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : + run_mul_exp_ray_evm y x = .ok 0 := by + have hguard : mulExpGuardTree y x = 0 := by + rw [mulExpGuardTree_eq_zero_iff hx] + refine ⟨habs, ?_, Or.inr (Or.inl hclamp)⟩ + rw [int256_mulExpRayHi] + rw [int256_mulExpRayZeroMax] at hclamp + omega + have h := run_mul_exp_ray_evm_eq_tree_of_guard y x hguard + rwa [mulExpTree_clamped hx hclamp] at h + +/-! ## Shell brackets -/ + +noncomputable section + +/-- **Scale-point bracket.** The exact result `y` satisfies the public bracket at `x = 0`. -/ +theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : y < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) : MulExpRayRunBracket y 0 := by + refine ⟨y, run_mul_exp_ray_evm_scale_point hy habs, ?_⟩ + rw [int256_zero_word] + have hA : mulExpRayMagnitudeTarget (int256 y) 0 = ((int256 y).natAbs : ℝ) := by + unfold mulExpRayMagnitudeTarget + norm_num + unfold MulExpRayBracket + have habs' : (((int256 y).natAbs : ℕ) : ℝ) = |((int256 y : ℤ) : ℝ)| := by + rw [Nat.cast_natAbs] + push_cast + ring + split_ifs with hneg + · have habsneg : |((int256 y : ℤ) : ℝ)| = -((int256 y : ℤ) : ℝ) := + abs_of_nonpos (by exact_mod_cast le_of_lt hneg) + refine ⟨by omega, ?_, ?_⟩ + · rw [hA, habs', habsneg] + push_cast + linarith + · rw [hA, habs', habsneg] + push_cast + linarith + · push_neg at hneg + have habspos : |((int256 y : ℤ) : ℝ)| = ((int256 y : ℤ) : ℝ) := + abs_of_nonneg (by exact_mod_cast hneg) + refine ⟨hneg, ?_, ?_⟩ + · rw [hA, habs', habspos] + · rw [hA, habs', habspos] + linarith + +/-- Below the zero cutoff, every supported magnitude's real target is below one. -/ +theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : + mulExpRayMagnitudeTarget (int256 y) (int256 x) < 1 := by + unfold mulExpRayMagnitudeTarget + have hRAY : (RAY : ℝ) = 10 ^ 27 := by unfold RAY; push_cast; norm_num + set z : ℝ := (int256 x : ℝ) / (RAY : ℝ) with hz + have hzM : z ≤ (-88376265521393026950697095485 : ℝ) / 10 ^ 27 := by + rw [hz, hRAY] + apply div_le_div_of_nonneg_right ?_ (by norm_num) + · exact_mod_cast le_trans hclamp (le_of_eq int256_mulExpRayZeroMax) + have hlog : Real.log 2 < 0.6931471808 := Real.log_two_lt_d9 + have hexp1 : Real.exp (z + 127 * Real.log 2) < 1 := by + apply Real.exp_lt_one_iff.mpr + nlinarith [hzM, hlog] + have hpow : (2 : ℝ) ^ (127 : ℕ) * Real.exp z = Real.exp (z + 127 * Real.log 2) := by + rw [Real.exp_add] + rw [show (127 : ℝ) * Real.log 2 = Real.log ((2 : ℝ) ^ (127 : ℕ)) from by + rw [Real.log_pow]; push_cast; ring] + rw [Real.exp_log (by positivity)] + ring + have hnat : ((int256 y).natAbs : ℝ) ≤ ((scaleQ67 : Nat) : ℝ) := by + have h := absTree_eq_natAbs hy + exact_mod_cast (h ▸ habs) + have hQ : ((scaleQ67 : Nat) : ℝ) < (2 : ℝ) ^ (127 : ℕ) := by + unfold scaleQ67 + norm_num + calc ((int256 y).natAbs : ℝ) * Real.exp z + ≤ (2 : ℝ) ^ (127 : ℕ) * Real.exp z := by + apply mul_le_mul_of_nonneg_right _ (le_of_lt (Real.exp_pos z)) + linarith + _ = Real.exp (z + 127 * Real.log 2) := hpow + _ < 1 := hexp1 + +/-- **Clamp bracket.** The zero result satisfies the public bracket at or below the cutoff. -/ +theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : + MulExpRayRunBracket y x := by + refine ⟨0, run_mul_exp_ray_evm_clamped hy hx habs hclamp, ?_⟩ + rw [int256_zero_word] + have hlt := clamped_target_lt_one hy hx habs hclamp + have hnn := mulExpRayMagnitudeTarget_nonneg (int256 y) (int256 x) + unfold MulExpRayBracket + split_ifs <;> + exact ⟨le_refl 0, by simpa using hnn, by push_cast; linarith⟩ + +end + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean b/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean new file mode 100644 index 000000000..61e2b5584 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean @@ -0,0 +1,61 @@ +import ExpProof.Mono.WordFacts + +/-! +# Word-level bridges for the `mulExpRay` guard + +Comparison and boolean-word facts that translate the compiled guard word into signed +predicates. They complement `Mono.WordFacts` without disturbing its downstream consumers. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word + +/-- `evmSgt` is `evmSlt` with the operands swapped. -/ +theorem evmSgt_eq_evmSlt_swap (a b : Nat) : evmSgt a b = evmSlt b a := rfl + +/-- `evmGt a b` compares the canonical words unsigned. -/ +theorem evmGt_eq_ite (a b : Nat) : evmGt a b = if u256 b < u256 a then 1 else 0 := rfl + +/-- `evmEq a b` compares the canonical words. -/ +theorem evmEq_eq_ite (a b : Nat) : evmEq a b = if u256 a = u256 b then 1 else 0 := rfl + +/-- A canonical word is signed-zero exactly when it is the zero word. -/ +theorem int256_zero_iff_of_canonical {x : Nat} (hx : x < 2 ^ 256) : int256 x = 0 ↔ x = 0 := by + unfold int256 + have hx' : (x : Int) < 2 ^ 256 := by exact_mod_cast hx + split_ifs <;> omega + +/-- An `if`-encoded boolean word is zero exactly when its condition fails. -/ +theorem ite_one_zero_eq_zero_iff {c : Prop} [Decidable c] : + (if c then (1 : Nat) else 0) = 0 ↔ ¬c := by + split_ifs with h <;> simp [h] + +/-- An `if`-encoded boolean word is one exactly when its condition holds. -/ +theorem ite_one_zero_eq_one_iff {c : Prop} [Decidable c] : + (if c then (1 : Nat) else 0) = 1 ↔ c := by + split_ifs with h <;> simp [h] + +/-- `evmIszero` negates an `if`-encoded boolean word. -/ +theorem evmIszero_ite (c : Prop) [Decidable c] : + evmIszero (if c then (1 : Nat) else 0) = if c then 0 else 1 := by + unfold evmIszero u256 WORD_MOD + split_ifs <;> simp_all + +/-- `evmOr` of `if`-encoded boolean words is the disjunction. -/ +theorem evmOr_ite (c d : Prop) [Decidable c] [Decidable d] : + evmOr (if c then (1 : Nat) else 0) (if d then (1 : Nat) else 0) = + if c ∨ d then 1 else 0 := by + unfold evmOr u256 WORD_MOD + split_ifs <;> simp_all + +/-- `evmAnd` of `if`-encoded boolean words is the conjunction. -/ +theorem evmAnd_ite (c d : Prop) [Decidable c] [Decidable d] : + evmAnd (if c then (1 : Nat) else 0) (if d then (1 : Nat) else 0) = + if c ∧ d then 1 else 0 := by + unfold evmAnd u256 WORD_MOD + split_ifs <;> simp_all + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean new file mode 100644 index 000000000..8a46d639c --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -0,0 +1,374 @@ +import ExpProof.ExpYulProof +import Common.Word +import ExpProof.Seam.Helpers +import ExpProof.Seam.Dispatcher +import ExpProof.Seam.Revert +import ExpProof.Mono.MulTree +import FormalYul.Preservation + +/-! +# Revert reduction for the `mulExpRay` guard + +When the guard word is one, `fun_mulExpRay` takes the panic branch and reverts via +`fun_panic(ARITHMETIC_OVERFLOW)`. The prefix of the trace (headroom, octave, shift, and the +guard atoms) is shared with the value path; only the branch outcome differs. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word + +set_option maxRecDepth 100000 + +set_option maxHeartbeats 12000000 in +/-- `fun_mulExpRay(y, x)` reverts when the guard word is one. -/ +theorem call_fun_mulExpRay_revert_direct + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hguard : mulExpGuardTree y x = 1) : + EvmYul.Yul.call (fuel + (extra + 2200)) [FormalYul.word y, FormalYul.word x] + (.some yulName_fun_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .error EvmYul.Yul.Exception.Revert := by + rw [show fuel + (extra + 2200) = (fuel + extra) + 2200 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_mulExpRay] + simp only [yulFunctionBody_fun_mulExpRay, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + let sign := signTree y + let ay := absTree y + let s0 := evmSub (evmClz ay) scaleMaxClz + let s := evmSub s0 (evmGt (evmShl s0 ay) scaleQ67) + let k := kTree x + let shift := evmSub s k + have hzeroInit := + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2176) + (shared := shared) (hlookup := hlookup) + have hzeroUint1 := + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2173) + (shared := shared) (hlookup := hlookup) + have hzeroUint2 := + call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2170) + (shared := shared) (hlookup := hlookup) + have hclz := + call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) + (shared := shared) (hlookup := hlookup) + have hscaleMaxClz := + call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 2023) + (shared := shared) (hlookup := hlookup) + have hwrapS0 := + call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) + (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) + have hscaleMax1 := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2020) + (shared := shared) (hlookup := hlookup) + have hoctave := + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2055) + (shared := shared) (hlookup := hlookup) + have hconvertS := + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2051) + (shared := shared) (hlookup := hlookup) + have hwrapShift := + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2088) + (shared := shared) (hlookup := hlookup) + have hscaleMax2 := + call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2004) + (shared := shared) (hlookup := hlookup) + have hcleanupScaleMax := + call_cleanup_t_uint256_direct (v := scaleQ67) (fuel := fuel + extra) (extra := 2141) + (shared := shared) (hlookup := hlookup) + have hcleanupAyGuard := + call_cleanup_t_uint256_direct (v := ay) (fuel := fuel + extra) (extra := 2139) + (shared := shared) (hlookup := hlookup) + have hHi := + call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 1998) + (shared := shared) (hlookup := hlookup) + have hcleanupHi := + call_cleanup_t_int256_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 2133) + (shared := shared) (hlookup := hlookup) + have hcleanupXForHi := + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2131) + (shared := shared) (hlookup := hlookup) + have hOrOut := + call_fun_or_direct (a := evmGt ay scaleQ67) (b := evmIszero (evmSlt x mulExpRayHi)) + (fuel := fuel + extra) (extra := 2076) (shared := shared) (hlookup := hlookup) + have hconvertZeroEq := + call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 2027) + (shared := shared) (hlookup := hlookup) + have hcleanupXEq := + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2125) + (shared := shared) (hlookup := hlookup) + have hZM1 := + call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1986) + (shared := shared) (hlookup := hlookup) + have hcleanupZM := + call_cleanup_t_int256_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 2123) + (shared := shared) (hlookup := hlookup) + have hcleanupXForLo := + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2121) + (shared := shared) (hlookup := hlookup) + have hAndLo := + call_fun_and_direct (a := evmIszero (evmEq x 0)) (b := evmSgt x mulExpRayZeroMax) + (fuel := fuel + extra) (extra := 2064) (shared := shared) (hlookup := hlookup) + have hconvertTwo := + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2017) + (shared := shared) (hlookup := hlookup) + have hcleanupShift := + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2115) + (shared := shared) (hlookup := hlookup) + have hAndAccuracy := + call_fun_and_direct + (a := evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) + (b := evmSlt shift 2) (fuel := fuel + extra) (extra := 2058) + (shared := shared) (hlookup := hlookup) + have hOrGuard := + call_fun_or_direct + (a := evmOr (evmGt ay scaleQ67) (evmIszero (evmSlt x mulExpRayHi))) + (b := evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) + (evmSlt shift 2)) + (fuel := fuel + extra) (extra := 2057) (shared := shared) (hlookup := hlookup) + have hoverflow := + call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1972) + (shared := shared) (hlookup := hlookup) + have hconvu := + call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2011) + (shared := shared) (hlookup := hlookup) + have hpanic := + call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1530) + (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS0 + simp only [Nat.reduceAdd, FormalYul.word] at hscaleMax1 hscaleMax2 + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave + simp only [Nat.reduceAdd, FormalYul.word, s, s0, ay, absTree, signTree, scaleMaxClz, + scaleQ67] at hconvertS + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, s0, ay, absTree, signTree, scaleMaxClz, + scaleQ67] at hwrapShift + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, + scaleQ67] at hcleanupScaleMax hcleanupAyGuard + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, + mulExpRayHi] at hHi + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hcleanupHi + simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, ay, absTree, signTree, scaleQ67, + mulExpRayHi] at hOrOut + simp only [Nat.reduceAdd, FormalYul.word] at hconvertZeroEq hcleanupXEq + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, + mulExpRayZeroMax] at hZM1 + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayZeroMax] at hcleanupZM + simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForLo + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, + mulExpRayZeroMax] at hAndLo + simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo + simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, s0, ay, absTree, signTree, + scaleMaxClz, scaleQ67] at hcleanupShift + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, k, kTree, shift, s, s0, ay, absTree, + signTree, scaleMaxClz, scaleQ67, mulExpRayZeroMax] at hAndAccuracy + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, s0, ay, absTree, + signTree, scaleMaxClz, scaleQ67, mulExpRayHi, mulExpRayZeroMax] at hOrGuard + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant_ARITHMETIC_OVERFLOW] at hoverflow + simp only [Nat.reduceAdd, FormalYul.word] at hconvu + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_panic] at hpanic + have hguardUnfold : + evmOr + (evmOr + (evmGt (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)) + 147573952589676412928000000000000000000) + (evmIszero (evmSlt x 86989971160273136331862631244))) + (evmAnd + (evmAnd (evmIszero (evmEq x 0)) + (evmSgt x 115792089237316195423570985008687907853269984665552187773936190980962432544451)) + (evmSlt + (evmSub + (evmSub (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) + (evmGt + (evmShl (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) + (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) + 147573952589676412928000000000000000000)) + (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) + 2)) = 1 := by + simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, scaleQ67, + scaleMaxClz, mulExpRayHi, mulExpRayZeroMax] using hguard + simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, + EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + hguard, hguardUnfold, + hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS0, + hscaleMax1, hoctave, hconvertS, hwrapShift, hscaleMax2, hcleanupScaleMax, hcleanupAyGuard, + hHi, hcleanupHi, hcleanupXForHi, hOrOut, hconvertZeroEq, hcleanupXEq, hZM1, hcleanupZM, + hcleanupXForLo, hAndLo, hconvertTwo, hcleanupShift, hAndAccuracy, hOrGuard, + hoverflow, hconvu, hpanic, + FormalYul.Preservation.uint256_ofNat_eq_eq_word_evmEq, + FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, + FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, + FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl, + Common.Word.uint256_ofNat_xor_eq_word_evmXor, + Common.Word.uint256_ofNat_sar_eq_word_evmSar, + uint256_ofNat_slt_eq_word_evmSlt, + uint256_ofNat_sgt_eq_word_evmSgt, + uint256_ofNat_iszero_eq_word_evmIszero, + mulExpGuardTree, mulShiftTree, kTree, scaleShiftTree, absTree, signTree, + scaleQ67, scaleMaxClz, mulExpRayHi, mulExpRayZeroMax, + sign, ay, s0, s, k, shift] + +set_option maxHeartbeats 12000000 in +/-- `fun_wrap_mulExpRay` forwards the revert. -/ +theorem call_fun_wrap_mulExpRay_revert_direct + (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hguard : mulExpGuardTree y x = 1) : + EvmYul.Yul.call (fuel + (extra + 2300)) [FormalYul.word y, FormalYul.word x] + (.some yulName_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .error EvmYul.Yul.Exception.Revert := by + rw [show fuel + (extra + 2300) = (fuel + extra) + 2300 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_wrap_mulExpRay] + simp only [yulFunctionBody_fun_wrap_mulExpRay, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hinner := + call_fun_mulExpRay_revert_direct (y := y) (x := x) (fuel := fuel + extra) (extra := 89) + (shared := shared) (hlookup := hlookup) (hguard := hguard) + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_mulExpRay] at hinner + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.setStore, + FormalYul.word, + call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2276) + (shared := shared) (hlookup := hlookup), + hinner] + +set_option maxHeartbeats 12000000 in +/-- The external `mulExpRay` entrypoint forwards the revert. -/ +theorem external_fun_wrap_mulExpRay_calldata_revert + (y x : Nat) (store : EvmYul.Yul.VarStore) + (hguard : mulExpGuardTree y x = 1) : + EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) store) = + .error EvmYul.Yul.Exception.Revert := by + rw [EvmYul.Yul.call.eq_def] + simp only [mulExpSharedAfterFreePtr_lookup, Option.getD_some, yulContract_functions, + lookup_external_fun_wrap_mulExpRay] + simp only [yulFunctionBody_external_fun_wrap_mulExpRay, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hdecode := + call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := y) (x := x) + (fuel := 0) (extra := 999464) + (shared := mulExpSharedAfterFreePtr y x) + (store := (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) + (hdata := mulExpSharedAfterFreePtr_calldata y x) + simp only [Nat.reduceAdd, FormalYul.word] at hdecode + have hwrap := + call_fun_wrap_mulExpRay_revert_direct (y := y) (x := x) (fuel := 0) (extra := 997683) + (shared := mulExpSharedAfterFreePtr y x) + (store := Finmap.insert "param_0" (FormalYul.word y) + (Finmap.insert "param_1" (FormalYul.word x) + (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hguard := hguard) + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.executionEnv, + mulExpSharedAfterFreePtr_weiValue, mulExpSharedAfterFreePtr_calldata, mulExpRay_calldata_size, + GetElem?.getElem!, decidableGetElem?, + EvmYul.Yul.State.instGetElemIdentifierLiteralMemVarStoreStore, + EvmYul.Yul.State.store, + Finmap.lookup_insert, + hdecode, hwrap] + +set_option maxHeartbeats 12000000 in +/-- The revert from the exact dispatcher-handed state. -/ +theorem external_fun_wrap_mulExpRay_dispatcher_state_revert + (y x : Nat) + (hguard : mulExpGuardTree y x = 1) : + EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Finmap.insert "selector" + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok + (EvmYul.SharedState.mk + (FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).toState + ((FormalYul.sharedFor yulContract + (selector_mulExpRay ++ FormalYul.encodeWords [y, x])).mstore + (EvmYul.UInt256.ofNat 64) (EvmYul.UInt256.ofNat 128))) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + (Inhabited.default : EvmYul.Yul.VarStore))) = + .error EvmYul.Yul.Exception.Revert := by + rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr_raw] + exact external_fun_wrap_mulExpRay_calldata_revert y x + (store := Finmap.insert "selector" + (EvmYul.UInt256.shiftRight + (EvmYul.State.calldataload + (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) + (Inhabited.default : EvmYul.Yul.VarStore)).toState + (EvmYul.UInt256.ofNat 0)) + (EvmYul.UInt256.ofNat 224)) + (Inhabited.default : EvmYul.Yul.VarStore)) + hguard + +set_option maxHeartbeats 12000000 in +/-- **Guard revert.** When the guard word is one, the compiled runtime reverts. -/ +theorem run_mul_exp_ray_evm_revert_of_guard (y x : Nat) + (hguard : mulExpGuardTree y x = 1) : + run_mul_exp_ray_evm y x = .error "revert" := by + have hexec : + EvmYul.Yul.exec 999998 yulContract.dispatcher (.some yulContract) + (stateFor yulContract (FormalYul.calldata selector_mulExpRay [y, x])) = + .error EvmYul.Yul.Exception.Revert := by + rw [yulContract_dispatcher] + simp +decide [FormalYul.calldata, stateFor, yulDispatcher, + EvmYul.Yul.execCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', + EvmYul.Yul.head', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.executionEnv, EvmYul.Yul.State.toMachineState, + FormalYul.word, call_shift_right_224_unsigned_direct] + rw [selectSwitchCase_mulExpRay_sharedFor_mk_raw y x] + simp +decide [external_fun_wrap_mulExpRay_dispatcher_state_revert y x hguard, + EvmYul.Yul.exec.eq_def, EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.multifill'] + have hrun : + runContract yulContract (FormalYul.calldata selector_mulExpRay [y, x]) 1000000 = + .error "revert" := + runContract_revert_of_exec_revert hexec + unfold run_mul_exp_ray_evm FormalYul.callWord FormalYul.call + rw [hrun] + rfl + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index a62c576f1..a1f88817f 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -6,7 +6,7 @@ import ExpProof.Floor.PublicUncond import ExpProof.Floor.R0BoundHolds import ExpProof.Floor.R0Bound import ExpProof.Floor.RoundTrip -import ExpProof.Mul +import ExpProof.Mul.Shell /-! # `expRayToWad` and `mulExpRay` — compiled-runtime proof signpost @@ -98,17 +98,20 @@ example (x1 x2 : Nat) The public spec for `mulExpRay` is a signed magnitude bracket plus monotonicity predicates in both arguments. Discharged today, axiom-clean: -* the guard-domain partition of canonical calldata into exact value and panic domains; -* the value path: whenever the guard word is zero, the compiled runtime returns the signed - dynamic-scale arithmetic tree (`run_mul_exp_ray_evm_eq_tree_of_guard`) — one reduction for - every multiplier, including zero, whose result the `sgn(0)` multiply collapses to zero - (`run_mul_exp_ray_evm_zero_of_guard`); -* the real-target monotonicity facts and the bracket/sign-reapplication glue. - -Still open, visible below as explicit hypotheses of the facade lemmas: the guard-word ↔ domain -bridge, the `Panic(17)` revert theorem on the panic domain, and the bracket and monotonicity of -the tree itself (which need the `Floor` certificates generalized from the fixed wad scale to the -dynamic scale). +| Property | Theorem | +|-----------------------------------------------------|-----------------------------------------| +| Exact value/panic partition of canonical calldata | `mulExpRay_value_iff_not_panic` | +| Guard word ↔ domain bridge | `valueDomain_iff_guard_eq_zero` | +| Value path returns the compiled tree | `run_mul_exp_ray_evm_eq_tree` | +| Rejected inputs revert | `run_mul_exp_ray_evm_revert` | +| Zero multiplier returns zero (and its bracket) | `run_mul_exp_ray_evm_zero_of_guard` | +| Scale point `mulExpRay(y, 0) = y` (and its bracket) | `run_mul_exp_ray_evm_scale_point` | +| Zero clamp at deep-negative `x` (and its bracket) | `run_mul_exp_ray_evm_clamped` | + +Still open, visible below as explicit hypotheses of the facade lemmas: the bracket on the live +region (`x` strictly between the clamp cutoff and the scale point's octave limit) and the runtime +monotonicity statements, both of which need the `Floor` certificates generalized from the fixed +wad scale `10¹⁸·2⁶⁷` to the dynamic scale `abs(y)·2ˢ`. -/ /-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ @@ -182,6 +185,45 @@ accepts. -/ example (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : MulExpRayRunBracket 0 x := mulExpRay_run_bracket_zero x hguard +/-- The guard word is zero exactly on the value domain. -/ +example {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayValueDomain y x ↔ mulExpGuardTree y x = 0 := + valueDomain_iff_guard_eq_zero hcanon + +/-- Accepted inputs return the compiled tree. -/ +example {y x : Nat} (h : MulExpRayValueDomain y x) : + run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := + run_mul_exp_ray_evm_eq_tree h + +/-- Rejected inputs revert. -/ +example {y x : Nat} (h : MulExpRayPanicDomain y x) : + run_mul_exp_ray_evm y x = .error "revert" := + run_mul_exp_ray_evm_revert h + +/-- The scale point returns the multiplier exactly. -/ +example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : + run_mul_exp_ray_evm y 0 = .ok y := + run_mul_exp_ray_evm_scale_point hy habs + +/-- The scale-point result satisfies the public bracket. -/ +example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : + MulExpRayRunBracket y 0 := + mulExpRay_run_bracket_scale_point hy habs + +/-- At or below the zero cutoff, every supported magnitude returns zero. -/ +example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) + (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : + run_mul_exp_ray_evm y x = .ok 0 := + run_mul_exp_ray_evm_clamped hy hx habs hclamp + +/-- The clamped result satisfies the public bracket. -/ +example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) + (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : + MulExpRayRunBracket y x := + mulExpRay_run_bracket_clamped hy hx habs hclamp + /-- The accumulator floor and target bounds imply the public magnitude bracket. -/ example {y x m : Int} {A : Real} (hm_nonneg : 0 ≤ m) @@ -283,6 +325,34 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_bracket_zero +/-- info: 'ExpYul.valueDomain_iff_guard_eq_zero' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms valueDomain_iff_guard_eq_zero + +/-- info: 'ExpYul.run_mul_exp_ray_evm_eq_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_eq_tree + +/-- info: 'ExpYul.run_mul_exp_ray_evm_revert' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_revert + +/-- info: 'ExpYul.run_mul_exp_ray_evm_scale_point' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_scale_point + +/-- info: 'ExpYul.mulExpRay_run_bracket_scale_point' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_bracket_scale_point + +/-- info: 'ExpYul.run_mul_exp_ray_evm_clamped' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_clamped + +/-- info: 'ExpYul.mulExpRay_run_bracket_clamped' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_bracket_clamped + /-- info: 'ExpRealSpec.mulExpRayTarget_signed_mono' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms ExpRealSpec.mulExpRayTarget_signed_mono From 1493ac2e9618ee370a8a3e481dd8b1bfe8dd8c09 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 10:17:43 +0200 Subject: [PATCH 066/107] Widen the exp reduction anchors to the mulExpRay region The octave/reduced-argument transports, the cert-domain and Reduce brackets, and their forward wrappers now hold on the whole live region of mulExpRay (bundled as WideRegion: strictly between the zero clamp and the overflow guard, |X| < 2^97, k in [-127, 125]). The widened Reduce brackets reprove the same literal constants (1/(32*2^129) over, 1025/(1024*2^129) under), so the downstream error budgets are unchanged. The expRayToWad meaningful region is strictly contained in the wide region, so every wad-named lemma keeps its statement and signature as a domain-inclusion instance; the symmetric reducedArg bracket now derives from the two one-sided bounds instead of repeating their decomposition. The wad kTree_bound keeps its own proof (its [-61, 65] range is strictly sharper than the wide [-127, 125]). Co-Authored-By: Claude Fable 5 --- formal/exp/ExpProof/ExpProof/Floor/GranV.lean | 64 +++-- .../exp/ExpProof/ExpProof/Floor/Reduce.lean | 265 +++++------------- .../exp/ExpProof/ExpProof/Floor/TBound.lean | 40 +-- formal/exp/ExpProof/ExpProof/Mono/Octave.lean | 177 +++++++++--- formal/exp/ExpProof/ExpProof/Mono/Quot.lean | 30 +- .../ExpProof/ExpProof/Mono/RegionMono.lean | 18 +- formal/exp/ExpProof/ExpProof/Mono/Stages.lean | 53 ++-- 7 files changed, 340 insertions(+), 307 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/GranV.lean b/formal/exp/ExpProof/ExpProof/Floor/GranV.lean index 4846bde61..595bfc665 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/GranV.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/GranV.lean @@ -403,11 +403,10 @@ theorem step_identity (v : Nat) (t : Int) : /-! ## Grid placement of the exact square -/ /-- The squared reduced argument splits as `t² = 2¹³⁵·vTree x + r` with `0 ≤ r < 2¹³⁵`. -/ -theorem tsq_split {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem tsq_split_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : 2 ^ 135 * (vTree x : Int) ≤ (int256 (tTree x)) ^ 2 ∧ (int256 (tTree x)) ^ 2 < 2 ^ 135 * (vTree x : Int) + 2 ^ 135 := by - obtain ⟨hveq, _⟩ := vTree_eq hx hC hC0 + obtain ⟨hveq, _⟩ := vTree_eq_wide hx hW have hsqnn : (0 : Int) ≤ (int256 (tTree x)) ^ 2 := sq_nonneg _ have hdm := Int.ediv_add_emod ((int256 (tTree x)) ^ 2) (2 ^ 135) have hmod_lt := Int.emod_lt_of_pos ((int256 (tTree x)) ^ 2) (by norm_num : (0:Int) < 2 ^ 135) @@ -417,12 +416,17 @@ theorem tsq_split {x : Nat} (hx : x < 2 ^ 256) · nlinarith [hdm, hmod_nn] · nlinarith [hdm, hmod_lt] -/-- The grid index never leaves the certified domain: `vTree x ≤ vmaxV`. -/ -theorem vTree_le_vmax {x : Nat} (hx : x < 2 ^ 256) +theorem tsq_split {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + 2 ^ 135 * (vTree x : Int) ≤ (int256 (tTree x)) ^ 2 ∧ + (int256 (tTree x)) ^ 2 < 2 ^ 135 * (vTree x : Int) + 2 ^ 135 := + tsq_split_wide hx (wideRegion_of_wad hC hC0) + +/-- The grid index never leaves the certified domain: `vTree x ≤ vmaxV`. -/ +theorem vTree_le_vmax_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : vTree x ≤ ExpCertV.vmaxV := by - obtain ⟨hlo, _⟩ := tsq_split hx hC hC0 - obtain ⟨htlo, hthi⟩ := tTree_in_cert_domain hx hC hC0 + obtain ⟨hlo, _⟩ := tsq_split_wide hx hW + obtain ⟨htlo, hthi⟩ := tTree_in_cert_domain_wide hx hW have ht2 : (int256 (tTree x)) ^ 2 ≤ 235865763225513294137944142764154484399 ^ 2 := by nlinarith [htlo, hthi] have hlt : 2 ^ 135 * (vTree x : Int) < @@ -436,6 +440,11 @@ theorem vTree_le_vmax {x : Nat} (hx : x < 2 ^ 256) unfold ExpCertV.vmaxV omega +theorem vTree_le_vmax {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + vTree x ≤ ExpCertV.vmaxV := + vTree_le_vmax_wide hx (wideRegion_of_wad hC hC0) + /-! ## Cross-monotonicity of the rational in the square argument -/ /-- Power cross-product monotonicity: `a^(j+d)·b^j ≤ a^j·b^(j+d)` for `0 ≤ a ≤ b`. -/ @@ -547,14 +556,13 @@ theorem DE_eq_w (t : Int) : /-- **The tie at the runtime point (nonnegative half)**: the cert rational at `t²` lies between the two grid values, as cross products. -/ -theorem tie_over {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) +theorem tie_over_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x) (int256 (tTree x)) ≤ NUMv (vTree x) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) ∧ NUMv (vTree x + 1) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) ≤ evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x + 1) (int256 (tTree x)) := by - obtain ⟨haw, hwb⟩ := tsq_split hx hC hC0 + obtain ⟨haw, hwb⟩ := tsq_split_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef have hs : (0:Int) ≤ 2 ^ 24 * t := by positivity @@ -586,15 +594,23 @@ theorem tie_over {x : Nat} (hx : x < 2 ^ 256) _ = 2 ^ 564 * (evalPoly ExpCertV.numExpV t * DENv (v + 1) t) := by ring exact le_of_mul_le_mul_left h2 hp555 -/-- **The tie at the runtime point (nonpositive half)**: the directions flip. -/ -theorem tie_under {x : Nat} (hx : x < 2 ^ 256) +theorem tie_over {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (htnn : 0 ≤ int256 (tTree x)) : + evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x) (int256 (tTree x)) ≤ + NUMv (vTree x) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) ∧ + NUMv (vTree x + 1) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) ≤ + evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x + 1) (int256 (tTree x)) := + tie_over_wide hx (wideRegion_of_wad hC hC0) htnn + +/-- **The tie at the runtime point (nonpositive half)**: the directions flip. -/ +theorem tie_under_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) (htnp : int256 (tTree x) ≤ 0) : NUMv (vTree x) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) ≤ evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x) (int256 (tTree x)) ∧ evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x + 1) (int256 (tTree x)) ≤ NUMv (vTree x + 1) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) := by - obtain ⟨haw, hwb⟩ := tsq_split hx hC hC0 + obtain ⟨haw, hwb⟩ := tsq_split_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef have hs : (0:Int) ≤ 2 ^ 24 * (-t) := by @@ -646,6 +662,15 @@ theorem tie_under {x : Nat} (hx : x < 2 ^ 256) _ = 2 ^ 564 * (NUMv (v + 1) t * evalPoly ExpCertV.denExpV t) := by ring exact le_of_mul_le_mul_left h2 hp555 +theorem tie_under {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (htnp : int256 (tTree x) ≤ 0) : + NUMv (vTree x) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) ≤ + evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x) (int256 (tTree x)) ∧ + evalPoly ExpCertV.numExpV (int256 (tTree x)) * DENv (vTree x + 1) (int256 (tTree x)) ≤ + NUMv (vTree x + 1) (int256 (tTree x)) * evalPoly ExpCertV.denExpV (int256 (tTree x)) := + tie_under_wide hx (wideRegion_of_wad hC hC0) htnp + /-! ## The 32-piece granularity certificate -/ /-- The per-piece granularity facts at a grid point `v`: positivity of the floors and the cap, @@ -1201,13 +1226,12 @@ theorem granPieces_ok : ∀ p ∈ ExpCertV.granPieces, PieceHolds p := by /-- **Piece selection.** The runtime grid point lies in one of the 32 pieces, whose certified constants apply, and the piece's `t`-cap dominates the reduced argument: `t² < T²`. -/ -theorem piece_select {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem piece_select_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : ∃ T DO DU Khi : Int, PieceOK (vTree x) T DO DU Khi ∧ (int256 (tTree x)) ^ 2 < T ^ 2 := by - obtain ⟨_, hsplit⟩ := tsq_split hx hC hC0 + obtain ⟨_, hsplit⟩ := tsq_split_wide hx hW have hvI : ((vTree x : Nat) : Int) ≤ (ExpCertV.vmaxV : Int) := by - exact_mod_cast vTree_le_vmax hx hC hC0 + exact_mod_cast vTree_le_vmax_wide hx hW obtain ⟨p, hp, hplo, hphi⟩ := piecesCover_sound hvI 0 granPieces_cover (Int.natCast_nonneg _) obtain ⟨vlo, vhi, T, DO, DU⟩ := p @@ -1215,4 +1239,10 @@ theorem piece_select {x : Nat} (hx : x < 2 ^ 256) granPieces_ok _ hp (vTree x) hplo hphi, tsq_lt_capsq hsplit hphi (granPieces_caps _ hp)⟩ +theorem piece_select {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + ∃ T DO DU Khi : Int, + PieceOK (vTree x) T DO DU Khi ∧ (int256 (tTree x)) ^ 2 < T ^ 2 := + piece_select_wide hx (wideRegion_of_wad hC hC0) + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean b/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean index 014e32b89..9249fbc3f 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/Reduce.lean @@ -16,12 +16,12 @@ margin the runtime `MARGIN` absorbs: Decompose `rt − t/2¹²⁹ = P1 + P2 + P3`: -* `P1 = X·(1/RAY − K27/2²³⁵)` — the rational coefficient error over `|X| < 2⁹⁶`, below `2⁻¹³³`; +* `P1 = X·(1/RAY − K27/2²³⁵)` — the rational coefficient error over `|X| < 2⁹⁷`, below `2⁻¹⁴⁰`; * `P2 = k·(LN2/2²³⁵ − ln2)` — the `ln2`-grid error (`0 ≤ ln2 − LN2/2²³⁵ < 2⁻²³⁵`, from `Ln2Bound`) - over `|k| ≤ 65`, below `2⁻²²⁸`; + over `|k| ≤ 127`, below `2⁻²²⁸`; * `P3 = (K27·X − LN2·k)/2²³⁵ − t/2¹²⁹ ∈ [0, 1/2¹²⁹)` — the integer `t`-rounding sandwich. -The sum is below `2/2¹²⁹`. +The sum is below `2/2¹²⁹`, and each bound holds over the whole wide region. -/ namespace ExpYul @@ -39,16 +39,15 @@ set_option maxHeartbeats 2000000 def reducedArg (x : Nat) : Real := (int256 x : Real) / (10 ^ 27 : Real) - (int256 (kTree x) : Real) * Real.log 2 -/-- **Reduced-argument tight over bound (gap-1, one-sided).** On the meaningful region the integer +/-- **Reduced-argument tight over bound (gap-1, one-sided).** On the wide region the integer `t`-rounding residual `P3 ≥ 0` makes the over direction strictly tighter than the symmetric bound: `t/2¹²⁹ − rt < 1/(32·2¹²⁹)` (the `ln2`-grid and rational errors alone, since `P3 ≥ 0` only helps). This is the gap-1 contribution the joint never-over budget consumes. -/ -theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem reducedArg_close_over_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (int256 (tTree x) : Real) / (2 ^ 129 : Real) - reducedArg x < 1 / (32 * (2 ^ 129 : Real)) := by - obtain ⟨htlo, hthi⟩ := tTree_sandwich hx hC hC0 - obtain ⟨hklo, hkhi⟩ := kTree_bound hx hC hC0 - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 + obtain ⟨htlo, hthi⟩ := tTree_sandwich_wide hx hW + obtain ⟨hklo, hkhi⟩ := kTree_bound_wide hx hW + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW have hln2lo := ln2_lower have hln2hi := ln2_upper set t : Int := int256 (tTree x) with htdef @@ -85,15 +84,15 @@ theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) -- identity: reducedArg x - t/2^128 = P1 + P2 + P3 have hident : XR / (10 ^ 27 : Real) - kR * LR - tR / N128 = P1 + P2 + P3 := by rw [hP1def, hP2def, hP3def]; ring - -- bound P1 : |P1| < 2^96·N/(2^235·10^27) where N = K27·10^27 − 2^235 = 222636907558699806209605632 - -- We bound P1 ∈ (−ε, ε) with ε = 2^96·N/(2^235·10^27) < 2⁻¹³². Use explicit endpoints. - have hXloR : -(79228162514264337593543950336 : Real) < XR := by + -- bound P1 : |P1| < 2^97·N/(2^235·10^27) where N = K27·10^27 − 2^235 = 222636907558699806209605632 + -- We bound P1 ∈ (−ε, ε) with ε = 2^97·N/(2^235·10^27) < 2⁻¹³⁹. Use explicit endpoints. + have hXloR : -(158456325028528675187087900672 : Real) < XR := by have := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hxlo; rw [hXRdef] - rw [show ((2:Int)^96 : Int) = 79228162514264337593543950336 from by norm_num] at this + rw [show ((2:Int)^97 : Int) = 158456325028528675187087900672 from by norm_num] at this push_cast at this; linarith [this] - have hXhiR : XR < (79228162514264337593543950336 : Real) := by + have hXhiR : XR < (158456325028528675187087900672 : Real) := by have := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hxhi; rw [hXRdef] - rw [show ((2:Int)^96 : Int) = 79228162514264337593543950336 from by norm_num] at this + rw [show ((2:Int)^97 : Int) = 158456325028528675187087900672 from by norm_num] at this push_cast at this; linarith [this] -- coefficient: 1/10^27 − K27/2^235 < 0, magnitude m := (K27·10^27 − 2^235)/(2^235·10^27) have hcoeff_eq : (1 / (10 ^ 27 : Real) - K27R / N235) = @@ -101,7 +100,7 @@ theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) rw [hK27R, hN235]; field_simp; ring have hcoeff_num : K27R * (10 ^ 27 : Real) - N235 = 222636907558699806209605632 := by rw [hK27R, hN235]; norm_num - -- |P1| < 2⁻¹³² (a generous bound): |XR| < 2^96, |coeff| = m, and 2^96·m < 2⁻¹³². + -- |P1| < 2⁻¹³⁹ (a generous bound): |XR| < 2^97, |coeff| = m, and 2^97·m < 2⁻¹³⁹. have hP1_abs : |P1| < 1 / (64 * N128) := by rw [hP1def, hcoeff_eq, hcoeff_num, abs_mul] have hden_pos : (0 : Real) < N235 * (10 ^ 27 : Real) := by positivity @@ -109,12 +108,12 @@ theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by rw [abs_neg, abs_of_pos (by positivity)] rw [hco_abs] - have hX_abs : |XR| < 79228162514264337593543950336 := abs_lt.mpr ⟨hXloR, hXhiR⟩ + have hX_abs : |XR| < 158456325028528675187087900672 := abs_lt.mpr ⟨hXloR, hXhiR⟩ have hco_pos : (0:Real) < 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by positivity calc |XR| * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) - < 79228162514264337593543950336 * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) := + < 158456325028528675187087900672 * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) := (mul_lt_mul_right hco_pos).mpr hX_abs - _ = 79228162514264337593543950336 * 222636907558699806209605632 / + _ = 158456325028528675187087900672 * 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by rw [mul_div_assoc] _ < 1 / (64 * N128) := by rw [hN235, hN128, div_lt_div_iff₀ (by positivity) (by positivity)]; norm_num @@ -123,23 +122,23 @@ theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) have hP2_hi : -(1 / N235) ≤ LN2R / N235 - LR := by have : LR ≤ (LN2R + 1) / N235 := hln2hi rw [add_div] at this; linarith [this] - -- |k| ≤ 65 ⇒ |P2| ≤ 65/N235 < 1/N128 - have hkloR : -(61 : Real) ≤ kR := by + -- |k| ≤ 127 ⇒ |P2| ≤ 127/N235 < 1/N128 + have hkloR : -(127 : Real) ≤ kR := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hklo; rw [hkRdef]; push_cast at this; linarith [this] - have hkhiR : kR ≤ (65 : Real) := by + have hkhiR : kR ≤ (125 : Real) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hkhi; rw [hkRdef]; push_cast at this; linarith [this] have hP2_abs : |P2| < 1 / (64 * N128) := by rw [hP2def] - have h1 : |kR| ≤ 65 := abs_le.mpr ⟨by linarith [hkloR], hkhiR⟩ + have h1 : |kR| ≤ 127 := abs_le.mpr ⟨hkloR, by linarith [hkhiR]⟩ have h2 : |LN2R / N235 - LR| ≤ 1 / N235 := by rw [abs_le] refine ⟨by linarith [hP2_hi], ?_⟩ have hpos : (0:Real) ≤ 1 / N235 := by positivity linarith [hP2_lo, hpos] - have hbound : |kR * (LN2R / N235 - LR)| ≤ 65 * (1 / N235) := by + have hbound : |kR * (LN2R / N235 - LR)| ≤ 127 * (1 / N235) := by rw [abs_mul] exact mul_le_mul h1 h2 (abs_nonneg _) (by norm_num) - have hlt : 65 * (1 / N235) < 1 / (64 * N128) := by + have hlt : 127 * (1 / N235) < 1 / (64 * N128) := by rw [hN235, hN128, mul_one_div, div_lt_div_iff₀ (by positivity) (by positivity)]; norm_num linarith [hbound, hlt] -- bound P3 ∈ [0, 1/N128) from the integer sandwich @@ -178,16 +177,20 @@ theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) linarith [hP1.1, hP2.1] linarith [h12lo, hP3_lo] +theorem reducedArg_close_over {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (int256 (tTree x) : Real) / (2 ^ 129 : Real) - reducedArg x < 1 / (32 * (2 ^ 129 : Real)) := + reducedArg_close_over_wide hx (wideRegion_of_wad hC hC0) + /-- **Reduced-argument tight under bound (gap-1, one-sided).** The deficit direction: the integer `t`-rounding residual `P3 ∈ [0, 1/2¹²⁹)` and the `ln2`-grid/rational errors `P1 + P2 < 1/(1024·2¹²⁹)` give `rt − t/2¹²⁹ < 1025/(1024·2¹²⁹)`. This is the gap-1 contribution the joint deficit budget consumes (far tighter than the symmetric `9/(8·2¹²⁹)`). -/ -theorem reducedArg_close_under {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem reducedArg_close_under_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : reducedArg x - (int256 (tTree x) : Real) / (2 ^ 129 : Real) < 1025 / (1024 * (2 ^ 129 : Real)) := by - obtain ⟨htlo, hthi⟩ := tTree_sandwich hx hC hC0 - obtain ⟨hklo, hkhi⟩ := kTree_bound hx hC hC0 - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 + obtain ⟨htlo, hthi⟩ := tTree_sandwich_wide hx hW + obtain ⟨hklo, hkhi⟩ := kTree_bound_wide hx hW + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW have hln2lo := ln2_lower have hln2hi := ln2_upper set t : Int := int256 (tTree x) with htdef @@ -218,13 +221,13 @@ theorem reducedArg_close_under {x : Nat} (hx : x < 2 ^ 256) set P3 : Real := (K27R * XR - LN2R * kR) / N235 - tR / N128 with hP3def have hident : XR / (10 ^ 27 : Real) - kR * LR - tR / N128 = P1 + P2 + P3 := by rw [hP1def, hP2def, hP3def]; ring - have hXloR : -(79228162514264337593543950336 : Real) < XR := by + have hXloR : -(158456325028528675187087900672 : Real) < XR := by have := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hxlo; rw [hXRdef] - rw [show ((2:Int)^96 : Int) = 79228162514264337593543950336 from by norm_num] at this + rw [show ((2:Int)^97 : Int) = 158456325028528675187087900672 from by norm_num] at this push_cast at this; linarith [this] - have hXhiR : XR < (79228162514264337593543950336 : Real) := by + have hXhiR : XR < (158456325028528675187087900672 : Real) := by have := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hxhi; rw [hXRdef] - rw [show ((2:Int)^96 : Int) = 79228162514264337593543950336 from by norm_num] at this + rw [show ((2:Int)^97 : Int) = 158456325028528675187087900672 from by norm_num] at this push_cast at this; linarith [this] have hcoeff_eq : (1 / (10 ^ 27 : Real) - K27R / N235) = -((K27R * (10 ^ 27 : Real) - N235) / (N235 * (10 ^ 27 : Real))) := by @@ -238,12 +241,12 @@ theorem reducedArg_close_under {x : Nat} (hx : x < 2 ^ 256) 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by rw [abs_neg, abs_of_pos (by positivity)] rw [hco_abs] - have hX_abs : |XR| < 79228162514264337593543950336 := abs_lt.mpr ⟨hXloR, hXhiR⟩ + have hX_abs : |XR| < 158456325028528675187087900672 := abs_lt.mpr ⟨hXloR, hXhiR⟩ have hco_pos : (0:Real) < 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by positivity calc |XR| * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) - < 79228162514264337593543950336 * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) := + < 158456325028528675187087900672 * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) := (mul_lt_mul_right hco_pos).mpr hX_abs - _ = 79228162514264337593543950336 * 222636907558699806209605632 / + _ = 158456325028528675187087900672 * 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by rw [mul_div_assoc] _ < 1 / (2048 * N128) := by rw [hN235, hN128, div_lt_div_iff₀ (by positivity) (by positivity)]; norm_num @@ -251,22 +254,22 @@ theorem reducedArg_close_under {x : Nat} (hx : x < 2 ^ 256) have hP2_hi : -(1 / N235) ≤ LN2R / N235 - LR := by have : LR ≤ (LN2R + 1) / N235 := hln2hi rw [add_div] at this; linarith [this] - have hkloR : -(61 : Real) ≤ kR := by + have hkloR : -(127 : Real) ≤ kR := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hklo; rw [hkRdef]; push_cast at this; linarith [this] - have hkhiR : kR ≤ (65 : Real) := by + have hkhiR : kR ≤ (125 : Real) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hkhi; rw [hkRdef]; push_cast at this; linarith [this] have hP2_abs : |P2| < 1 / (2048 * N128) := by rw [hP2def] - have h1 : |kR| ≤ 65 := abs_le.mpr ⟨by linarith [hkloR], hkhiR⟩ + have h1 : |kR| ≤ 127 := abs_le.mpr ⟨hkloR, by linarith [hkhiR]⟩ have h2 : |LN2R / N235 - LR| ≤ 1 / N235 := by rw [abs_le] refine ⟨by linarith [hP2_hi], ?_⟩ have hpos : (0:Real) ≤ 1 / N235 := by positivity linarith [hP2_lo, hpos] - have hbound : |kR * (LN2R / N235 - LR)| ≤ 65 * (1 / N235) := by + have hbound : |kR * (LN2R / N235 - LR)| ≤ 127 * (1 / N235) := by rw [abs_mul] exact mul_le_mul h1 h2 (abs_nonneg _) (by norm_num) - have hlt : 65 * (1 / N235) < 1 / (2048 * N128) := by + have hlt : 127 * (1 / N235) < 1 / (2048 * N128) := by rw [hN235, hN128, mul_one_div, div_lt_div_iff₀ (by positivity) (by positivity)]; norm_num linarith [hbound, hlt] have hP3int_hi : 55213970774324510299478046898216203619608872 * X - @@ -295,163 +298,41 @@ theorem reducedArg_close_under {x : Nat} (hx : x < 2 ^ 256) have h12 : P1 + P2 < 1 / (1024 * N128) := by rw [← he12]; linarith [hP1.2, hP2.2] rw [← h1_1024N]; linarith [h12, hP3_hi] +theorem reducedArg_close_under {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + reducedArg x - (int256 (tTree x) : Real) / (2 ^ 129 : Real) < 1025 / (1024 * (2 ^ 129 : Real)) := + reducedArg_close_under_wide hx (wideRegion_of_wad hC hC0) + /-- info: 'ExpYul.reducedArg_close_under' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms reducedArg_close_under -/-- **Reduced-argument real bound (gap-1).** On the meaningful region the reduced argument `rt` +/-- **Reduced-argument real bound (gap-1).** On the wide region the reduced argument `rt` agrees with `t/2¹²⁹` to within `9/(8·2¹²⁹)` (the integer `t`-rounding sandwich `[0, 1/2¹²⁹)` -dominates; the rational and `ln2`-grid errors are below `2⁻¹³²`). -/ +dominates; the rational and `ln2`-grid errors are below `2⁻¹⁴⁰`). -/ +theorem reducedArg_close_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : + |reducedArg x - (int256 (tTree x) : Real) / (2 ^ 129 : Real)| < 9 / (8 * (2 ^ 129 : Real)) := by + have hover := reducedArg_close_over_wide hx hW + have hunder := reducedArg_close_under_wide hx hW + set d : Real := reducedArg x - (int256 (tTree x) : Real) / (2 ^ 129 : Real) with hd + have hp128 : (0 : Real) < (2 ^ 129 : Real) := by positivity + rw [abs_lt] + constructor + · -- −d < 1/(32·2¹²⁹) ≤ 9/(8·2¹²⁹) + have h32 : (1 : Real) / (32 * (2 ^ 129 : Real)) ≤ 9 / (8 * (2 ^ 129 : Real)) := by + rw [div_le_div_iff₀ (by positivity) (by positivity)]; nlinarith [hp128] + have : -d < 1 / (32 * (2 ^ 129 : Real)) := by rw [hd]; linarith [hover] + linarith [this, h32] + · -- d < 1025/(1024·2¹²⁹) ≤ 9/(8·2¹²⁹) + have h1025 : (1025 : Real) / (1024 * (2 ^ 129 : Real)) ≤ 9 / (8 * (2 ^ 129 : Real)) := by + rw [div_le_div_iff₀ (by positivity) (by positivity)]; nlinarith [hp128] + have : d < 1025 / (1024 * (2 ^ 129 : Real)) := by rw [hd]; exact hunder + linarith [this, h1025] + theorem reducedArg_close {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : - |reducedArg x - (int256 (tTree x) : Real) / (2 ^ 129 : Real)| < 9 / (8 * (2 ^ 129 : Real)) := by - obtain ⟨htlo, hthi⟩ := tTree_sandwich hx hC hC0 - obtain ⟨hklo, hkhi⟩ := kTree_bound hx hC hC0 - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 - have hln2lo := ln2_lower - have hln2hi := ln2_upper - set t : Int := int256 (tTree x) with htdef - set k : Int := int256 (kTree x) with hkdef - set X : Int := int256 x with hXdef - have hK : (0x279d346de4781f921dd7a89933d54d1f72928 : Int) = 55213970774324510299478046898216203619608872 := by norm_num - have hL : (0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d : Int) = - 38271408169742254668347313025622401492114385419650052359639581444463709 := by norm_num - rw [hK, hL] at htlo hthi - -- ln2 bounds cleaned to decimal Real - have hLN2decimal : ((LN2c : Nat) : Real) = - 38271408169742254668347313025622401492114385419650052359639581444463709 := by - unfold LN2c; norm_num - rw [hLN2decimal] at hln2lo hln2hi - -- Real abbreviations - set LR : Real := Real.log 2 with hLRdef - set XR : Real := (X : Real) with hXRdef - set kR : Real := (k : Real) with hkRdef - set tR : Real := (t : Real) with htRdef - -- numeric Real names - set N235 : Real := (2 ^ 235 : Real) with hN235 - set N128 : Real := (2 ^ 129 : Real) with hN128 - set LN2R : Real := (38271408169742254668347313025622401492114385419650052359639581444463709 : Real) with hLN2R - set K27R : Real := (55213970774324510299478046898216203619608872 : Real) with hK27R - have hp235 : (0 : Real) < N235 := by rw [hN235]; positivity - have hp128 : (0 : Real) < N128 := by rw [hN128]; positivity - have hpRAY : (0 : Real) < (10 ^ 27 : Real) := by positivity - -- 2^235 = 2^128 · 2^107 - have hsplit : N235 = N128 * 2 ^ 106 := by rw [hN235, hN128, ← pow_add] - -- the three pieces - set P1 : Real := XR * (1 / (10 ^ 27 : Real) - K27R / N235) with hP1def - set P2 : Real := kR * (LN2R / N235 - LR) with hP2def - set P3 : Real := (K27R * XR - LN2R * kR) / N235 - tR / N128 with hP3def - -- identity: reducedArg x - t/2^128 = P1 + P2 + P3 - have hident : XR / (10 ^ 27 : Real) - kR * LR - tR / N128 = P1 + P2 + P3 := by - rw [hP1def, hP2def, hP3def]; ring - -- bound P1 : |P1| < 2^96·N/(2^235·10^27) where N = K27·10^27 − 2^235 = 222636907558699806209605632 - -- We bound P1 ∈ (−ε, ε) with ε = 2^96·N/(2^235·10^27) < 2⁻¹³². Use explicit endpoints. - have hXloR : -(79228162514264337593543950336 : Real) < XR := by - have := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hxlo; rw [hXRdef] - rw [show ((2:Int)^96 : Int) = 79228162514264337593543950336 from by norm_num] at this - push_cast at this; linarith [this] - have hXhiR : XR < (79228162514264337593543950336 : Real) := by - have := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hxhi; rw [hXRdef] - rw [show ((2:Int)^96 : Int) = 79228162514264337593543950336 from by norm_num] at this - push_cast at this; linarith [this] - -- coefficient: 1/10^27 − K27/2^235 < 0, magnitude m := (K27·10^27 − 2^235)/(2^235·10^27) - have hcoeff_eq : (1 / (10 ^ 27 : Real) - K27R / N235) = - -((K27R * (10 ^ 27 : Real) - N235) / (N235 * (10 ^ 27 : Real))) := by - rw [hK27R, hN235]; field_simp; ring - have hcoeff_num : K27R * (10 ^ 27 : Real) - N235 = 222636907558699806209605632 := by - rw [hK27R, hN235]; norm_num - -- |P1| < 2⁻¹³² (a generous bound): |XR| < 2^96, |coeff| = m, and 2^96·m < 2⁻¹³². - have hP1_abs : |P1| < 1 / (64 * N128) := by - rw [hP1def, hcoeff_eq, hcoeff_num, abs_mul] - have hden_pos : (0 : Real) < N235 * (10 ^ 27 : Real) := by positivity - have hco_abs : |(-(222636907558699806209605632 / (N235 * (10 ^ 27 : Real))))| = - 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by - rw [abs_neg, abs_of_pos (by positivity)] - rw [hco_abs] - have hX_abs : |XR| < 79228162514264337593543950336 := abs_lt.mpr ⟨hXloR, hXhiR⟩ - have hco_pos : (0:Real) < 222636907558699806209605632 / (N235 * (10 ^ 27 : Real)) := by positivity - calc |XR| * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) - < 79228162514264337593543950336 * (222636907558699806209605632 / (N235 * (10 ^ 27 : Real))) := - (mul_lt_mul_right hco_pos).mpr hX_abs - _ = 79228162514264337593543950336 * 222636907558699806209605632 / - (N235 * (10 ^ 27 : Real)) := by rw [mul_div_assoc] - _ < 1 / (64 * N128) := by - rw [hN235, hN128, div_lt_div_iff₀ (by positivity) (by positivity)]; norm_num - -- bound P2 : 0 ≤ LN2R/N235 − LR... actually ln2 ≥ LN2/2^235, so LN2R/N235 − LR ≤ 0, and ≥ −1/N235. - have hP2_lo : LN2R / N235 - LR ≤ 0 := by linarith [hln2lo] - have hP2_hi : -(1 / N235) ≤ LN2R / N235 - LR := by - have : LR ≤ (LN2R + 1) / N235 := hln2hi - rw [add_div] at this; linarith [this] - -- |k| ≤ 65 ⇒ |P2| ≤ 65/N235 < 1/N128 - have hkloR : -(61 : Real) ≤ kR := by - have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hklo; rw [hkRdef]; push_cast at this; linarith [this] - have hkhiR : kR ≤ (65 : Real) := by - have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hkhi; rw [hkRdef]; push_cast at this; linarith [this] - have hP2_abs : |P2| < 1 / (64 * N128) := by - rw [hP2def] - have h1 : |kR| ≤ 65 := abs_le.mpr ⟨by linarith [hkloR], hkhiR⟩ - have h2 : |LN2R / N235 - LR| ≤ 1 / N235 := by - rw [abs_le] - refine ⟨by linarith [hP2_hi], ?_⟩ - have hpos : (0:Real) ≤ 1 / N235 := by positivity - linarith [hP2_lo, hpos] - have hbound : |kR * (LN2R / N235 - LR)| ≤ 65 * (1 / N235) := by - rw [abs_mul] - exact mul_le_mul h1 h2 (abs_nonneg _) (by norm_num) - have hlt : 65 * (1 / N235) < 1 / (64 * N128) := by - rw [hN235, hN128, mul_one_div, div_lt_div_iff₀ (by positivity) (by positivity)]; norm_num - linarith [hbound, hlt] - -- bound P3 ∈ [0, 1/N128) from the integer sandwich - have hP3int_lo : (0 : Int) ≤ 55213970774324510299478046898216203619608872 * X - - 38271408169742254668347313025622401492114385419650052359639581444463709 * k - 2 ^ 106 * t := by omega - have hP3int_hi : 55213970774324510299478046898216203619608872 * X - - 38271408169742254668347313025622401492114385419650052359639581444463709 * k - 2 ^ 106 * t < 2 ^ 106 := by omega - -- P3 = (A − 2^107·t)/N235, with the numerator (a Real cast of an Int) in [0, 2^107) - have hnumR_lo : (0 : Real) ≤ K27R * XR - LN2R * kR - 2 ^ 106 * tR := by - have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hP3int_lo - rw [hK27R, hLN2R, hXRdef, hkRdef, htRdef] - push_cast at h; linarith [h] - have hnumR_hi : K27R * XR - LN2R * kR - 2 ^ 106 * tR < 2 ^ 106 := by - have h := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hP3int_hi - rw [hK27R, hLN2R, hXRdef, hkRdef, htRdef] - push_cast at h; linarith [h] - have hP3eq : P3 = (K27R * XR - LN2R * kR - 2 ^ 106 * tR) / N235 := by - rw [hP3def, hsplit]; field_simp; ring - have hP3_lo : 0 ≤ P3 := by rw [hP3eq]; exact div_nonneg hnumR_lo (le_of_lt hp235) - have hP3_hi : P3 < 1 / N128 := by - rw [hP3eq, hsplit, div_lt_div_iff₀ (by positivity) (by positivity)] - nlinarith [hnumR_hi, hp128] - -- assemble - show |reducedArg x - tR / N128| < 9 / (8 * N128) - rw [show reducedArg x = XR / (10 ^ 27 : Real) - kR * LR from rfl] - rw [hident, abs_lt] - have hP1 := abs_lt.mp hP1_abs - have hP2 := abs_lt.mp hP2_abs - clear_value N128 N235 - -- P1+P2 < 2/(64N) = 1/(32N); P3 ∈ [0, 1/N). 9/(8N) = 36/(32N) covers 33/(32N). - have hp128' : (0 : Real) < 1 / N128 := by positivity - -- 1/(64N)+1/(64N) ≤ 1/(32N) ≤ 1/(8N) - have he12 : (1 : Real) / (64 * N128) + 1 / (64 * N128) = 1 / (32 * N128) := by - field_simp; ring - have h32_8 : (1 : Real) / (32 * N128) ≤ 1 / (8 * N128) := by - rw [div_le_div_iff₀ (by positivity) (by positivity)]; linarith [hp128] - have h1_8N : (1 : Real) / N128 + 1 / (8 * N128) = 9 / (8 * N128) := by - field_simp; ring - have hsum_hi : P1 + P2 + P3 < 9 / (8 * N128) := by - have h12 : P1 + P2 < 1 / (8 * N128) := by - have : P1 + P2 < 1 / (32 * N128) := by rw [← he12]; linarith [hP1.2, hP2.2] - linarith [this, h32_8] - rw [← h1_8N]; linarith [h12, hP3_hi] - have hsum_lo : -(9 / (8 * N128)) < P1 + P2 + P3 := by - have h12 : -(1 / (8 * N128)) < P1 + P2 := by - have hlo : -(1 / (32 * N128)) < P1 + P2 := by - rw [show -(1 / (32 * N128)) = -(1 / (64 * N128)) + -(1 / (64 * N128)) from by rw [← he12]; ring] - linarith [hP1.1, hP2.1] - linarith [hlo, h32_8] - have hneg : -(9 / (8 * N128)) < -(1 / (8 * N128)) + 0 := by - rw [← h1_8N]; linarith [hp128'] - linarith [h12, hP3_lo, hneg] - exact ⟨hsum_lo, hsum_hi⟩ + |reducedArg x - (int256 (tTree x) : Real) / (2 ^ 129 : Real)| < 9 / (8 * (2 ^ 129 : Real)) := + reducedArg_close_wide hx (wideRegion_of_wad hC hC0) /-- info: 'ExpYul.reducedArg_close' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in diff --git a/formal/exp/ExpProof/ExpProof/Floor/TBound.lean b/formal/exp/ExpProof/ExpProof/Floor/TBound.lean index eb50d676a..5714a9c4d 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/TBound.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/TBound.lean @@ -6,7 +6,7 @@ import Mathlib.Tactic.IntervalCases The reduced-argument Taylor caps (`Floor.CapsV`) are certified over `t ∈ [0, H129]` with `H129 = ⌊ln2/2 · 2¹²⁸⌋`. To instantiate them at the runtime reduced argument `t = tTree x` we -need `|tTree x| ≤ H129` on the meaningful region. +need `|tTree x| ≤ H129` on the wide region. This is an integer-`k` fact: a real linear-program relaxation of the octave/reduced-argument sandwiches is unbounded (it decouples `k` from `x`), but the *integer* @@ -22,22 +22,21 @@ open FormalYul open FormalYul.Preservation set_option maxRecDepth 100000 +set_option maxHeartbeats 1600000 -/-- On the meaningful region the reduced argument lands in the certificate domain: +/-- On the wide region the reduced argument lands in the certificate domain: `-H129 ≤ tTree x ≤ H129` (as signed integers), where `H129 = ⌊ln2/2 · 2¹²⁸⌋`. -/ -theorem tTree_in_cert_domain {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem tTree_in_cert_domain_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : -(235865763225513294137944142764154484399 : Int) ≤ int256 (tTree x) ∧ int256 (tTree x) ≤ 235865763225513294137944142764154484399 := by - obtain ⟨htlo, hthi⟩ := tTree_sandwich hx hC hC0 - obtain ⟨hklo, hkhi⟩ := kTree_sandwich hx hC hC0 - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 - obtain ⟨hkblo, hkbhi⟩ := kTree_bound hx hC hC0 + obtain ⟨htlo, hthi⟩ := tTree_sandwich_wide hx hW + obtain ⟨hklo, hkhi⟩ := kTree_sandwich_wide hx hW + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW + obtain ⟨hkblo, hkbhi⟩ := kTree_bound_wide hx hW + obtain ⟨hC, hC0⟩ := hW -- region endpoints as decimals - have hCi : int256 Cmask = -41446531673892822312323846185 := int256_Cmask - have hC0i : int256 C0thresh = 45401140326676417766828703956 := int256_C0thresh - rw [hCi] at hC - rw [hC0i] at hC0 + rw [int256_mulExpRayZeroMax] at hC + rw [int256_mulExpRayHi] at hC0 -- constants as decimals have hK27 : (0x279d346de4781f921dd7a89933d54d1f72928 : Int) = 55213970774324510299478046898216203619608872 := by norm_num @@ -56,15 +55,20 @@ theorem tTree_in_cert_domain {x : Nat} (hx : x < 2 ^ 256) 3138550867693340381917894711603833208051177722232017256448 := by norm_num have p200 : (2 : Int) ^ 192 = 6277101735386680763835789423207666416102355444464034512896 := by norm_num - have pH : (235865763225513294137944142764154484399 : Int) = - 235865763225513294137944142764154484399 := rfl rw [p106] at htlo hthi rw [p199, p200] at hklo hkhi clear_value k - -- For each fixed integer octave index `k ∈ [−61, 65]` the band of consistent `x` together with - -- the reduction sandwich pins `t` to the cert domain; `omega` closes each band (the coupling is - -- linear in `x` and `t` once `k` is a literal). - clear htdef hXdef hkdef hCi hC0i hK27 hLN2 hCINV pH p106 p199 p200 hx hxlo hxhi + -- For each fixed integer octave index `k ∈ [−127, 125]` the band of consistent `x` together + -- with the reduction sandwich pins `t` to the cert domain; `omega` closes each band (the + -- coupling is linear in `x` and `t` once `k` is a literal). + clear htdef hXdef hkdef hK27 hLN2 hCINV p106 p199 p200 hx hxlo hxhi interval_cases k <;> constructor <;> omega +/-- The meaningful-region instance of `tTree_in_cert_domain_wide`. -/ +theorem tTree_in_cert_domain {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + -(235865763225513294137944142764154484399 : Int) ≤ int256 (tTree x) ∧ + int256 (tTree x) ≤ 235865763225513294137944142764154484399 := + tTree_in_cert_domain_wide hx (wideRegion_of_wad hC hC0) + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/Octave.lean b/formal/exp/ExpProof/ExpProof/Mono/Octave.lean index c4ec42c56..07b3a1818 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Octave.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Octave.lean @@ -3,14 +3,17 @@ import ExpProof.Mono.Tree /-! # Octave-index and reduced-argument transports -On the meaningful region the input word `x` (canonical, `< 2^256`) has signed value in -`(C, C0) ⊂ (−2^96, 2^96)`. This file transports the first two kernel stages — the octave index -`k = round(x/(10²⁷·ln2))` and the reduced argument `t` — to closed `Int` forms via the no-overflow -bounds, and proves `k` is nondecreasing in `int256 x` and (for a fixed `k`) `t` is nondecreasing in -`int256 x`. +On the wide region the input word `x` (canonical, `< 2^256`) has signed value strictly between the +`mulExpRay` zero clamp and its overflow guard, `(zeroMax, hi) ⊂ (−2^97, 2^97)`. This file +transports the first two kernel stages — the octave index `k = round(x/(10²⁷·ln2))` and the +reduced argument `t` — to closed `Int` forms via the no-overflow bounds, and proves `k` is +nondecreasing in `int256 x` and (for a fixed `k`) `t` is nondecreasing in `int256 x`. + +The `expRayToWad` meaningful region `(Cmask, C0thresh)` is strictly inside the wide region, so +every transport specializes to it; the wad-named lemmas below are those instances. Constants and their bit widths (so every product stays below `2^255`): -`CINV` 111 bits, `K27` 146 bits, `LN2` 235 bits, `|int256 x| < 2^96`, `k ∈ [-61, 64]`. +`CINV` 111 bits, `K27` 146 bits, `LN2` 235 bits, `|int256 x| < 2^97`, `k ∈ [-127, 125]`. -/ namespace ExpYul @@ -20,6 +23,26 @@ open FormalYul.Preservation set_option maxRecDepth 100000 +/-- The `mulExpRay` live region: strictly between the zero clamp and the overflow guard. -/ +abbrev WideRegion (x : Nat) : Prop := + int256 mulExpRayZeroMax < int256 x ∧ int256 x < int256 mulExpRayHi + +/-- The `expRayToWad` meaningful region is contained in the wide region. -/ +theorem wideRegion_of_wad {x : Nat} (hC : int256 Cmask < int256 x) + (hC0 : int256 x < int256 C0thresh) : WideRegion x := by + rw [int256_Cmask] at hC + rw [int256_C0thresh] at hC0 + exact ⟨by rw [int256_mulExpRayZeroMax]; omega, by rw [int256_mulExpRayHi]; omega⟩ + +/-- The signed value of `x` on the wide region is bounded by `2^97`. -/ +theorem region_x_bound_wide {x : Nat} (hW : WideRegion x) : + -(2 ^ 97 : Int) < int256 x ∧ int256 x < 2 ^ 97 := by + obtain ⟨hlo, hhi⟩ := hW + rw [int256_mulExpRayZeroMax] at hlo + rw [int256_mulExpRayHi] at hhi + constructor <;> [skip; skip] <;> + simp only [show (2:Int)^97 = 158456325028528675187087900672 from by norm_num] <;> omega + /-- The signed value of `x` on the meaningful region is bounded by `2^96`. -/ theorem region_x_bound {x : Nat} (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : @@ -53,24 +76,22 @@ theorem evmShl_bf_one : evmShl 0xbf 1 = 2 ^ 191 := by /-! ## The octave index `k` -/ /-- The argument of the rounding shift, transported to `Int`: `2^191 + CINV · int256 x`. -/ -theorem int256_kArg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem int256_kArg_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) = 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x := by - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 - have hx96 : (-(2 ^ 96 : Int)) < int256 x ∧ int256 x < 2 ^ 96 := ⟨hxlo, hxhi⟩ - have hb96 : (2 : Int) ^ 96 = 79228162514264337593543950336 := by norm_num + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW + have hb97 : (2 : Int) ^ 97 = 158456325028528675187087900672 := by norm_num -- the product `CINV * int256 x` fits have hmul : int256 (evmMul 0x724d54edbacbebbb95c52a0f60 x) = 0x724d54edbacbebbb95c52a0f60 * int256 x := by rw [evmMul_transport (by norm_num) hx ?_ ?_, int256_CINV] · rw [int256_CINV] - simp only [hb96] at hxlo hxhi + simp only [hb97] at hxlo hxhi have : -(2 ^ 255 : Int) ≤ 0x724d54edbacbebbb95c52a0f60 * int256 x := by simp only [ipow255]; nlinarith [hxlo, hxhi] exact this · rw [int256_CINV] - simp only [hb96] at hxlo hxhi + simp only [hb97] at hxlo hxhi simp only [ipow255]; nlinarith [hxlo, hxhi] have hshl : evmShl 0xbf 1 = 2 ^ 191 := evmShl_bf_one rw [hshl] @@ -83,36 +104,48 @@ theorem int256_kArg {x : Nat} (hx : x < 2 ^ 256) · rw [hmul] have h199 : int256 (2 ^ 191 : Nat) = (2 ^ 191 : Int) := by rw [int256_of_lt (by norm_num)]; norm_num - rw [h199]; simp only [hb96, ipow255] at *; nlinarith [hxlo, hxhi] + rw [h199]; simp only [hb97, ipow255] at *; nlinarith [hxlo, hxhi] · rw [hmul] have h199 : int256 (2 ^ 191 : Nat) = (2 ^ 191 : Int) := by rw [int256_of_lt (by norm_num)]; norm_num - rw [h199]; simp only [hb96, ipow255] at *; nlinarith [hxlo, hxhi] + rw [h199]; simp only [hb97, ipow255] at *; nlinarith [hxlo, hxhi] + +theorem int256_kArg {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + int256 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) = + 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x := + int256_kArg_wide hx (wideRegion_of_wad hC hC0) /-- The argument of the `k`-rounding shift is a valid word (so the sandwich applies). -/ theorem kArg_lt {x : Nat} : evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x) < 2 ^ 256 := evmAdd_lt _ _ -/-- The `k`-floor sandwich on the meaningful region: `2^192·k ≤ 2^191 + CINV·x < 2^192·k + 2^192`. -/ -theorem kTree_sandwich {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +/-- The `k`-floor sandwich on the wide region: `2^192·k ≤ 2^191 + CINV·x < 2^192·k + 2^192`. -/ +theorem kTree_sandwich_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (2 ^ 192 : Int) * int256 (kTree x) ≤ 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x ∧ 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x < (2 ^ 192 : Int) * int256 (kTree x) + 2 ^ 192 := by unfold kTree obtain ⟨_, hlo, hhi⟩ := evmSar_sandwich (s := 0xc0) (by norm_num) (kArg_lt (x := x)) - rw [int256_kArg hx hC hC0] at hlo hhi + rw [int256_kArg_wide hx hW] at hlo hhi exact ⟨by simpa using hlo, by simpa using hhi⟩ -/-- `k` is nondecreasing in the signed input across the meaningful region. -/ -theorem kTree_mono {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) - (hC1 : int256 Cmask < int256 x1) (hle : int256 x1 ≤ int256 x2) - (hC02 : int256 x2 < int256 C0thresh) : +theorem kTree_sandwich {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (2 ^ 192 : Int) * int256 (kTree x) ≤ 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x ∧ + 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x < + (2 ^ 192 : Int) * int256 (kTree x) + 2 ^ 192 := + kTree_sandwich_wide hx (wideRegion_of_wad hC hC0) + +/-- `k` is nondecreasing in the signed input across the wide region. -/ +theorem kTree_mono_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1lo : int256 mulExpRayZeroMax < int256 x1) (hle : int256 x1 ≤ int256 x2) + (hW2hi : int256 x2 < int256 mulExpRayHi) : int256 (kTree x1) ≤ int256 (kTree x2) := by - have hC2 : int256 Cmask < int256 x2 := lt_of_lt_of_le hC1 hle - have hC01 : int256 x1 < int256 C0thresh := lt_of_le_of_lt hle hC02 - obtain ⟨hlo1, hhi1⟩ := kTree_sandwich hx1 hC1 hC01 - obtain ⟨hlo2, hhi2⟩ := kTree_sandwich hx2 hC2 hC02 + have hW1 : WideRegion x1 := ⟨hW1lo, lt_of_le_of_lt hle hW2hi⟩ + have hW2 : WideRegion x2 := ⟨lt_of_lt_of_le hW1lo hle, hW2hi⟩ + obtain ⟨hlo1, hhi1⟩ := kTree_sandwich_wide hx1 hW1 + obtain ⟨hlo2, hhi2⟩ := kTree_sandwich_wide hx2 hW2 -- kArg increases with int256 x (CINV > 0), and floor is monotone. have hcinv : (0 : Int) < 0x724d54edbacbebbb95c52a0f60 := by norm_num have hargle : 2 ^ 191 + 0x724d54edbacbebbb95c52a0f60 * int256 x1 ≤ @@ -123,6 +156,36 @@ theorem kTree_mono {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) have hpow : (0 : Int) < 2 ^ 192 := by norm_num nlinarith [hlo1, hhi2, hargle, hpow] +theorem kTree_mono {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hC1 : int256 Cmask < int256 x1) (hle : int256 x1 ≤ int256 x2) + (hC02 : int256 x2 < int256 C0thresh) : + int256 (kTree x1) ≤ int256 (kTree x2) := by + refine kTree_mono_wide hx1 hx2 ?_ hle ?_ + · rw [int256_mulExpRayZeroMax]; rw [int256_Cmask] at hC1; omega + · rw [int256_mulExpRayHi]; rw [int256_C0thresh] at hC02; omega + +/-- On the wide region the octave index is bounded: `-127 ≤ k ≤ 125`. The endpoints are exact: +the zero clamp sits at the least input whose octave count reaches `-127`, and the overflow guard +at the least input whose octave count reaches `126`. -/ +theorem kTree_bound_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : + -127 ≤ int256 (kTree x) ∧ int256 (kTree x) ≤ 125 := by + obtain ⟨hlo, hhi⟩ := kTree_sandwich_wide hx hW + obtain ⟨hC, hC0⟩ := hW + rw [int256_mulExpRayZeroMax] at hC + rw [int256_mulExpRayHi] at hC0 + have hcinv : (0x724d54edbacbebbb95c52a0f60 : Int) = 9055943544797870567083544809312 := by + norm_num + -- bound the rounding-shift argument from the exact region endpoints. + have hprod_lo : (0x724d54edbacbebbb95c52a0f60 : Int) * int256 x > + 0x724d54edbacbebbb95c52a0f60 * (-88376265521393026950697095485) := by + rw [hcinv]; nlinarith [hC] + have hprod_hi : (0x724d54edbacbebbb95c52a0f60 : Int) * int256 x < + 0x724d54edbacbebbb95c52a0f60 * 86989971160273136331862631244 := by + rw [hcinv]; nlinarith [hC0] + constructor + · nlinarith [hhi, hprod_lo] + · nlinarith [hlo, hprod_hi] + /-- On the meaningful region the octave index is bounded: `-61 ≤ k ≤ 65`. -/ theorem kTree_bound {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : @@ -149,24 +212,22 @@ theorem kTree_bound {x : Nat} (hx : x < 2 ^ 256) /-- The argument of the `t`-reduction shift, transported to `Int`: `K27 · int256 x − LN2 · int256 k`. -/ -theorem int256_tArg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem int256_tArg_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d (kTree x))) = 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x - 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d * int256 (kTree x) := by - have hCi : int256 Cmask = -41446531673892822312323846185 := int256_Cmask - have hC0i : int256 C0thresh = 45401140326676417766828703956 := int256_C0thresh - have hxr := hC; rw [hCi] at hxr - have hxr0 := hC0; rw [hC0i] at hxr0 - obtain ⟨hklo, hkhi⟩ := kTree_bound hx hC hC0 + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW + have hb97 : (2 : Int) ^ 97 = 158456325028528675187087900672 := by norm_num + rw [hb97] at hxlo hxhi + obtain ⟨hklo, hkhi⟩ := kTree_bound_wide hx hW have hk256 : kTree x < 2 ^ 256 := by unfold kTree; exact evmSar_lt _ _ -- transport the two products. have hmul1 : int256 (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) = 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x := by rw [evmMul_transport (by norm_num) hx ?_ ?_, int256_K27] - · rw [int256_K27]; simp only [ipow255]; nlinarith [hxr, hxr0] - · rw [int256_K27]; simp only [ipow255]; nlinarith [hxr, hxr0] + · rw [int256_K27]; simp only [ipow255]; nlinarith [hxlo, hxhi] + · rw [int256_K27]; simp only [ipow255]; nlinarith [hxlo, hxhi] have hmul2 : int256 (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d (kTree x)) = 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d * int256 (kTree x) := by @@ -174,8 +235,16 @@ theorem int256_tArg {x : Nat} (hx : x < 2 ^ 256) · rw [int256_LN2]; simp only [ipow255]; nlinarith [hklo, hkhi] · rw [int256_LN2]; simp only [ipow255]; nlinarith [hklo, hkhi] rw [evmSub_transport (evmMul_lt _ _) (evmMul_lt _ _) ?_ ?_, hmul1, hmul2] - · rw [hmul1, hmul2]; simp only [ipow255]; nlinarith [hxr, hxr0, hklo, hkhi] - · rw [hmul1, hmul2]; simp only [ipow255]; nlinarith [hxr, hxr0, hklo, hkhi] + · rw [hmul1, hmul2]; simp only [ipow255]; nlinarith [hxlo, hxhi, hklo, hkhi] + · rw [hmul1, hmul2]; simp only [ipow255]; nlinarith [hxlo, hxhi, hklo, hkhi] + +theorem int256_tArg {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + int256 (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d (kTree x))) = + 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x - + 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d * int256 (kTree x) := + int256_tArg_wide hx (wideRegion_of_wad hC hC0) /-- The `t`-reduction shift argument is a valid word. -/ theorem tArg_lt {x : Nat} : @@ -184,8 +253,7 @@ theorem tArg_lt {x : Nat} : < 2 ^ 256 := evmSub_lt _ _ /-- `t = sar(106, tArg)` floor sandwich: `2^106·t ≤ K27·x − LN2·k < 2^106·t + 2^106`. -/ -theorem tTree_sandwich {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem tTree_sandwich_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (2 ^ 106 : Int) * int256 (tTree x) ≤ 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x - 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d * int256 (kTree x) ∧ @@ -194,18 +262,27 @@ theorem tTree_sandwich {x : Nat} (hx : x < 2 ^ 256) (2 ^ 106 : Int) * int256 (tTree x) + 2 ^ 106 := by unfold tTree obtain ⟨_, hlo, hhi⟩ := evmSar_sandwich (s := 0x6a) (by norm_num) (tArg_lt (x := x)) - rw [int256_tArg hx hC hC0] at hlo hhi + rw [int256_tArg_wide hx hW] at hlo hhi exact ⟨by simpa using hlo, by simpa using hhi⟩ +theorem tTree_sandwich {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (2 ^ 106 : Int) * int256 (tTree x) ≤ + 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x - + 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d * int256 (kTree x) ∧ + 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x - + 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d * int256 (kTree x) < + (2 ^ 106 : Int) * int256 (tTree x) + 2 ^ 106 := + tTree_sandwich_wide hx (wideRegion_of_wad hC hC0) + /-- Within a fixed octave (`k` constant), `t` is nondecreasing in the signed input (`K27 > 0`, and the floor of an increasing affine map is monotone). -/ -theorem tTree_mono_sameOctave {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) - (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) - (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) +theorem tTree_mono_sameOctave_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hk : int256 (kTree x1) = int256 (kTree x2)) (hle : int256 x1 ≤ int256 x2) : int256 (tTree x1) ≤ int256 (tTree x2) := by - obtain ⟨hlo1, hhi1⟩ := tTree_sandwich hx1 hC1 hC01 - obtain ⟨hlo2, hhi2⟩ := tTree_sandwich hx2 hC2 hC02 + obtain ⟨hlo1, hhi1⟩ := tTree_sandwich_wide hx1 hW1 + obtain ⟨hlo2, hhi2⟩ := tTree_sandwich_wide hx2 hW2 rw [hk] at hlo1 hhi1 have hk27 : (0 : Int) < 0x279d346de4781f921dd7a89933d54d1f72928 := by norm_num have hargle : 0x279d346de4781f921dd7a89933d54d1f72928 * int256 x1 - @@ -217,4 +294,12 @@ theorem tTree_mono_sameOctave {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ have hpow : (0 : Int) < 2 ^ 106 := by norm_num nlinarith [hlo1, hhi2, hargle, hpow] +theorem tTree_mono_sameOctave {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) + (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) + (hk : int256 (kTree x1) = int256 (kTree x2)) (hle : int256 x1 ≤ int256 x2) : + int256 (tTree x1) ≤ int256 (tTree x2) := + tTree_mono_sameOctave_wide hx1 hx2 (wideRegion_of_wad hC1 hC01) (wideRegion_of_wad hC2 hC02) + hk hle + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean index 522af4739..72120c1c7 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean @@ -37,14 +37,13 @@ theorem int256_eq_of_nonneg {w : Nat} (hw : w < 2 ^ 256) (hnn : 0 ≤ int256 w) /-- `tod` transported to `Int`: a signed floor with `|tod| < 2^126`. The product `t·Od` fits a word (`|t| < 2.4·10³⁸`, `Od < 5·2^125`, so `|t·Od| < 29·2^250`). -/ -theorem todTree_bound {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem todTree_bound_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : -(2 ^ 126 : Int) ≤ int256 (todTree x) ∧ int256 (todTree x) < 2 ^ 126 ∧ (2 ^ 129 : Int) * int256 (todTree x) ≤ int256 (tTree x) * (odTree x : Int) ∧ int256 (tTree x) * (odTree x : Int) < (2 ^ 129 : Int) * int256 (todTree x) + 2 ^ 129 := by - obtain ⟨htlo, hthi⟩ := tTree_bound_sharp hx hC hC0 - obtain ⟨_, hvlt⟩ := vTree_eq hx hC hC0 + obtain ⟨htlo, hthi⟩ := tTree_bound_sharp_wide hx hW + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW have hodlt : odTree x < 5 * 2 ^ 125 := odTree_lt hvlt have htw : tTree x < 2 ^ 256 := by unfold tTree; exact evmSar_lt _ _ have hodw : odTree x < 2 ^ 256 := by unfold odTree; exact evmAdd_lt _ _ @@ -85,6 +84,14 @@ theorem todTree_bound {x : Nat} (hx : x < 2 ^ 256) · -- upper bound: t·od < 2^129·tod + 2^129 and t·od < 29·2^250 ⇒ tod < 2^126 nlinarith [hsh, hprod_lt, hp252] +theorem todTree_bound {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + -(2 ^ 126 : Int) ≤ int256 (todTree x) ∧ int256 (todTree x) < 2 ^ 126 ∧ + (2 ^ 129 : Int) * int256 (todTree x) ≤ int256 (tTree x) * (odTree x : Int) ∧ + int256 (tTree x) * (odTree x : Int) < + (2 ^ 129 : Int) * int256 (todTree x) + 2 ^ 129 := + todTree_bound_wide hx (wideRegion_of_wad hC hC0) + /-! ## Numerator and denominator -/ /-- Abstract numerator/denominator positivity: stated over opaque words `E` (the even accumulator) @@ -119,15 +126,14 @@ theorem numden_pos_of {E TD : Nat} (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) /-- `num = ev + tod` and `den = ev − tod`, transported to `Int`, are both strictly positive: the even accumulator dominates `|tod|`. -/ -theorem numden_pos {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem numden_pos_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (evmAdd (evTree x) (todTree x)) = (evTree x : Int) + int256 (todTree x) ∧ int256 (evmSub (evTree x) (todTree x)) = (evTree x : Int) - int256 (todTree x) ∧ 0 < (evTree x : Int) + int256 (todTree x) ∧ 0 < (evTree x : Int) - int256 (todTree x) := by - obtain ⟨_, hvlt⟩ := vTree_eq hx hC hC0 + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW obtain ⟨hev_lo, hev_hi⟩ := evTree_facts hvlt - obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound hx hC hC0 + obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound_wide hx hW have hevw : evTree x < 2 ^ 256 := by unfold evTree; exact evmAdd_lt _ _ have htodw : todTree x < 2 ^ 256 := by unfold todTree; exact evmSar_lt _ _ refine numden_pos_of hevw htodw ?_ ?_ ?_ ?_ @@ -139,6 +145,14 @@ theorem numden_pos {x : Nat} (hx : x < 2 ^ 256) · rw [show (85070591730234615865843651857942052864 : Int) = 2 ^ 126 by norm_num]; exact htod_lo · rw [show (85070591730234615865843651857942052864 : Int) = 2 ^ 126 by norm_num]; exact htod_hi +theorem numden_pos {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + int256 (evmAdd (evTree x) (todTree x)) = (evTree x : Int) + int256 (todTree x) ∧ + int256 (evmSub (evTree x) (todTree x)) = (evTree x : Int) - int256 (todTree x) ∧ + 0 < (evTree x : Int) + int256 (todTree x) ∧ + 0 < (evTree x : Int) - int256 (todTree x) := + numden_pos_wide hx (wideRegion_of_wad hC hC0) + /-! ## The runtime quotient `r0 = ⌊(10¹⁸·2⁶⁷)·num/den⌋` -/ /-- Abstract scaled-quotient bounds over opaque numerator/denominator words: `⌊scaleQ67·N/D⌋` diff --git a/formal/exp/ExpProof/ExpProof/Mono/RegionMono.lean b/formal/exp/ExpProof/ExpProof/Mono/RegionMono.lean index c35ce06b1..9b1afea36 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/RegionMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/RegionMono.lean @@ -17,14 +17,13 @@ open FormalYul.Preservation set_option maxRecDepth 100000 /-- The octave index advances by `0` or `1` per unit input step (`CINV ≪ 2^192`). -/ -theorem kTree_step {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) - (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) - (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) +theorem kTree_step_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hadj : int256 x2 = int256 x1 + 1) : int256 (kTree x2) = int256 (kTree x1) ∨ int256 (kTree x2) = int256 (kTree x1) + 1 := by - obtain ⟨hlo1, hhi1⟩ := kTree_sandwich hx1 hC1 hC01 - obtain ⟨hlo2, hhi2⟩ := kTree_sandwich hx2 hC2 hC02 - have hmono := kTree_mono hx1 hx2 hC1 (by omega) hC02 + obtain ⟨hlo1, hhi1⟩ := kTree_sandwich_wide hx1 hW1 + obtain ⟨hlo2, hhi2⟩ := kTree_sandwich_wide hx2 hW2 + have hmono := kTree_mono_wide hx1 hx2 hW1.1 (by omega) hW2.2 -- the rounding argument advances by exactly `CINV < 2^192` set k1 := int256 (kTree x1) set k2 := int256 (kTree x2) @@ -40,6 +39,13 @@ theorem kTree_step {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) have hupper : k2 < k1 + 2 := by nlinarith [hlo2, hhi1, hcinv, hp200] omega +theorem kTree_step {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) + (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (kTree x2) = int256 (kTree x1) ∨ int256 (kTree x2) = int256 (kTree x1) + 1 := + kTree_step_wide hx1 hx2 (wideRegion_of_wad hC1 hC01) (wideRegion_of_wad hC2 hC02) hadj + /-- **The octave-seam step** (`k` advances by one): `r1Tree` is nondecreasing across the boundary. The accumulators are still nearly constant (`v_a ≈ v_b`), the reduced argument flips sign (`t_b ≈ −t_a`), and the closing shift loses one bit, so `r1Tree x1 ≤ r1Tree x2`. Carried as an diff --git a/formal/exp/ExpProof/ExpProof/Mono/Stages.lean b/formal/exp/ExpProof/ExpProof/Mono/Stages.lean index a24044720..f60227a54 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Stages.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Stages.lean @@ -28,18 +28,17 @@ set_option maxRecDepth 100000 /-! ## The reduced-argument bound `|t| < 2^128` -/ -/-- On the meaningful region the reduced argument is bounded: `-2^128 < int256 (tTree x) < 2^128`. +/-- On the wide region the reduced argument is bounded: `-2^128 < int256 (tTree x) < 2^128`. The octave reduction couples `k` to `x` (`2^192·k ≈ CINV·x`), so the residual `K27·x − LN2·k` stays inside `±ln2/2·2^235`, leaving `|t| < ln2/2·2^129 < 2^128`. -/ -theorem tTree_bound {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem tTree_bound_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : -(2 ^ 128 : Int) < int256 (tTree x) ∧ int256 (tTree x) < 2 ^ 128 := by - obtain ⟨htlo, hthi⟩ := tTree_sandwich hx hC hC0 - obtain ⟨hklo, hkhi⟩ := kTree_sandwich hx hC hC0 - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 + obtain ⟨htlo, hthi⟩ := tTree_sandwich_wide hx hW + obtain ⟨hklo, hkhi⟩ := kTree_sandwich_wide hx hW + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW -- numeric forms - have hb96 : (2 : Int) ^ 96 = 79228162514264337593543950336 := by norm_num - rw [hb96] at hxlo hxhi + have hb97 : (2 : Int) ^ 97 = 158456325028528675187087900672 := by norm_num + rw [hb97] at hxlo hxhi -- constants as decimal have hK27 : (0x279d346de4781f921dd7a89933d54d1f72928 : Int) = 55213970774324510299478046898216203619608872 := by norm_num @@ -108,19 +107,23 @@ theorem tTree_bound {x : Nat} (hx : x < 2 ^ 256) · nlinarith [htlo', hthi', hklo', hkhi', hxlo, hxhi] · nlinarith [htlo', hthi', hklo', hkhi', hxlo, hxhi] -/-- The sharper reduced-argument bound `|t| < 1.2·10^38`: the true envelope is -`ln2/2 · 2^128 ≈ 1.1793·10^38`, and this relaxation still squares below `2^253`, which is what the +theorem tTree_bound {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + -(2 ^ 128 : Int) < int256 (tTree x) ∧ int256 (tTree x) < 2 ^ 128 := + tTree_bound_wide hx (wideRegion_of_wad hC hC0) + +/-- The sharper reduced-argument bound `|t| < 2.4·10^38`: the true envelope is +`ln2/2 · 2^129 ≈ 2.3587·10^38`, and this relaxation still squares below `2^253`, which is what the Q123 square and the monic-stage multiply safety need. Same sandwich elimination as `tTree_bound`, closed against the sharper literal. -/ -theorem tTree_bound_sharp {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem tTree_bound_sharp_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : -(240000000000000000000000000000000000000 : Int) < int256 (tTree x) ∧ int256 (tTree x) < 240000000000000000000000000000000000000 := by - obtain ⟨htlo, hthi⟩ := tTree_sandwich hx hC hC0 - obtain ⟨hklo, hkhi⟩ := kTree_sandwich hx hC hC0 - obtain ⟨hxlo, hxhi⟩ := region_x_bound hC hC0 - have hb96 : (2 : Int) ^ 96 = 79228162514264337593543950336 := by norm_num - rw [hb96] at hxlo hxhi + obtain ⟨htlo, hthi⟩ := tTree_sandwich_wide hx hW + obtain ⟨hklo, hkhi⟩ := kTree_sandwich_wide hx hW + obtain ⟨hxlo, hxhi⟩ := region_x_bound_wide hW + have hb97 : (2 : Int) ^ 97 = 158456325028528675187087900672 := by norm_num + rw [hb97] at hxlo hxhi have hK27 : (0x279d346de4781f921dd7a89933d54d1f72928 : Int) = 55213970774324510299478046898216203619608872 := by norm_num have hLN2 : (0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d : Int) = @@ -182,14 +185,19 @@ theorem tTree_bound_sharp {x : Nat} (hx : x < 2 ^ 256) · nlinarith [htlo', hthi', hklo', hkhi', hxlo, hxhi] · nlinarith [htlo', hthi', hklo', hkhi', hxlo, hxhi] +theorem tTree_bound_sharp {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + -(240000000000000000000000000000000000000 : Int) < int256 (tTree x) ∧ + int256 (tTree x) < 240000000000000000000000000000000000000 := + tTree_bound_sharp_wide hx (wideRegion_of_wad hC hC0) + /-! ## `v = t²` in Q123 -/ /-- The Q123 square `v = ⌊t²/2^135⌋` as a `Nat`: nonnegative, and `< 2^120`. The shift argument `t·t` fits in a word because `|t| < 2.4·10^38` gives `t² < 2^255`. -/ -theorem vTree_eq {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem vTree_eq_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (vTree x : Int) = (int256 (tTree x))^2 / 2 ^ 135 ∧ vTree x < 2 ^ 120 := by - obtain ⟨htlo, hthi⟩ := tTree_bound_sharp hx hC hC0 + obtain ⟨htlo, hthi⟩ := tTree_bound_sharp_wide hx hW have htw : tTree x < 2 ^ 256 := by unfold tTree; exact evmSar_lt _ _ -- the signed square equals the unsigned product of the canonical word with itself set t := int256 (tTree x) with htdef @@ -230,6 +238,11 @@ theorem vTree_eq {x : Nat} (hx : x < 2 ^ 256) rw [Nat.pow_div (by norm_num) (by norm_num)] omega +theorem vTree_eq {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (vTree x : Int) = (int256 (tTree x))^2 / 2 ^ 135 ∧ vTree x < 2 ^ 120 := + vTree_eq_wide hx (wideRegion_of_wad hC hC0) + /-! ## Exact word arithmetic when the operands fit -/ /-- `evmAdd` is ordinary addition when the sum fits in a word. -/ From 49721f2e2f9e6bfa091131834cf4715e9dfa5dbc Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 10:44:08 +0200 Subject: [PATCH 067/107] Carry the exp per-point brackets on the wide region The r0-vs-exp bridge (both sides), the granularity pair, and the runtime quotient bounds now take the mulExpRay live region directly: every lemma in Floor/R0Exp.lean, Floor/R0ExpUnder.lean, and Floor/GranPair.lean consumes WideRegion through the widened reduction anchors, with the scale still the wad literal. The certificates are untouched: the per-point budgets depend only on the reduced argument's cert domain, which the widened anchors preserve. The externally consumed conclusions (r0_real_over_within, r0_real_under_within, r0_seam_double, r0Tree_bounds) keep wad-signature instances by domain inclusion, so the expRayToWad floor brackets consume them unchanged. Co-Authored-By: Claude Fable 5 --- .../exp/ExpProof/ExpProof/Floor/GranPair.lean | 18 +- formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean | 208 +++++++++--------- .../ExpProof/ExpProof/Floor/R0ExpUnder.lean | 115 +++++----- formal/exp/ExpProof/ExpProof/Mono/Quot.lean | 14 +- 4 files changed, 189 insertions(+), 166 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/GranPair.lean b/formal/exp/ExpProof/ExpProof/Floor/GranPair.lean index a9d0dc6f8..62cc9038a 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/GranPair.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/GranPair.lean @@ -30,7 +30,7 @@ noncomputable section and the grid rational exceeds the cert rational by at most one `K`-step: `2¹²⁶·(ê(v) − ê(t²)) ≤ 3290521163436398582/10¹⁹` (the piecewise-certified envelope). -/ theorem gran_over_pair {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (evalPoly ExpCertV.numExpV (int256 (tTree x)) : Real) / (evalPoly ExpCertV.denExpV (int256 (tTree x)) : Real) ≤ @@ -40,10 +40,10 @@ theorem gran_over_pair {x : Nat} (hx : x < 2 ^ 256) (2 ^ 126 : Real) * ((evalPoly ExpCertV.numExpV (int256 (tTree x)) : Real) / (evalPoly ExpCertV.denExpV (int256 (tTree x)) : Real)) + 3290521163436398582 / 10000000000000000000 := by - obtain ⟨htie1, htie2⟩ := tie_over hx hC hC0 htnn - obtain ⟨T, DO, DU, Khi, hpiece, hT2⟩ := piece_select hx hC hC0 + obtain ⟨htie1, htie2⟩ := tie_over_wide hx hW htnn + obtain ⟨T, DO, DU, Khi, hpiece, hT2⟩ := piece_select_wide hx hW obtain ⟨hDOpos, _, hKhinn, hTnn, hflO, hflO1, _, _, hK, hbudO, _⟩ := hpiece - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef have htdom : t ≤ (ExpCertV.H129 : Int) := by @@ -158,7 +158,7 @@ the cert rational exceeds the grid rational — `Mp`-factor `2¹³¹/(2¹³¹− one-grain lift is monotone in `|t|` (the sign condition is the over-half denominator floor), so each piece's `t = −T` denominator floor applies for every `t` in the half. -/ theorem gran_under_pair {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnp : int256 (tTree x) ≤ 0) : (NUMv (vTree x) (int256 (tTree x)) : Real) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ (evalPoly ExpCertV.numExpV (int256 (tTree x)) : Real) / @@ -168,11 +168,11 @@ theorem gran_under_pair {x : Nat} (hx : x < 2 ^ 256) (evalPoly ExpCertV.denExpV (int256 (tTree x)) : Real) - (NUMv (vTree x) (int256 (tTree x)) : Real) / (DENv (vTree x) (int256 (tTree x)) : Real)) ≤ 1644901622230542074 / 10000000000000000000 := by - obtain ⟨htie1, htie2⟩ := tie_under hx hC hC0 htnp - obtain ⟨T, DO, DU, Khi, hpiece, hT2⟩ := piece_select hx hC hC0 + obtain ⟨htie1, htie2⟩ := tie_under_wide hx hW htnp + obtain ⟨T, DO, DU, Khi, hpiece, hT2⟩ := piece_select_wide hx hW obtain ⟨hDOpos, hDUpos, hKhinn, hTnn, hflO, hflO1, hflU, hflU1, hK, _, hbudU⟩ := hpiece - obtain ⟨htlo, _⟩ := tTree_in_cert_domain hx hC hC0 - have hvle := vTree_le_vmax hx hC hC0 + obtain ⟨htlo, _⟩ := tTree_in_cert_domain_wide hx hW + have hvle := vTree_le_vmax_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef have htdom : -t ≤ (ExpCertV.H129 : Int) := by diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean index 3466e63c9..0218b91c4 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean @@ -45,12 +45,12 @@ set_option exponentiation.threshold 2000 /-- The scaled quotient is the integer floor: `r0·den_rt ≤ scaleQ67·num_rt < (r0+1)·den_rt` with `num_rt = ev + tod`, `den_rt = ev − tod`. -/ theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : int256 (r0Tree x) * ((evTree x : Int) - int256 (todTree x)) ≤ (0x6f05b59d3b2000000000000000000000 : Int) * ((evTree x : Int) + int256 (todTree x)) ∧ (0x6f05b59d3b2000000000000000000000 : Int) * ((evTree x : Int) + int256 (todTree x)) < (int256 (r0Tree x) + 1) * ((evTree x : Int) - int256 (todTree x)) := by - obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos hx hC hC0 + obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW set num := evmAdd (evTree x) (todTree x) with hnumdef set den := evmSub (evTree x) (todTree x) with hdendef have hnumw : num < 2 ^ 256 := evmAdd_lt _ _ @@ -59,8 +59,8 @@ theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) have hdeni : int256 den = (evTree x : Int) - int256 (todTree x) := hsub obtain ⟨hnumeq, hnum255⟩ := int256_eq_of_nonneg hnumw (by rw [hnumi]; omega) obtain ⟨hdeneq, hden255⟩ := int256_eq_of_nonneg hdenw (by rw [hdeni]; omega) - obtain ⟨hevlo, hevhi⟩ := evTree_facts (vTree_eq hx hC hC0).2 - obtain ⟨_, htod_hi, _, _⟩ := todTree_bound hx hC hC0 + obtain ⟨hevlo, hevhi⟩ := evTree_facts (vTree_eq_wide hx hW).2 + obtain ⟨_, htod_hi, _, _⟩ := todTree_bound_wide hx hW have hevloI : (415147853590918758559635130244235626256 : Int) ≤ (evTree x : Int) := by have : (0x1385291795942d41ba5fd317688e18710 : Int) ≤ (evTree x : Int) := by exact_mod_cast hevlo linarith [this] @@ -133,11 +133,11 @@ theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) /-- `den_rt = ev − tod ≥ 1.94·2¹²⁶` on the region (the even accumulator dominates `|tod|`). -/ theorem den_ge_194 {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : (330077261860684142693791478386293573392 : Int) ≤ (evTree x : Int) - int256 (todTree x) := by - obtain ⟨hevlo, _⟩ := evTree_facts (vTree_eq hx hC hC0).2 - obtain ⟨_, htod_hi, _, _⟩ := todTree_bound hx hC hC0 + obtain ⟨hevlo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 + obtain ⟨_, htod_hi, _, _⟩ := todTree_bound_wide hx hW have hev : (0x1385291795942d41ba5fd317688e18710 : Int) ≤ (evTree x : Int) := by exact_mod_cast hevlo have ht126 : int256 (todTree x) < 2 ^ 126 := htod_hi rw [show (0x1385291795942d41ba5fd317688e18710 : Int) = 415147853590918758559635130244235626256 from by norm_num] at hev @@ -146,18 +146,18 @@ theorem den_ge_194 {x : Nat} (hx : x < 2 ^ 256) /-- On the nonpositive half `tod ≤ 0` and hence `r0 ≤ scaleQ67` (num ≤ den). -/ theorem r0_le_scale_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (r0Tree x) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hC hC0 + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW set r0 := int256 (r0Tree x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef have hden072 : (330077261860684142693791478386293573392 : Int) ≤ ev - tod := by - have := den_ge_194 hx hC hC0; rw [← hevdef, ← htoddef] at this; exact this + have := den_ge_194 hx hW; rw [← hevdef, ← htoddef] at this; exact this have hdenpos : (0:Int) < ev - tod := lt_of_lt_of_le (by norm_num) hden072 have htodnp : tod ≤ 0 := by - obtain ⟨_, _, htodlo, _⟩ := todTree_bound hx hC hC0 + obtain ⟨_, _, htodlo, _⟩ := todTree_bound_wide hx hW have hodnn : (0:Int) ≤ (odTree x : Int) := Int.natCast_nonneg _ have : int256 (tTree x) * (odTree x : Int) ≤ 0 := mul_nonpos_of_nonpos_of_nonneg htneg hodnn nlinarith [htodlo, this] @@ -177,12 +177,12 @@ runtime `ev`/`tod` at the common scale `2^637`. -/ /-- The `Int`-cast Horner brackets and `tod` floor collected. -/ theorem bridge_facts {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : 2 ^ 526 * (evTree x : Int) ≤ (evNumV (vTree x) : Int) ∧ (evNumV (vTree x) : Int) < 2 ^ 526 * (evTree x : Int) + 72572599271425 * 2 ^ 480 ∧ 2 ^ 508 * (odTree x : Int) ≤ (odNumV (vTree x) : Int) ∧ (odNumV (vTree x) : Int) < 2 ^ 508 * (odTree x : Int) + 269746241 * 2 ^ 480 := by - obtain ⟨_, hvlt⟩ := vTree_eq hx hC hC0 + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW obtain ⟨hev_lo, hev_hi⟩ := evTree_bracket hvlt obtain ⟨hod_lo, hod_hi⟩ := odTree_bracket hvlt refine ⟨?_, ?_, ?_, ?_⟩ @@ -194,13 +194,13 @@ theorem bridge_facts {x : Nat} (hx : x < 2 ^ 256) /-- The `t·Od` product brackets (nonnegative half): `2⁶³⁷·tod ≤ t·Od` and `t·Od ≤ 2⁶³⁷·tod + 2⁶³⁷ + Wod·2⁴⁸⁰·t`. -/ theorem tOd_bracket_nonneg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 2 ^ 637 * int256 (todTree x) ≤ int256 (tTree x) * (odNumV (vTree x) : Int) ∧ int256 (tTree x) * (odNumV (vTree x) : Int) ≤ 2 ^ 637 * int256 (todTree x) + 2 ^ 637 + 269746241 * 2 ^ 480 * int256 (tTree x) := by - obtain ⟨_, _, hOp_lo, hOp_hi⟩ := bridge_facts hx hC hC0 - obtain ⟨_, _, htod_lo, htod_hi⟩ := todTree_bound hx hC hC0 + obtain ⟨_, _, hOp_lo, hOp_hi⟩ := bridge_facts hx hW + obtain ⟨_, _, htod_lo, htod_hi⟩ := todTree_bound_wide hx hW set t := int256 (tTree x) with htdef set od := (odTree x : Int) with hoddef set tod := int256 (todTree x) with htoddef @@ -221,13 +221,13 @@ theorem tOd_bracket_nonneg {x : Nat} (hx : x < 2 ^ 256) /-- The `t·Od` product brackets (nonpositive half): `t·Od ≤ 2⁶³⁷·tod + 2⁶³⁷` and `2⁶³⁷·tod − Wod·2⁴⁸⁰·(−t) ≤ t·Od`. -/ theorem tOd_bracket_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (tTree x) * (odNumV (vTree x) : Int) ≤ 2 ^ 637 * int256 (todTree x) + 2 ^ 637 ∧ 2 ^ 637 * int256 (todTree x) - 269746241 * 2 ^ 480 * (-(int256 (tTree x))) ≤ int256 (tTree x) * (odNumV (vTree x) : Int) := by - obtain ⟨_, _, hOp_lo, hOp_hi⟩ := bridge_facts hx hC hC0 - obtain ⟨_, _, htod_lo, htod_hi⟩ := todTree_bound hx hC hC0 + obtain ⟨_, _, hOp_lo, hOp_hi⟩ := bridge_facts hx hW + obtain ⟨_, _, htod_lo, htod_hi⟩ := todTree_bound_wide hx hW set t := int256 (tTree x) with htdef set od := (odTree x : Int) with hoddef set tod := int256 (todTree x) with htoddef @@ -250,15 +250,15 @@ theorem tOd_bracket_neg {x : Nat} (hx : x < 2 ^ 256) /-- **Joint link-1 over (nonneg half, `r0 ≥ scaleQ67`)**: the shared even truncation cancels through the floor, `r0·DENv − scaleQ67·NUMv ≤ Wev·2⁵⁹⁰·(r0 − scaleQ67)`. -/ theorem link1_over_tight {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) (hr0ge : (0x6f05b59d3b2000000000000000000000 : Int) ≤ int256 (r0Tree x)) : int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) - (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ 72572599271425 * 2 ^ 591 * (int256 (r0Tree x) - (0x6f05b59d3b2000000000000000000000 : Int)) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hC hC0 - obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hC hC0 htnn + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hW + obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hW htnn unfold NUMv DENv set r0 := int256 (r0Tree x) with hr0def set ev := (evTree x : Int) with hevdef @@ -284,14 +284,14 @@ theorem link1_over_tight {x : Nat} (hx : x < 2 ^ 256) /-- **Link-1 over (nonneg half, `r0 ≤ scaleQ67`)**: the residue is nonpositive outright. -/ theorem link1_over_small {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) (hr0le : int256 (r0Tree x) ≤ (0x6f05b59d3b2000000000000000000000 : Int)) : int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) - (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ 0 := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hC hC0 - obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hC hC0 htnn + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW + obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hW htnn unfold NUMv DENv set r0 := int256 (r0Tree x) with hr0def set ev := (evTree x : Int) with hevdef @@ -299,7 +299,7 @@ theorem link1_over_small {x : Nat} (hx : x < 2 ^ 256) set t := int256 (tTree x) with htdef set Ep := (evNumV (vTree x) : Int) with hEpdef set Op := (odNumV (vTree x) : Int) with hOpdef - obtain ⟨hr0lo, _⟩ := r0Tree_bounds hx hC hC0 + obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW have hr0nn : (0:Int) ≤ r0 := by have : (0:Int) < 2 ^ 124 := by positivity linarith [hr0lo] @@ -319,15 +319,15 @@ theorem link1_over_small {x : Nat} (hx : x < 2 ^ 256) /-- **Link-1 over (nonpositive half)**: the even truncation drops (`r0 ≤ scaleQ67`); the odd truncation survives attenuated to the `t`-scale: `r0·DENv − scaleQ67·NUMv ≤ Wod·2⁴⁸⁰·(−t)·(r0 + scaleQ67)`. -/ theorem link1_over_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) - (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ 269746241 * 2 ^ 480 * (-(int256 (tTree x))) * (int256 (r0Tree x) + (0x6f05b59d3b2000000000000000000000 : Int)) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hC hC0 - obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨_, htOp_lo⟩ := tOd_bracket_neg hx hC hC0 htneg - have hr0le := r0_le_scale_neg hx hC hC0 htneg + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW + obtain ⟨_, htOp_lo⟩ := tOd_bracket_neg hx hW htneg + have hr0le := r0_le_scale_neg hx hW htneg unfold NUMv DENv set r0 := int256 (r0Tree x) with hr0def set ev := (evTree x : Int) with hevdef @@ -335,7 +335,7 @@ theorem link1_over_neg {x : Nat} (hx : x < 2 ^ 256) set t := int256 (tTree x) with htdef set Ep := (evNumV (vTree x) : Int) with hEpdef set Op := (odNumV (vTree x) : Int) with hOpdef - obtain ⟨hr0lo, _⟩ := r0Tree_bounds hx hC hC0 + obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW have hr0nn : (0:Int) ≤ r0 := by have : (0:Int) < 2 ^ 124 := by positivity linarith [hr0lo] @@ -358,15 +358,15 @@ theorem link1_over_neg {x : Nat} (hx : x < 2 ^ 256) /-- On the nonneg half `DENv` brackets the runtime denominator: `2⁶³⁷·(den − 2) ≤ DENv ≤ 2⁶³⁷·den + Wev·2⁵⁹⁰` (`den = ev − tod`). -/ theorem DENv_runtime_bracket {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) - 2 * 2 ^ 637 ≤ DENv (vTree x) (int256 (tTree x)) ∧ DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + 72572599271425 * 2 ^ 591 := by - obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hC hC0 htnn - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 + obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hW + obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hW htnn + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW unfold DENv set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef @@ -389,10 +389,10 @@ theorem DENv_runtime_bracket {x : Nat} (hx : x < 2 ^ 256) /-- On the nonpositive half `DENv` dominates the scaled even accumulator: `2⁶³⁷·ev ≤ DENv`. -/ theorem DENv_ge_ev_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : 2 ^ 637 * (evTree x : Int) ≤ DENv (vTree x) (int256 (tTree x)) := by - obtain ⟨hEp_lo, _, _, hOp_hi⟩ := bridge_facts hx hC hC0 + obtain ⟨hEp_lo, _, _, hOp_hi⟩ := bridge_facts hx hW unfold DENv have hOp_nn : (0:Int) ≤ (odNumV (vTree x) : Int) := Int.natCast_nonneg _ have htOp : int256 (tTree x) * (odNumV (vTree x) : Int) ≤ 0 := @@ -401,11 +401,11 @@ theorem DENv_ge_ev_neg {x : Nat} (hx : x < 2 ^ 256) /-- On the nonneg half `NUMv` dominates the scaled runtime numerator: `2⁶³⁷·num ≤ NUMv`. -/ theorem NUMv_ge_num {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 2 ^ 637 * ((evTree x : Int) + int256 (todTree x)) ≤ NUMv (vTree x) (int256 (tTree x)) := by - obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hC hC0 htnn + obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW + obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hW htnn unfold NUMv nlinarith [hEp_lo, htOp_lo] @@ -557,9 +557,9 @@ theorem certLo_real_neg {t : Int} (h1 : t ≤ 0) (h2 : (-t) ≤ (ExpCertV.H129 : /-- `t/2¹²⁸ ≤ 0` gives the cert domain `−t ≤ H129` for the negative half. -/ theorem tdom_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (-(int256 (tTree x))) ≤ (ExpCertV.H129 : Int) := by - obtain ⟨htlo, _⟩ := tTree_in_cert_domain hx hC hC0 + obtain ⟨htlo, _⟩ := tTree_in_cert_domain_wide hx hW rw [show ((ExpCertV.H129 : Nat) : Int) = 235865763225513294137944142764154484399 from by unfold ExpCertV.H129; norm_num] omega @@ -569,9 +569,9 @@ theorem tdom_neg {x : Nat} (hx : x < 2 ^ 256) /-- On the nonnegative half of the region the reduced argument is below `ln2/2`: `t/2¹²⁸ ≤ log 2 / 2`. -/ theorem t_over_2128_le_half_log2 {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : (int256 (tTree x) : Real) / (2 ^ 129 : Real) ≤ Real.log 2 / 2 := by - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hln2lo := ln2_lower rw [LN2c_eq] at hln2lo have htR : (int256 (tTree x) : Real) ≤ (235865763225513294137944142764154484399 : Real) := by @@ -590,9 +590,9 @@ theorem t_over_2128_le_half_log2 {x : Nat} (hx : x < 2 ^ 256) /-- `exp(t/2¹²⁸) ≤ √2` on the nonneg half. -/ theorem exp_t_le_sqrt2 {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : Real.exp ((int256 (tTree x) : Real) / (2 ^ 129 : Real)) ≤ Real.sqrt 2 := by - have hle := t_over_2128_le_half_log2 hx hC hC0 + have hle := t_over_2128_le_half_log2 hx hW calc Real.exp ((int256 (tTree x) : Real) / (2 ^ 129 : Real)) ≤ Real.exp (Real.log 2 / 2) := Real.exp_le_exp.mpr hle _ = Real.sqrt 2 := by @@ -607,10 +607,10 @@ theorem exp_diff_le (a b : Real) : Real.exp b - Real.exp a ≤ (b - a) * Real.ex /-- The reduced argument is above `−log 2` on the region, so `exp(rt) > 1/2`. -/ theorem exp_reducedArg_gt_half {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : (1 : Real) / 2 < Real.exp (reducedArg x) := by - obtain ⟨htlo, _⟩ := tTree_in_cert_domain hx hC hC0 - have hclose := abs_lt.mp (reducedArg_close hx hC hC0) + obtain ⟨htlo, _⟩ := tTree_in_cert_domain_wide hx hW + have hclose := abs_lt.mp (reducedArg_close_wide hx hW) have hp128 : (0 : Real) < (2 ^ 129 : Real) := by positivity have htR : -(235865763225513294137944142764154484399 : Real) ≤ (int256 (tTree x) : Real) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr htlo; push_cast at this; linarith [this] @@ -637,12 +637,12 @@ Pulling that back through the truncation brackets caps the runtime numerator /-- The grid rational is below `14145/10000` on the nonneg half. -/ theorem Qv_le_14145 {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (NUMv (vTree x) (int256 (tTree x)) : Real) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ 14145 / 10000 := by - obtain ⟨_, hgran⟩ := gran_over_pair hx hC hC0 htnn - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 + obtain ⟨_, hgran⟩ := gran_over_pair hx hW htnn + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW set t := int256 (tTree x) with htdef have htdom : t ≤ (ExpCertV.H129 : Int) := by rw [show ((ExpCertV.H129 : Nat) : Int) = 235865763225513294137944142764154484399 from by @@ -657,7 +657,7 @@ theorem Qv_le_14145 {x : Nat} (hx : x < 2 ^ 256) -- NE/DE ≤ Et·Mp ≤ √2·(2^131/(2^131−1)) ≤ 14144/10000 have hcertlo := certLo_real htnn htdom set Et := Real.exp ((t : Real) / (2 ^ 129 : Real)) with hEtdef - have hEtsqrt2 := exp_t_le_sqrt2 hx hC hC0 + have hEtsqrt2 := exp_t_le_sqrt2 hx hW rw [← hEtdef] at hEtsqrt2 have hNEDE_le : (evalPoly ExpCertV.numExpV t : Real) / (evalPoly ExpCertV.denExpV t : Real) ≤ Et * ((2 ^ 132 : Real) / ((2 ^ 132 : Real) - 1)) := by @@ -696,13 +696,13 @@ theorem Qv_le_14145 {x : Nat} (hx : x < 2 ^ 256) /-- The runtime numerator ceiling: `10⁴·num ≤ 14145·den + 28290`. -/ theorem num_ceiling {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 10000 * ((evTree x : Int) + int256 (todTree x)) ≤ 14145 * ((evTree x : Int) - int256 (todTree x)) + 28290 := by - have hQv := Qv_le_14145 hx hC hC0 htnn - obtain ⟨hthi_lo, hthi⟩ := tTree_in_cert_domain hx hC hC0 - have hvle := vTree_le_vmax hx hC hC0 + have hQv := Qv_le_14145 hx hW htnn + obtain ⟨hthi_lo, hthi⟩ := tTree_in_cert_domain_wide hx hW + have hvle := vTree_le_vmax_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef have hD : 1108965543718 * 2 ^ 725 ≤ DENv v t := DENv_ge_over (by omega) hthi @@ -717,8 +717,8 @@ theorem num_ceiling {x : Nat} (hx : x < 2 ^ 256) nlinarith [hR] exact_mod_cast hR2 -- pull back through the brackets: 2^637·num ≤ NUMv; DENv ≤ 2^637·den + Wev·2^590 - have hNUM_ge := NUMv_ge_num hx hC hC0 htnn - obtain ⟨_, hDEN_le⟩ := DENv_runtime_bracket hx hC hC0 htnn + have hNUM_ge := NUMv_ge_num hx hW htnn + obtain ⟨_, hDEN_le⟩ := DENv_runtime_bracket hx hW htnn set num := (evTree x : Int) + int256 (todTree x) with hnumdef set den := (evTree x : Int) - int256 (todTree x) with hdendef -- 10000·2^637·num ≤ 14145·(2^637·den + Wev·2^590) ≤ 2^637·(14145·den + 28290) @@ -738,11 +738,11 @@ theorem num_ceiling {x : Nat} (hx : x < 2 ^ 256) /-- `100·num ≤ 145·den` (`ê ≤ 1.45`) on the nonneg half. -/ theorem num_le_145_den {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 100 * ((evTree x : Int) + int256 (todTree x)) ≤ 145 * ((evTree x : Int) - int256 (todTree x)) := by - have hceil := num_ceiling hx hC hC0 htnn - have hden := den_ge_194 hx hC hC0 + have hceil := num_ceiling hx hW htnn + have hden := den_ge_194 hx hW set num := (evTree x : Int) + int256 (todTree x) with hnumdef set den := (evTree x : Int) - int256 (todTree x) with hdendef -- 100·(10000·num) ≤ 100·(14145·den + 28290) ≤ 10000·(145·den) since 355·den ≥ 2829000 @@ -750,12 +750,12 @@ theorem num_le_145_den {x : Nat} (hx : x < 2 ^ 256) /-- The quotient cap: `10⁴·(r0 − scaleQ67) ≤ 4146·scaleQ67` on the nonneg half. -/ theorem r0_cap {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 10000 * (int256 (r0Tree x) - (0x6f05b59d3b2000000000000000000000 : Int)) ≤ 4146 * (0x6f05b59d3b2000000000000000000000 : Int) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hC hC0 - have hceil := num_ceiling hx hC hC0 htnn - have hden := den_ge_194 hx hC hC0 + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + have hceil := num_ceiling hx hW htnn + have hden := den_ge_194 hx hW set r0 := int256 (r0Tree x) with hr0def set num := (evTree x : Int) + int256 (todTree x) with hnumdef set den := (evTree x : Int) - int256 (todTree x) with hdendef @@ -773,13 +773,13 @@ theorem r0_cap {x : Nat} (hx : x < 2 ^ 256) /-- The link-1 jitter divided by `DENv` stays inside its budget (nonneg half): `Wev·2⁵⁹⁰·(r0 − scaleQ67)/DENv ≤ (5¹⁸/2⁴⁰)·2170557036555806152/10¹⁹`. -/ theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (72572599271425 : Real) * 2 ^ 591 * ((int256 (r0Tree x) : Real) - 0x6f05b59d3b2000000000000000000000) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 - have hvle := vTree_le_vmax hx hC hC0 + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW + have hvle := vTree_le_vmax_wide hx hW set r0 := int256 (r0Tree x) with hr0def set t := int256 (tTree x) with htdef set v := vTree x with hvdef @@ -794,13 +794,13 @@ theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) have hpos : (0:Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by positivity linarith [this, hpos] · rw [div_le_iff₀ hDR] - have hcap := r0_cap hx hC hC0 htnn + have hcap := r0_cap hx hW htnn have hcapR : (r0 : Real) - 0x6f05b59d3b2000000000000000000000 ≤ 4146 * 0x6f05b59d3b2000000000000000000000 / 10000 := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hcap push_cast at h linarith [h] - obtain ⟨hDEN_ge, _⟩ := DENv_runtime_bracket hx hC hC0 htnn - have hden := den_ge_194 hx hC hC0 + obtain ⟨hDEN_ge, _⟩ := DENv_runtime_bracket hx hW htnn + have hden := den_ge_194 hx hW have hDENlow : (2:Int) ^ 637 * (330077261860684142693791478386293573392 - 2) ≤ DENv v t := by have : (2:Int) ^ 637 * (330077261860684142693791478386293573392 - 2) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) - 2 * 2 ^ 637 := by @@ -828,12 +828,12 @@ theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) /-- **The per-point never-over (nonneg half).** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` with the four-link budget `B = 5737291786393199862/10¹⁹` itemized in the module header. -/ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 - have hvle := vTree_le_vmax hx hC hC0 + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW + have hvle := vTree_le_vmax_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef have htdom : t ≤ (ExpCertV.H129 : Int) := by @@ -852,14 +852,14 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) have hlink1 : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by rcases le_or_gt r0 (0x6f05b59d3b2000000000000000000000 : Int) with hsm | hbg - · have hi := link1_over_small hx hC hC0 htnn hsm + · have hi := link1_over_small hx hW htnn hsm have hiR : (r0 : Real) * (DENv v t : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] have hr0le : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) := by rw [mul_div_assoc', le_div_iff₀ hDR]; linarith [hiR] have hBJnn : (0:Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by positivity linarith [hr0le, hBJnn] - · have hi := link1_over_tight hx hC hC0 htnn (le_of_lt hbg) + · have hi := link1_over_tight hx hW htnn (le_of_lt hbg) have hjointR : (r0 : Real) * (DENv v t : Real) - (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) ≤ (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] @@ -867,16 +867,16 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) / (DENv v t : Real) := by rw [div_add_div_same, le_div_iff₀ hDR]; nlinarith [hjointR, hDR] rw [mul_div_assoc] at hstep - linarith [hstep, jitter_over_budget hx hC hC0 htnn] + linarith [hstep, jitter_over_budget hx hW htnn] -- link 2: 2^126·Qv ≤ 2^126·(NE/DE) + grain - obtain ⟨_, hgran⟩ := gran_over_pair hx hC hC0 htnn + obtain ⟨_, hgran⟩ := gran_over_pair hx hW htnn -- link 3: NE/DE ≤ Et·Mp; Mp excess ≤ √2·2^126/(2^131−1) have hcertlo := certLo_real htnn htdom set Et := Real.exp ((t : Real) / (2 ^ 129 : Real)) with hEtdef set NE := evalPoly ExpCertV.numExpV t with hNEdef set DE := evalPoly ExpCertV.denExpV t with hDEdef set Mp : Real := (2 ^ 132 : Real) / ((2 ^ 132 : Real) - 1) with hMpdef - have hEtsqrt2 := exp_t_le_sqrt2 hx hC hC0 + have hEtsqrt2 := exp_t_le_sqrt2 hx hW rw [← hEtdef] at hEtsqrt2 have hEtnn : (0 : Real) ≤ Et := le_of_lt (Real.exp_pos _) have hNEDE_le : (NE : Real) / (DE : Real) ≤ Et * Mp := by @@ -906,7 +906,7 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) linarith [hb, hn] -- link 4: 2^126·(Et − Ert) ≤ √2/128 set Ert := Real.exp (reducedArg x) with hErtdef - have hgapover := reducedArg_close_over hx hC hC0 + have hgapover := reducedArg_close_over_wide hx hW have hExp_diff : Et - Ert ≤ ((t : Real) / (2 ^ 129 : Real) - reducedArg x) * Et := exp_diff_le _ _ have hcGap1 : (2 ^ 126 : Real) * (Et - Ert) ≤ 55242717280199026 / 10000000000000000000 := by have h1 : Et - Ert ≤ (1 / (32 * (2 ^ 129 : Real))) * Et := @@ -939,16 +939,16 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) /-- The link-1 jitter budget on the nonpositive half: `Wod·2⁴⁸⁰·(−t)·(r0 + scaleQ67)/DENv ≤ (5¹⁸/2⁴⁰)·2170557036555806152/10¹⁹`. -/ theorem jitter_over_budget_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (269746241 : Real) * 2 ^ 480 * (-(int256 (tTree x) : Real)) * ((int256 (r0Tree x) : Real) + 0x6f05b59d3b2000000000000000000000) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by - obtain ⟨htlo, _⟩ := tTree_in_cert_domain hx hC hC0 - have hr0le := r0_le_scale_neg hx hC hC0 htneg - obtain ⟨hr0lo, _⟩ := r0Tree_bounds hx hC hC0 - have hDEN_ge := DENv_ge_ev_neg hx hC hC0 htneg - obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq hx hC hC0).2 + obtain ⟨htlo, _⟩ := tTree_in_cert_domain_wide hx hW + have hr0le := r0_le_scale_neg hx hW htneg + obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW + have hDEN_ge := DENv_ge_ev_neg hx hW htneg + obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 set r0 := int256 (r0Tree x) with hr0def set t := int256 (tTree x) with htdef set v := vTree x with hvdef @@ -1008,12 +1008,12 @@ theorem jitter_over_budget_neg {x : Nat} (hx : x < 2 ^ 256) /-- **The per-point never-over (nonpositive half).** The granularity is free here; the `Mp` factor and reduced-argument gap shrink (`Et ≤ 1`), so the same budget `B` covers the half. -/ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by - have htdom := tdom_neg hx hC hC0 htneg - have hvle := vTree_le_vmax hx hC hC0 + have htdom := tdom_neg hx hW htneg + have hvle := vTree_le_vmax_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0Tree x) with hr0def @@ -1025,7 +1025,7 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) -- link 1: r0 ≤ scaleQ67·Qv + jitter have hlink1 : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by - have hi := link1_over_neg hx hC hC0 htneg + have hi := link1_over_neg hx hW htneg have hiR : (r0 : Real) * (DENv v t : Real) - (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) ≤ (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + 0x6f05b59d3b2000000000000000000000) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] @@ -1034,9 +1034,9 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) (DENv v t : Real) := by rw [div_add_div_same, le_div_iff₀ hDR]; nlinarith [hiR, hDR] rw [mul_div_assoc] at hstep - linarith [hstep, jitter_over_budget_neg hx hC hC0 htneg] + linarith [hstep, jitter_over_budget_neg hx hW htneg] -- link 2 (free): Qv ≤ NE/DE - obtain ⟨hgran1, _⟩ := gran_under_pair hx hC hC0 htneg + obtain ⟨hgran1, _⟩ := gran_under_pair hx hW htneg -- link 3: NE/DE ≤ Et·Mpp with Et ≤ 1 have hcertlo := certLo_real_neg htneg htdom set Et := Real.exp ((t : Real) / (2 ^ 129 : Real)) with hEtdef @@ -1071,7 +1071,7 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) linarith [h1, hn] -- link 4 with Et ≤ 1 set Ert := Real.exp (reducedArg x) with hErtdef - have hgapover := reducedArg_close_over hx hC hC0 + have hgapover := reducedArg_close_over_wide hx hW have hExp_diff : Et - Ert ≤ ((t : Real) / (2 ^ 129 : Real) - reducedArg x) * Et := exp_diff_le _ _ have hcGap1 : (2 ^ 126 : Real) * (Et - Ert) ≤ 55242717280199026 / 10000000000000000000 := by have h1 : Et - Ert ≤ (1 / (32 * (2 ^ 129 : Real))) * Et := @@ -1099,13 +1099,19 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) /-- **Per-point never-over (tight, any sign):** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴⁰)·B` (the budget's image is strictly below `MARGIN = 1`). -/ -theorem r0_real_over_within {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem r0_real_over_within_wide {x : Nat} (hx : x < 2 ^ 256) + (hW : WideRegion x) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg - · exact r0_real_over_tight hx hC hC0 htnn - · exact r0_real_over_tight_neg hx hC hC0 (le_of_lt htneg) + · exact r0_real_over_tight hx hW htnn + · exact r0_real_over_tight_neg hx hW (le_of_lt htneg) + +theorem r0_real_over_within {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := + r0_real_over_within_wide hx (wideRegion_of_wad hC hC0) /-! ## The octave real identity `E·2^(68−k) = WAD·2⁶⁸·exp(rt)` diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean index c6b337633..69ef33935 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean @@ -37,12 +37,12 @@ noncomputable section `reducedArg ≤ log2/2 + 33/(32·2¹²⁸)`, so `exp` is at most `√2·(1+ε)`, which the `14143/10000` ceiling covers with room. Drives the under gap-1. -/ theorem exp_reducedArg_le_sqrt2bound {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : Real.exp (reducedArg x) ≤ 14143 / 10000 := by - have hclose := abs_lt.mp (reducedArg_close hx hC hC0) + have hclose := abs_lt.mp (reducedArg_close_wide hx hW) have hthalf : (int256 (tTree x) : Real) / (2 ^ 129 : Real) ≤ Real.log 2 / 2 := by rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg - · exact t_over_2128_le_half_log2 hx hC hC0 + · exact t_over_2128_le_half_log2 hx hW · have htle : (int256 (tTree x) : Real) ≤ 0 := by exact_mod_cast le_of_lt htneg have hlog2 : (0:Real) ≤ Real.log 2 := Real.log_nonneg (by norm_num) have : (int256 (tTree x) : Real) / (2 ^ 129 : Real) ≤ 0 := @@ -79,21 +79,21 @@ theorem exp_reducedArg_le_sqrt2bound {x : Nat} (hx : x < 2 ^ 256) /-- `r0` is bracketed on the nonneg half: `scaleQ67 ≤ r0` and `100·r0 ≤ 145·scaleQ67`. -/ theorem r0_bracket_nonneg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (0x6f05b59d3b2000000000000000000000 : Int) ≤ int256 (r0Tree x) ∧ 100 * (int256 (r0Tree x)) ≤ 145 * (0x6f05b59d3b2000000000000000000000 : Int) := by - obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hx hC hC0 - have h145 := num_le_145_den hx hC hC0 htnn + obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hx hW + have h145 := num_le_145_den hx hW htnn set r0 := int256 (r0Tree x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef have hden072 : (330077261860684142693791478386293573392 : Int) ≤ ev - tod := by - have := den_ge_194 hx hC hC0; rw [← hevdef, ← htoddef] at this; exact this + have := den_ge_194 hx hW; rw [← hevdef, ← htoddef] at this; exact this have hdenpos : (0:Int) < ev - tod := lt_of_lt_of_le (by norm_num) hden072 -- tod ≥ 0 on nonneg half have htodnn : (0:Int) ≤ tod := by - obtain ⟨_, _, htodlo, _⟩ := todTree_bound hx hC hC0 + obtain ⟨_, _, htodlo, _⟩ := todTree_bound_wide hx hW have hodnn : (0:Int) ≤ (odTree x : Int) := Int.natCast_nonneg _ have htod : (2 ^ 129 : Int) * tod ≤ int256 (tTree x) * (odTree x : Int) := htodlo have hpos : (0:Int) ≤ int256 (tTree x) * (odTree x : Int) := mul_nonneg htnn hodnn @@ -183,16 +183,16 @@ costs one denominator; the odd-truncation carry `(2⁶³⁷ + Wod·2⁴⁸⁰·t piecewise over `granPieces` (`t ≤ T` and `DO·2⁷²⁵ ≤ DENv` per piece, the certified `Link1PieceOK` row closing the quadratic), fitting `1.378` denominators. -/ theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 1000 * ((0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x))) ≤ 2378 * DENv (vTree x) (int256 (tTree x)) := by - obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hx hC hC0 - obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hC hC0 htnn - obtain ⟨hr0lo, hr0hi145⟩ := r0_bracket_nonneg hx hC hC0 htnn - obtain ⟨hDEN_lo, hDEN_up⟩ := DENv_runtime_bracket hx hC hC0 htnn + obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hx hW + obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW + obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hW htnn + obtain ⟨hr0lo, hr0hi145⟩ := r0_bracket_nonneg hx hW htnn + obtain ⟨hDEN_lo, hDEN_up⟩ := DENv_runtime_bracket hx hW htnn have hLHS : (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + @@ -221,9 +221,9 @@ theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) 2 ^ 637 * (ev - tod) := mul_le_mul_of_nonneg_left hfloor (by positivity) nlinarith [hterm1, hterm2, hfloor638] -- select the covering piece; its certified facts drive the aggregation - obtain ⟨_, hvsplit⟩ := tsq_split hx hC hC0 + obtain ⟨_, hvsplit⟩ := tsq_split_wide hx hW have hvmaxI : ((vTree x : Nat) : Int) ≤ (ExpCertV.vmaxV : Int) := by - exact_mod_cast vTree_le_vmax hx hC hC0 + exact_mod_cast vTree_le_vmax_wide hx hW obtain ⟨p, hp, hplo, hphi⟩ := piecesCover_sound hvmaxI 0 granPieces_cover (Int.natCast_nonneg (vTree x)) obtain ⟨vlo, vhi, T, DO, DU⟩ := p @@ -305,18 +305,18 @@ theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) this half `DENv = Ep·2¹¹¹ − t·Op ≥ 2⁶³⁸·ev`, so the even-truncation width and the `tod`-floor unit are absorbed against `2⁶³⁸·ev ≥ 2⁶³⁸·A0`. -/ theorem link1_under_int_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : 1000 * ((0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x))) ≤ 2378 * DENv (vTree x) (int256 (tTree x)) := by - obtain ⟨_, hfloor_hi⟩ := r0_floor_sandwich hx hC hC0 - obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hC hC0 - obtain ⟨htOp_hi, _⟩ := tOd_bracket_neg hx hC hC0 htneg - have hr0le := r0_le_scale_neg hx hC hC0 htneg - obtain ⟨hr0lo, _⟩ := r0Tree_bounds hx hC hC0 - obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq hx hC hC0).2 - obtain ⟨htod_lo126, _, _, _⟩ := todTree_bound hx hC hC0 + obtain ⟨_, hfloor_hi⟩ := r0_floor_sandwich hx hW + obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hW + obtain ⟨htOp_hi, _⟩ := tOd_bracket_neg hx hW htneg + have hr0le := r0_le_scale_neg hx hW htneg + obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW + obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 + obtain ⟨htod_lo126, _, _, _⟩ := todTree_bound_wide hx hW have hLHS : (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + @@ -400,11 +400,11 @@ theorem link1_under_int_neg {x : Nat} (hx : x < 2 ^ 256) /-- **The per-point deficit (nonneg half).** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`: link-1 `≤ 2378/1000`, the `Mp` factor `≤ 2/25`, the under gap `≤ 307/1000`; the granularity is free on this half. -/ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by - obtain ⟨_, hthi⟩ := tTree_in_cert_domain hx hC hC0 - have hvle := vTree_le_vmax hx hC hC0 + obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW + have hvle := vTree_le_vmax_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0Tree x) with hr0def @@ -420,7 +420,7 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) have : (0:Int) < evalPoly ExpCertV.denExpV t := lt_of_lt_of_le one_pos hDE exact_mod_cast this -- link 1: 2^126·Qv ≤ r0 + 2378/1000 - have hlink1 := link1_under_int hx hC hC0 htnn + have hlink1 := link1_under_int hx hW htnn have hQv_le : (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (r0 : Real) + 2378 / 1000 := by rw [mul_div_assoc', div_le_iff₀ hDR] @@ -428,7 +428,7 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) push_cast at hR nlinarith [hR, hDR] -- link 2 (free): NE/DE ≤ Qv - obtain ⟨hgran1, _⟩ := gran_over_pair hx hC hC0 htnn + obtain ⟨hgran1, _⟩ := gran_over_pair hx hW htnn -- link 3: Et ≤ (NE/DE)·Mpp ≤ Qv·Mpp; Mpp excess ≤ 2/25 via r0 ≤ 1.45·2^126 have hcertup := certUp_real htnn htdom set Et := Real.exp ((t : Real) / (2 ^ 129 : Real)) with hEtdef @@ -447,7 +447,7 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) have hEt_le_Qv : Et ≤ ((NUMv v t : Real) / (DENv v t : Real)) * Mpp := le_trans hEt_le (mul_le_mul_of_nonneg_right hgran1 hMpp_nn) have hMpp1 : Mpp - 1 = 1 / (2 ^ 132 : Real) := by rw [hMppdef]; field_simp - obtain ⟨_, hr0hi145⟩ := r0_bracket_nonneg hx hC hC0 htnn + obtain ⟨_, hr0hi145⟩ := r0_bracket_nonneg hx hW htnn have hr0R : (r0 : Real) ≤ (145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0hi145 push_cast at h @@ -470,9 +470,9 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) linarith [h1, h2 ▸ h1, h3, hQv_le] -- link 4 (under gap): 2^126·(Ert − Et) ≤ 307/1000 set Ert := Real.exp (reducedArg x) with hErtdef - have hgapunder := reducedArg_close_under hx hC hC0 + have hgapunder := reducedArg_close_under_wide hx hW have hExp_diff : Ert - Et ≤ (reducedArg x - (t : Real) / (2 ^ 129 : Real)) * Ert := exp_diff_le _ _ - have hErt_le := exp_reducedArg_le_sqrt2bound hx hC hC0 + have hErt_le := exp_reducedArg_le_sqrt2bound hx hW rw [← hErtdef] at hErt_le have hErt_nn : (0:Real) ≤ Ert := le_of_lt (Real.exp_pos _) have hgap126 : (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) ≤ 307 / 1000 := by @@ -498,11 +498,11 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) the `Mp`-folded granularity `≤ (5¹⁸/2⁴¹)·1644901622230542074/10¹⁹`, the `Mp` factor `≤ 2/25` (via `r0 ≤ scaleQ67`), the under gap `≤ 307/1000`. -/ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) + (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by - have htdom := tdom_neg hx hC hC0 htneg - have hvle := vTree_le_vmax hx hC hC0 + have htdom := tdom_neg hx hW htneg + have hvle := vTree_le_vmax_wide hx hW set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0Tree x) with hr0def @@ -512,7 +512,7 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) have hDEpos : (0:Int) < evalPoly ExpCertV.denExpV t := (certNE_pos_neg_aux htneg htdom).2 have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by exact_mod_cast hDEpos -- link 1: 2^126·Qv ≤ r0 + 2378/1000 - have hlink1 := link1_under_int_neg hx hC hC0 htneg + have hlink1 := link1_under_int_neg hx hW htneg have hQv_le : (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (r0 : Real) + 2378 / 1000 := by rw [mul_div_assoc', div_le_iff₀ hDR] @@ -532,13 +532,13 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) (((2 ^ 132 - 1 : Int) : Real) * (DE : Real)) := by push_cast; field_simp; ring rw [key]; exact hcertup - obtain ⟨_, hgran2⟩ := gran_under_pair hx hC hC0 htneg + obtain ⟨_, hgran2⟩ := gran_under_pair hx hW htneg have hMp_nn : (0:Real) ≤ Mp := by rw [hMpdef] have : (0:Real) < (2 ^ 132 : Real) - 1 := by norm_num positivity have hMp1 : Mp - 1 = 1 / ((2 ^ 132 : Real) - 1) := by rw [hMpdef]; field_simp - have hr0le := r0_le_scale_neg hx hC hC0 htneg + have hr0le := r0_le_scale_neg hx hW htneg have hr0R : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h @@ -567,7 +567,7 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) linarith [h1, hsplit ▸ h1, hMpterm, hgran2, hQv_le] -- link 4 (under gap): 2^126·(Ert − Et) ≤ 307/1000 set Ert := Real.exp (reducedArg x) with hErtdef - have hgapunder := reducedArg_close_under hx hC hC0 + have hgapunder := reducedArg_close_under_wide hx hW have hExp_diff : Ert - Et ≤ (reducedArg x - (t : Real) / (2 ^ 129 : Real)) * Ert := exp_diff_le _ _ have hErt_nn : (0:Real) ≤ Ert := le_of_lt (Real.exp_pos _) -- on this half `rt ≤ 1025/(1024·2¹²⁹)`, so `Ert ≤ 10001/10000` @@ -614,20 +614,25 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) linarith [hEt_bound, hgap126, hdist, hsum] /-- **Per-point deficit (tight, any sign):** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`. -/ -theorem r0_real_under_within {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +theorem r0_real_under_within_wide {x : Nat} (hx : x < 2 ^ 256) + (hW : WideRegion x) : (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg - · exact r0_real_under_tight hx hC hC0 htnn - · exact r0_real_under_tight_neg hx hC hC0 (le_of_lt htneg) + · exact r0_real_under_tight hx hW htnn + · exact r0_real_under_tight_neg hx hW (le_of_lt htneg) + +theorem r0_real_under_within {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := + r0_real_under_within_wide hx (wideRegion_of_wad hC hC0) /-! ## The octave-seam `r0`-doubling consequence -/ /-- `2¹²³ < r0Tree x` on the region, directly from the runtime quotient range. -/ theorem r0Tree_gt_2126 {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + (hW : WideRegion x) : (2 : Real) ^ 123 < (int256 (r0Tree x) : Real) := by - obtain ⟨hr0lo, _⟩ := r0Tree_bounds hx hC hC0 + obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW have h : ((2 ^ 124 : Int) : Real) ≤ (int256 (r0Tree x) : Real) := by exact_mod_cast hr0lo have h2 : (2 : Real) ^ 123 < ((2 ^ 124 : Int) : Real) := by norm_num linarith [h, h2] @@ -651,16 +656,15 @@ theorem reducedArg_seam {x1 x2 : Nat} `SeamR0Bound`). The strict slack from `exp(−1/RAY) < 1` (against `r0Tree x2 > 2¹²³`, worth `≈ 8.5·10¹⁰` grid units) dwarfs the per-point envelopes and the three integer units the seam-floor comparison consumes. -/ -theorem r0_seam_double {x1 x2 : Nat} +theorem r0_seam_double_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) - (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) - (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hk : int256 (kTree x2) = int256 (kTree x1) + 1) (hadj : int256 x2 = int256 x1 + 1) : int256 (r0Tree x1) + 3 ≤ 2 * int256 (r0Tree x2) := by - have hover1 := r0_real_over_within hx1 hC1 hC01 - have hunder2 := r0_real_under_within hx2 hC2 hC02 - have hr0_2_big := r0Tree_gt_2126 hx2 hC2 hC02 + have hover1 := r0_real_over_within_wide hx1 hW1 + have hunder2 := r0_real_under_within_wide hx2 hW2 + have hr0_2_big := r0Tree_gt_2126 hx2 hW2 have hseam := reducedArg_seam hk hadj set E1 := Real.exp (reducedArg x1) with hE1 set E2 := Real.exp (reducedArg x2) with hE2 @@ -722,6 +726,15 @@ theorem r0_seam_double {x1 x2 : Nat} linarith [hreal] exact_mod_cast hcast +theorem r0_seam_double {x1 x2 : Nat} + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) + (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) + (hk : int256 (kTree x2) = int256 (kTree x1) + 1) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (r0Tree x1) + 3 ≤ 2 * int256 (r0Tree x2) := + r0_seam_double_wide hx1 hx2 (wideRegion_of_wad hC1 hC01) (wideRegion_of_wad hC2 hC02) hk hadj + end end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean index 72120c1c7..5c8de1977 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean @@ -239,13 +239,12 @@ theorem r0Tree_bounds_ofEvTod {E TD : Nat} (hevw : E < 2 ^ 256) (htodw : TD < 2 have hDpos : 0 < ((evmSub E TD : Nat) : Int) := by rw [← hDi, hsub]; omega exact r0Tree_bounds_of hNlt128 hDlt128 hDwlt hDi hNpos hDpos hNlo hND -/-- `2^124 ≤ r0Tree x < 2^130` on the meaningful region. -/ -theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) - (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : +/-- `2^124 ≤ r0Tree x < 2^130` on the wide region. -/ +theorem r0Tree_bounds_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 130 := by - obtain ⟨_, hvlt⟩ := vTree_eq hx hC hC0 + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW obtain ⟨hev_lo, hev_hi⟩ := evTree_facts hvlt - obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound hx hC hC0 + obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound_wide hx hW have hr0 : r0Tree x = evmDiv (evmMul scaleQ67 (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) := rfl rw [hr0] @@ -260,4 +259,9 @@ theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) · rw [show (85070591730234615865843651857942052864 : Int) = 2 ^ 126 by norm_num]; exact htod_lo · rw [show (85070591730234615865843651857942052864 : Int) = 2 ^ 126 by norm_num]; exact htod_hi +theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 130 := + r0Tree_bounds_wide hx (wideRegion_of_wad hC hC0) + end ExpYul From 97608804e7b0bb53197360500543eb8546599f83 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 12:40:58 +0200 Subject: [PATCH 068/107] Generalize the exp per-point brackets to a symbolic scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scaled quotient becomes r0ScaledTree scale x, with r0Tree and the mulExpRay quotient its scaleQ67 and dynamic-scale instances by rfl. The whole per-point bracket surface — floor sandwich, link-1 on both sides, quotient cap, jitter budgets, and the never-over/deficit assemblies — now holds for any scale with 2^125 <= scale <= scaleQ67: the error budgets stay certified at the literal maximal scale (smaller scales only shrink the true error terms), the piecewise decide+kernel link-1 certificate keeps its literal rows behind a monotone-in-scale adapter (every scale coefficient in a row is nonnegative and the right-hand side is scale-free), and the 2^126-normalized cert links are rescaled by scale/2^126 before assembly instead of relying on a constant-ratio closure. The scaled quotient itself sits in [2^123, 2^130) with the lower bound exact at the minimal scale, and the same-octave cross-monotonicity transport takes the scale symbolically. Wad-named instances keep their statements and signatures by instantiating the maximal scale. Co-Authored-By: Claude Fable 5 --- formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean | 392 ++++++++++-------- .../ExpProof/ExpProof/Floor/R0ExpUnder.lean | 373 +++++++++++------ formal/exp/ExpProof/ExpProof/Mono/Cross.lean | 96 ++--- .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 2 + formal/exp/ExpProof/ExpProof/Mono/Quot.lean | 109 +++++ .../exp/ExpProof/ExpProof/Mono/StepMono.lean | 4 +- formal/exp/ExpProof/ExpProof/Mono/Tree.lean | 7 + 7 files changed, 643 insertions(+), 340 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean index 0218b91c4..584541e13 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean @@ -8,8 +8,10 @@ import Mathlib.Analysis.SpecialFunctions.Pow.Real /-! # The per-point `r0`-vs-`exp` bridge (never-over side) -This module bounds the scaled quotient `r0Tree x` above by `scaleQ67·exp(rt) = (10¹⁸·2⁶⁷)·exp(rt)` -plus the never-over budget image `(5¹⁸/2⁴¹)·B` +This module bounds the scaled quotient `r0ScaledTree scale x` above by `scale·exp(rt)` +plus the never-over budget image `(5¹⁸/2⁴¹)·B`, for any scale `2¹²⁵ ≤ scale ≤ scaleQ67 = +10¹⁸·2⁶⁷` (the budget is certified at the maximal scale; smaller scales only shrink the true +error) (`rt = X/RAY − k·ln2` the reduced argument), the analytic content the floor brackets (`Floor.R0BoundHolds`) consume. The chain has four links: @@ -42,14 +44,14 @@ set_option exponentiation.threshold 2000 /-! ## The `div` floor sandwich -/ -/-- The scaled quotient is the integer floor: `r0·den_rt ≤ scaleQ67·num_rt < (r0+1)·den_rt` with -`num_rt = ev + tod`, `den_rt = ev − tod`. -/ -theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) +/-- The scaled quotient is the integer floor: `r0·den_rt ≤ scale·num_rt < (r0+1)·den_rt` with +`num_rt = ev + tod`, `den_rt = ev − tod`, at any `scale ≤ scaleQ67`. -/ +theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) : - int256 (r0Tree x) * ((evTree x : Int) - int256 (todTree x)) ≤ - (0x6f05b59d3b2000000000000000000000 : Int) * ((evTree x : Int) + int256 (todTree x)) ∧ - (0x6f05b59d3b2000000000000000000000 : Int) * ((evTree x : Int) + int256 (todTree x)) < - (int256 (r0Tree x) + 1) * ((evTree x : Int) - int256 (todTree x)) := by + int256 (r0ScaledTree scale x) * ((evTree x : Int) - int256 (todTree x)) ≤ + (scale : Int) * ((evTree x : Int) + int256 (todTree x)) ∧ + (scale : Int) * ((evTree x : Int) + int256 (todTree x)) < + (int256 (r0ScaledTree scale x) + 1) * ((evTree x : Int) - int256 (todTree x)) := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW set num := evmAdd (evTree x) (todTree x) with hnumdef set den := evmSub (evTree x) (todTree x) with hdendef @@ -57,8 +59,8 @@ theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) have hdenw : den < 2 ^ 256 := evmSub_lt _ _ have hnumi : int256 num = (evTree x : Int) + int256 (todTree x) := hadd have hdeni : int256 den = (evTree x : Int) - int256 (todTree x) := hsub - obtain ⟨hnumeq, hnum255⟩ := int256_eq_of_nonneg hnumw (by rw [hnumi]; omega) - obtain ⟨hdeneq, hden255⟩ := int256_eq_of_nonneg hdenw (by rw [hdeni]; omega) + obtain ⟨hnumeq, hnum255⟩ := int256_eq_of_nonneg hnumw (by rw [hnumi]; exact le_of_lt hnum_pos) + obtain ⟨hdeneq, hden255⟩ := int256_eq_of_nonneg hdenw (by rw [hdeni]; exact le_of_lt hden_pos) obtain ⟨hevlo, hevhi⟩ := evTree_facts (vTree_eq_wide hx hW).2 obtain ⟨_, htod_hi, _, _⟩ := todTree_bound_wide hx hW have hevloI : (415147853590918758559635130244235626256 : Int) ≤ (evTree x : Int) := by @@ -73,43 +75,43 @@ theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) have hnumnat128 : num < 2 ^ 129 := by have hh : ((num : Nat) : Int) < 2 ^ 129 := by rw [hnumeq] at hnumlt128; exact hnumlt128 exact_mod_cast hh - have hsw : scaleQ67 < 2 ^ 256 := by unfold scaleQ67; norm_num - have hfit : scaleQ67 * num < 2 ^ 256 := by - have h1 : scaleQ67 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul_left _ (le_of_lt hnumnat128) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hfit : scale * num < 2 ^ 256 := by + have h1 : scale * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hnumnat128) have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num omega - have hmulval : evmMul scaleQ67 num = scaleQ67 * num := evmMul_eq_nat hsw hnumw hfit + have hmulval : evmMul scale num = scale * num := evmMul_eq_nat hsw hnumw hfit have hdennat : 0 < den := by - have hh : (0:Int) < ((den : Nat) : Int) := by rw [← hdeneq, hdeni]; omega + have hh : (0:Int) < ((den : Nat) : Int) := by rw [← hdeneq, hdeni]; exact hden_pos exact_mod_cast hh - have hr0eq : r0Tree x = evmDiv (evmMul scaleQ67 num) den := rfl - have hdivval : evmDiv (evmMul scaleQ67 num) den = scaleQ67 * num / den := by - rw [hmulval, evmDiv_eq hfit hdenw (by omega)] - have hr0q : r0Tree x = scaleQ67 * num / den := by rw [hr0eq, hdivval] - have hfloor_lo : (scaleQ67 * num / den) * den ≤ scaleQ67 * num := Nat.div_mul_le_self _ _ - have hfloor_hi : scaleQ67 * num < (scaleQ67 * num / den + 1) * den := by - have hdm : den * (scaleQ67 * num / den) + (scaleQ67 * num) % den = scaleQ67 * num := + have hr0eq : r0ScaledTree scale x = evmDiv (evmMul scale num) den := rfl + have hdivval : evmDiv (evmMul scale num) den = scale * num / den := by + rw [hmulval, evmDiv_eq hfit hdenw (Nat.pos_iff_ne_zero.mp hdennat)] + have hr0q : r0ScaledTree scale x = scale * num / den := by rw [hr0eq, hdivval] + have hfloor_lo : (scale * num / den) * den ≤ scale * num := Nat.div_mul_le_self _ _ + have hfloor_hi : scale * num < (scale * num / den + 1) * den := by + have hdm : den * (scale * num / den) + (scale * num) % den = scale * num := Nat.div_add_mod _ den - have hmod : (scaleQ67 * num) % den < den := Nat.mod_lt _ hdennat - calc scaleQ67 * num = den * (scaleQ67 * num / den) + (scaleQ67 * num) % den := hdm.symm - _ < den * (scaleQ67 * num / den) + den := Nat.add_lt_add_left hmod _ - _ = (scaleQ67 * num / den + 1) * den := by ring + have hmod : (scale * num) % den < den := Nat.mod_lt _ hdennat + calc scale * num = den * (scale * num / den) + (scale * num) % den := hdm.symm + _ < den * (scale * num / den) + den := Nat.add_lt_add_left hmod _ + _ = (scale * num / den + 1) * den := by ring -- the quotient is small: den ≥ 2^126 gives q < 2^130 < 2^255 have hden126 : 2 ^ 126 ≤ den := by have h : (2 ^ 126 : Int) ≤ ((den : Nat) : Int) := by rw [← hdeneq, hdeni, hp126] rw [hp126] at ht126 - omega + linarith [hevloI, ht126] exact_mod_cast h - have hq130 : scaleQ67 * num / den < 2 ^ 130 := by - have h1 : scaleQ67 * num / den ≤ scaleQ67 * num / 2 ^ 126 := + have hq130 : scale * num / den < 2 ^ 130 := by + have h1 : scale * num / den ≤ scale * num / 2 ^ 126 := Nat.div_le_div_left hden126 (Nat.two_pow_pos _) - have h2 : scaleQ67 * num / 2 ^ 126 < 2 ^ 130 := by + have h2 : scale * num / 2 ^ 126 < 2 ^ 130 := by rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] - calc scaleQ67 * num < 2 ^ 256 := hfit + calc scale * num < 2 ^ 256 := hfit _ = 2 ^ 130 * 2 ^ 126 := by norm_num - omega - have hr0nat : int256 (r0Tree x) = ((scaleQ67 * num / den : Nat) : Int) := by + exact lt_of_le_of_lt h1 h2 + have hr0nat : int256 (r0ScaledTree scale x) = ((scale * num / den : Nat) : Int) := by rw [hr0q] exact int256_of_lt (by have : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num @@ -117,17 +119,14 @@ theorem r0_floor_sandwich {x : Nat} (hx : x < 2 ^ 256) have hgoalnum : (evTree x : Int) + int256 (todTree x) = (num : Int) := by rw [← hnumi, hnumeq] have hgoalden : (evTree x : Int) - int256 (todTree x) = (den : Int) := by rw [← hdeni, hdeneq] rw [hr0nat, hgoalnum, hgoalden] - have hscn : scaleQ67 = 0x6f05b59d3b2000000000000000000000 := rfl constructor - · have hInt : ((scaleQ67 * num / den : Nat) : Int) * ((den : Nat) : Int) ≤ - ((scaleQ67 * num : Nat) : Int) := by exact_mod_cast hfloor_lo - rw [hscn] at hInt ⊢ + · have hInt : ((scale * num / den : Nat) : Int) * ((den : Nat) : Int) ≤ + ((scale * num : Nat) : Int) := by exact_mod_cast hfloor_lo push_cast at hInt ⊢ linarith [hInt] - · have hInt : ((scaleQ67 * num : Nat) : Int) < - (((scaleQ67 * num / den : Nat) : Int) + 1) * ((den : Nat) : Int) := by + · have hInt : ((scale * num : Nat) : Int) < + (((scale * num / den : Nat) : Int) + 1) * ((den : Nat) : Int) := by exact_mod_cast hfloor_hi - rw [hscn] at hInt ⊢ push_cast at hInt ⊢ linarith [hInt] @@ -144,13 +143,13 @@ theorem den_ge_194 {x : Nat} (hx : x < 2 ^ 256) rw [show (2:Int)^126 = 85070591730234615865843651857942052864 from by norm_num] at ht126 omega -/-- On the nonpositive half `tod ≤ 0` and hence `r0 ≤ scaleQ67` (num ≤ den). -/ -theorem r0_le_scale_neg {x : Nat} (hx : x < 2 ^ 256) +/-- On the nonpositive half `tod ≤ 0` and hence `r0 ≤ scale` (num ≤ den). -/ +theorem r0_le_scale_neg {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : - int256 (r0Tree x) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW - set r0 := int256 (r0Tree x) with hr0def + int256 (r0ScaledTree scale x) ≤ (scale : Int) := by + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hshi hx hW + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef have hden072 : (330077261860684142693791478386293573392 : Int) ≤ ev - tod := by @@ -161,10 +160,10 @@ theorem r0_le_scale_neg {x : Nat} (hx : x < 2 ^ 256) have hodnn : (0:Int) ≤ (odTree x : Int) := Int.natCast_nonneg _ have : int256 (tTree x) * (odTree x : Int) ≤ 0 := mul_nonpos_of_nonpos_of_nonneg htneg hodnn nlinarith [htodlo, this] - -- r0·den ≤ scaleQ67·num ≤ scaleQ67·den (num ≤ den) - have hscnn : (0:Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by positivity - have hnumden : r0 * (ev - tod) ≤ (0x6f05b59d3b2000000000000000000000 : Int) * (ev - tod) := by - have h1 : r0 * (ev - tod) ≤ (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) := hfloor_lo + -- r0·den ≤ scale·num ≤ scale·den (num ≤ den) + have hscnn : (0:Int) ≤ (scale : Int) := Int.natCast_nonneg _ + have hnumden : r0 * (ev - tod) ≤ (scale : Int) * (ev - tod) := by + have h1 : r0 * (ev - tod) ≤ (scale : Int) * (ev + tod) := hfloor_lo nlinarith [h1, htodnp, hscnn] exact le_of_mul_le_mul_right hnumden hdenpos @@ -249,107 +248,111 @@ theorem tOd_bracket_neg {x : Nat} (hx : x < 2 ^ 256) /-- **Joint link-1 over (nonneg half, `r0 ≥ scaleQ67`)**: the shared even truncation cancels through the floor, `r0·DENv − scaleQ67·NUMv ≤ Wev·2⁵⁹⁰·(r0 − scaleQ67)`. -/ -theorem link1_over_tight {x : Nat} (hx : x < 2 ^ 256) - (hW : WideRegion x) +theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) - (hr0ge : (0x6f05b59d3b2000000000000000000000 : Int) ≤ int256 (r0Tree x)) : - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) - - (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ - 72572599271425 * 2 ^ 591 * (int256 (r0Tree x) - (0x6f05b59d3b2000000000000000000000 : Int)) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + (hr0ge : (scale : Int) ≤ int256 (r0ScaledTree scale x)) : + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) - + (scale : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ + 72572599271425 * 2 ^ 591 * (int256 (r0ScaledTree scale x) - (scale : Int)) := by + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hshi hx hW obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hW obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hW htnn unfold NUMv DENv - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef set t := int256 (tTree x) with htdef set Ep := (evNumV (vTree x) : Int) with hEpdef set Op := (odNumV (vTree x) : Int) with hOpdef - have hr0m : (0:Int) ≤ r0 - (0x6f05b59d3b2000000000000000000000 : Int) := by linarith [hr0ge] - have hr0p : (0:Int) ≤ r0 + (0x6f05b59d3b2000000000000000000000 : Int) := by linarith [hr0ge] + have hr0m : (0:Int) ≤ r0 - (scale : Int) := by linarith [hr0ge] + have hr0p : (0:Int) ≤ r0 + (scale : Int) := by linarith [hr0ge] -- Ep·2^110·(r0−2^126) ≤ (2^637·ev + Wev·2^590)·(r0−2^126) - have hterm1 : Ep * 2 ^ 111 * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) ≤ - (2 ^ 637 * ev + 72572599271425 * 2 ^ 591) * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) := by + have hterm1 : Ep * 2 ^ 111 * (r0 - (scale : Int)) ≤ + (2 ^ 637 * ev + 72572599271425 * 2 ^ 591) * (r0 - (scale : Int)) := by apply mul_le_mul_of_nonneg_right _ hr0m nlinarith [hEp_hi] -- −(t·Op)·(r0+2^126) ≤ −(2^637·tod)·(r0+2^126) - have hterm2 : 2 ^ 637 * tod * (r0 + (0x6f05b59d3b2000000000000000000000 : Int)) ≤ t * Op * (r0 + (0x6f05b59d3b2000000000000000000000 : Int)) := + have hterm2 : 2 ^ 637 * tod * (r0 + (scale : Int)) ≤ t * Op * (r0 + (scale : Int)) := mul_le_mul_of_nonneg_right (by linarith [htOp_lo]) hr0p -- floor: r0·den − 2^126·num ≤ 0, scaled by 2^637 - have hfloor : r0 * (ev - tod) - (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] - have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod)) ≤ 0 := + have hfloor : r0 * (ev - tod) - (scale : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] + have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (scale : Int) * (ev + tod)) ≤ 0 := mul_nonpos_of_nonneg_of_nonpos (by positivity) hfloor nlinarith [hterm1, hterm2, hfloor638] /-- **Link-1 over (nonneg half, `r0 ≤ scaleQ67`)**: the residue is nonpositive outright. -/ -theorem link1_over_small {x : Nat} (hx : x < 2 ^ 256) - (hW : WideRegion x) +theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) - (hr0le : int256 (r0Tree x) ≤ (0x6f05b59d3b2000000000000000000000 : Int)) : - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) - - (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ 0 := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + (hr0le : int256 (r0ScaledTree scale x) ≤ (scale : Int)) : + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) - + (scale : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ 0 := by + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hshi hx hW obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW obtain ⟨htOp_lo, _⟩ := tOd_bracket_nonneg hx hW htnn unfold NUMv DENv - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef set t := int256 (tTree x) with htdef set Ep := (evNumV (vTree x) : Int) with hEpdef set Op := (odNumV (vTree x) : Int) with hOpdef - obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW + obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW have hr0nn : (0:Int) ≤ r0 := by have : (0:Int) < 2 ^ 124 := by positivity linarith [hr0lo] - have hr0m : r0 - (0x6f05b59d3b2000000000000000000000 : Int) ≤ 0 := by linarith [hr0le] - have hr0p : (0:Int) ≤ r0 + (0x6f05b59d3b2000000000000000000000 : Int) := by positivity + have hr0m : r0 - (scale : Int) ≤ 0 := by linarith [hr0le] + have hr0p : (0:Int) ≤ r0 + (scale : Int) := by + have := Int.natCast_nonneg scale + linarith [hr0nn] -- Ep·2^110·(r0−2^126) ≤ 2^637·ev·(r0−2^126) (Ep·2^110 ≥ 2^637·ev, factor ≤ 0) - have hterm1 : Ep * 2 ^ 111 * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) ≤ 2 ^ 637 * ev * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) := by + have hterm1 : Ep * 2 ^ 111 * (r0 - (scale : Int)) ≤ 2 ^ 637 * ev * (r0 - (scale : Int)) := by apply mul_le_mul_of_nonpos_right _ hr0m nlinarith [hEp_lo] - have hterm2 : 2 ^ 637 * tod * (r0 + (0x6f05b59d3b2000000000000000000000 : Int)) ≤ t * Op * (r0 + (0x6f05b59d3b2000000000000000000000 : Int)) := + have hterm2 : 2 ^ 637 * tod * (r0 + (scale : Int)) ≤ t * Op * (r0 + (scale : Int)) := mul_le_mul_of_nonneg_right (by linarith [htOp_lo]) hr0p - have hfloor : r0 * (ev - tod) - (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] - have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod)) ≤ 0 := + have hfloor : r0 * (ev - tod) - (scale : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] + have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (scale : Int) * (ev + tod)) ≤ 0 := mul_nonpos_of_nonneg_of_nonpos (by positivity) hfloor nlinarith [hterm1, hterm2, hfloor638] /-- **Link-1 over (nonpositive half)**: the even truncation drops (`r0 ≤ scaleQ67`); the odd truncation survives attenuated to the `t`-scale: `r0·DENv − scaleQ67·NUMv ≤ Wod·2⁴⁸⁰·(−t)·(r0 + scaleQ67)`. -/ -theorem link1_over_neg {x : Nat} (hx : x < 2 ^ 256) - (hW : WideRegion x) +theorem link1_over_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) - - (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ - 269746241 * 2 ^ 480 * (-(int256 (tTree x))) * (int256 (r0Tree x) + (0x6f05b59d3b2000000000000000000000 : Int)) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) - + (scale : Int) * NUMv (vTree x) (int256 (tTree x)) ≤ + 269746241 * 2 ^ 480 * (-(int256 (tTree x))) * (int256 (r0ScaledTree scale x) + (scale : Int)) := by + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hshi hx hW obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW obtain ⟨_, htOp_lo⟩ := tOd_bracket_neg hx hW htneg - have hr0le := r0_le_scale_neg hx hW htneg + have hr0le := r0_le_scale_neg hshi hx hW htneg unfold NUMv DENv - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef set t := int256 (tTree x) with htdef set Ep := (evNumV (vTree x) : Int) with hEpdef set Op := (odNumV (vTree x) : Int) with hOpdef - obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW + obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW have hr0nn : (0:Int) ≤ r0 := by have : (0:Int) < 2 ^ 124 := by positivity linarith [hr0lo] - have hr0m : r0 - (0x6f05b59d3b2000000000000000000000 : Int) ≤ 0 := by linarith [hr0le] - have hr0p : (0:Int) ≤ r0 + (0x6f05b59d3b2000000000000000000000 : Int) := by positivity - have hterm1 : Ep * 2 ^ 111 * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) ≤ 2 ^ 637 * ev * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) := by + have hr0m : r0 - (scale : Int) ≤ 0 := by linarith [hr0le] + have hr0p : (0:Int) ≤ r0 + (scale : Int) := by + have := Int.natCast_nonneg scale + linarith [hr0nn] + have hterm1 : Ep * 2 ^ 111 * (r0 - (scale : Int)) ≤ 2 ^ 637 * ev * (r0 - (scale : Int)) := by apply mul_le_mul_of_nonpos_right _ hr0m nlinarith [hEp_lo] -- −(t·Op)·(r0+2^126) ≤ (−2^637·tod + Wod·2^480·(−t))·(r0+2^126) - have hterm2 : (2 ^ 637 * tod - 269746241 * 2 ^ 480 * (-t)) * (r0 + (0x6f05b59d3b2000000000000000000000 : Int)) ≤ - t * Op * (r0 + (0x6f05b59d3b2000000000000000000000 : Int)) := + have hterm2 : (2 ^ 637 * tod - 269746241 * 2 ^ 480 * (-t)) * (r0 + (scale : Int)) ≤ + t * Op * (r0 + (scale : Int)) := mul_le_mul_of_nonneg_right htOp_lo hr0p - have hfloor : r0 * (ev - tod) - (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] - have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod)) ≤ 0 := + have hfloor : r0 * (ev - tod) - (scale : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] + have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (scale : Int) * (ev + tod)) ≤ 0 := mul_nonpos_of_nonneg_of_nonpos (by positivity) hfloor nlinarith [hterm1, hterm2, hfloor638] @@ -748,57 +751,66 @@ theorem num_le_145_den {x : Nat} (hx : x < 2 ^ 256) -- 100·(10000·num) ≤ 100·(14145·den + 28290) ≤ 10000·(145·den) since 355·den ≥ 2829000 nlinarith [hceil, hden] -/-- The quotient cap: `10⁴·(r0 − scaleQ67) ≤ 4146·scaleQ67` on the nonneg half. -/ -theorem r0_cap {x : Nat} (hx : x < 2 ^ 256) +/-- The quotient cap: `10⁴·(r0 − scale) ≤ 4146·scale` on the nonneg half. -/ +theorem r0_cap {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - 10000 * (int256 (r0Tree x) - (0x6f05b59d3b2000000000000000000000 : Int)) ≤ 4146 * (0x6f05b59d3b2000000000000000000000 : Int) := by - obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hx hW + 10000 * (int256 (r0ScaledTree scale x) - (scale : Int)) ≤ 4146 * (scale : Int) := by + obtain ⟨hfloor_lo, _⟩ := r0_floor_sandwich hshi hx hW have hceil := num_ceiling hx hW htnn have hden := den_ge_194 hx hW - set r0 := int256 (r0Tree x) with hr0def + have hSnn : (0:Int) ≤ (scale : Int) := Int.natCast_nonneg _ + set r0 := int256 (r0ScaledTree scale x) with hr0def set num := (evTree x : Int) + int256 (todTree x) with hnumdef set den := (evTree x : Int) - int256 (todTree x) with hdendef have hdenpos : (0:Int) < den := lt_of_lt_of_le (by norm_num) hden -- 10000·(r0−S)·den ≤ S·(10000·num − 10000·den) ≤ S·(4145·den + 28290) ≤ 4146·S·den - have h1 : 10000 * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) * den ≤ (0x6f05b59d3b2000000000000000000000 : Int) * (4145 * den + 28290) := by - nlinarith [hfloor_lo, hceil] - have h2 : (0x6f05b59d3b2000000000000000000000 : Int) * (4145 * den + 28290) ≤ 4146 * (0x6f05b59d3b2000000000000000000000 : Int) * den := by - nlinarith [hden] - have hchain : 10000 * (r0 - (0x6f05b59d3b2000000000000000000000 : Int)) * den ≤ 4146 * (0x6f05b59d3b2000000000000000000000 : Int) * den := le_trans h1 h2 + have h1 : 10000 * (r0 - (scale : Int)) * den ≤ (scale : Int) * (4145 * den + 28290) := by + have hceilS := mul_le_mul_of_nonneg_left hceil hSnn + nlinarith [hfloor_lo, hceilS] + have h2 : (scale : Int) * (4145 * den + 28290) ≤ 4146 * (scale : Int) * den := by + have hdS := mul_le_mul_of_nonneg_left (show (28290:Int) ≤ den by linarith [hden]) hSnn + nlinarith [hdS] + have hchain : 10000 * (r0 - (scale : Int)) * den ≤ 4146 * (scale : Int) * den := le_trans h1 h2 exact le_of_mul_le_mul_right hchain hdenpos /-! ## The per-point never-over (nonnegative half) -/ /-- The link-1 jitter divided by `DENv` stays inside its budget (nonneg half): `Wev·2⁵⁹⁰·(r0 − scaleQ67)/DENv ≤ (5¹⁸/2⁴⁰)·2170557036555806152/10¹⁹`. -/ -theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) +theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - (72572599271425 : Real) * 2 ^ 591 * ((int256 (r0Tree x) : Real) - 0x6f05b59d3b2000000000000000000000) / + (72572599271425 : Real) * 2 ^ 591 * ((int256 (r0ScaledTree scale x) : Real) - (scale : Real)) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW - set r0 := int256 (r0Tree x) with hr0def + have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h + set r0 := int256 (r0ScaledTree scale x) with hr0def set t := int256 (tTree x) with htdef set v := vTree x with hvdef have hD : 1108965543718 * 2 ^ 725 ≤ DENv v t := DENv_ge_over (by omega) hthi have hDpos : (0:Int) < DENv v t := lt_of_lt_of_le (by positivity) hD have hDR : (0:Real) < (DENv v t : Real) := by exact_mod_cast hDpos - rcases le_or_gt ((r0:Real) - 0x6f05b59d3b2000000000000000000000) 0 with hle0 | hgt0 - · have hnumneg : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) ≤ 0 := + rcases le_or_gt ((r0:Real) - (scale : Real)) 0 with hle0 | hgt0 + · have hnumneg : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) ≤ 0 := mul_nonpos_of_nonneg_of_nonpos (by positivity) hle0 - have : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) / (DENv v t : Real) ≤ 0 := + have : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) / (DENv v t : Real) ≤ 0 := div_nonpos_of_nonpos_of_nonneg hnumneg (le_of_lt hDR) have hpos : (0:Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by positivity linarith [this, hpos] · rw [div_le_iff₀ hDR] - have hcap := r0_cap hx hW htnn - have hcapR : (r0 : Real) - 0x6f05b59d3b2000000000000000000000 ≤ 4146 * 0x6f05b59d3b2000000000000000000000 / 10000 := by + have hcap := r0_cap hshi hx hW htnn + have hcapR : (r0 : Real) - (scale : Real) ≤ 4146 * 0x6f05b59d3b2000000000000000000000 / 10000 := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hcap push_cast at h - linarith [h] + linarith [h, hshiR] obtain ⟨hDEN_ge, _⟩ := DENv_runtime_bracket hx hW htnn have hden := den_ge_194 hx hW have hDENlow : (2:Int) ^ 637 * (330077261860684142693791478386293573392 - 2) ≤ DENv v t := by @@ -811,14 +823,14 @@ theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hDENlow push_cast at h linarith [h] - have hnum_le : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) ≤ + have hnum_le : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) ≤ (72572599271425 : Real) * 2 ^ 591 * (4146 * 0x6f05b59d3b2000000000000000000000 / 10000) := mul_le_mul_of_nonneg_left hcapR (by positivity) have hbudget : (72572599271425 : Real) * 2 ^ 591 * (4146 * 0x6f05b59d3b2000000000000000000000 / 10000) ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * ((2:Real) ^ 637 * (330077261860684142693791478386293573392 - 2)) := by norm_num - calc (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) + calc (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) ≤ (72572599271425 : Real) * 2 ^ 591 * (4146 * 0x6f05b59d3b2000000000000000000000 / 10000) := hnum_le _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * ((2:Real) ^ 637 * (330077261860684142693791478386293573392 - 2)) := hbudget @@ -827,20 +839,27 @@ theorem jitter_over_budget {x : Nat} (hx : x < 2 ^ 256) /-- **The per-point never-over (nonneg half).** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` with the four-link budget `B = 5737291786393199862/10¹⁹` itemized in the module header. -/ -theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) - (hW : WideRegion x) +theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + + (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW + have hsRnn : (0:Real) ≤ (scale : Real) := by positivity + have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h set t := int256 (tTree x) with htdef set v := vTree x with hvdef have htdom : t ≤ (ExpCertV.H129 : Int) := by rw [show ((ExpCertV.H129 : Nat) : Int) = 235865763225513294137944142764154484399 from by unfold ExpCertV.H129; norm_num] exact hthi - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def have hD : 1108965543718 * 2 ^ 725 ≤ DENv v t := DENv_ge_over (by omega) hthi have hDpos : (0:Int) < DENv v t := lt_of_lt_of_le (by positivity) hD have hDR : (0:Real) < (DENv v t : Real) := by exact_mod_cast hDpos @@ -848,26 +867,26 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by have : (0:Int) < evalPoly ExpCertV.denExpV t := lt_of_lt_of_le one_pos hDE exact_mod_cast this - -- link 1: r0 ≤ scaleQ67·Qv + jitter - have hlink1 : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + + -- link 1: r0 ≤ scale·Qv + jitter + have hlink1 : (r0 : Real) ≤ (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by - rcases le_or_gt r0 (0x6f05b59d3b2000000000000000000000 : Int) with hsm | hbg - · have hi := link1_over_small hx hW htnn hsm - have hiR : (r0 : Real) * (DENv v t : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) := by + rcases le_or_gt r0 (scale : Int) with hsm | hbg + · have hi := link1_over_small hslo hshi hx hW htnn hsm + have hiR : (r0 : Real) * (DENv v t : Real) ≤ (scale : Real) * (NUMv v t : Real) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] - have hr0le : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) := by + have hr0le : (r0 : Real) ≤ (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) := by rw [mul_div_assoc', le_div_iff₀ hDR]; linarith [hiR] have hBJnn : (0:Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by positivity linarith [hr0le, hBJnn] - · have hi := link1_over_tight hx hW htnn (le_of_lt hbg) - have hjointR : (r0 : Real) * (DENv v t : Real) - (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) ≤ - (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) := by + · have hi := link1_over_tight hslo hshi hx hW htnn (le_of_lt hbg) + have hjointR : (r0 : Real) * (DENv v t : Real) - (scale : Real) * (NUMv v t : Real) ≤ + (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] - have hstep : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) / (DENv v t : Real) + - (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - 0x6f05b59d3b2000000000000000000000) / (DENv v t : Real) := by + have hstep : (r0 : Real) ≤ (scale : Real) * (NUMv v t : Real) / (DENv v t : Real) + + (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) / (DENv v t : Real) := by rw [div_add_div_same, le_div_iff₀ hDR]; nlinarith [hjointR, hDR] rw [mul_div_assoc] at hstep - linarith [hstep, jitter_over_budget hx hW htnn] + linarith [hstep, jitter_over_budget hshi hx hW htnn] -- link 2: 2^126·Qv ≤ 2^126·(NE/DE) + grain obtain ⟨_, hgran⟩ := gran_over_pair hx hW htnn -- link 3: NE/DE ≤ Et·Mp; Mp excess ≤ √2·2^126/(2^131−1) @@ -923,7 +942,8 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) have : (2 ^ 126 : Real) / (32 * 2 ^ 129) = 1 / 256 := by norm_num rw [this]; nlinarith [hsqrt2_hi, hsqrt2_nn] linarith [h2, h3, h4] - -- assemble + -- assemble: links 2–4 at the 2^126 normalization, then rescale by `scale/2^126` and relax the + -- constant to the maximal scale have hNEMp : (2 ^ 126 : Real) * ((NE : Real) / (DE : Real)) ≤ (2 ^ 126 : Real) * Et + (2 ^ 126 : Real) * Et * (Mp - 1) := by have h := mul_le_mul_of_nonneg_left hNEDE_le (by positivity : (0:Real) ≤ (2 ^ 126 : Real)) @@ -931,25 +951,39 @@ theorem r0_real_over_tight {x : Nat} (hx : x < 2 ^ 256) have hEtErt : (2 ^ 126 : Real) * Et ≤ (2 ^ 126 : Real) * Ert + 55242717280199026 / 10000000000000000000 := by nlinarith [hcGap1] + have h234 : (2 ^ 126 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ + (2 ^ 126 : Real) * Ert + 3566734749837393710 / 10000000000000000000 := by + linarith [hgran, hNEMp, hcMp, hEtErt] + have h234S := mul_le_mul_of_nonneg_left h234 hsRnn + have hCs : (scale : Real) * (3566734749837393710 / 10000000000000000000) ≤ + (0x6f05b59d3b2000000000000000000000 : Real) * (3566734749837393710 / 10000000000000000000) := + mul_le_mul_of_nonneg_right hshiR (by positivity) rw [hErtdef] at * - linarith [hlink1, hgran, hNEMp, hcMp, hEtErt] + nlinarith [hlink1, h234S, hCs] /-! ## The per-point never-over (nonpositive half) -/ /-- The link-1 jitter budget on the nonpositive half: `Wod·2⁴⁸⁰·(−t)·(r0 + scaleQ67)/DENv ≤ (5¹⁸/2⁴⁰)·2170557036555806152/10¹⁹`. -/ -theorem jitter_over_budget_neg {x : Nat} (hx : x < 2 ^ 256) +theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (269746241 : Real) * 2 ^ 480 * (-(int256 (tTree x) : Real)) * - ((int256 (r0Tree x) : Real) + 0x6f05b59d3b2000000000000000000000) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ + ((int256 (r0ScaledTree scale x) : Real) + (scale : Real)) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by obtain ⟨htlo, _⟩ := tTree_in_cert_domain_wide hx hW - have hr0le := r0_le_scale_neg hx hW htneg - obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW + have hr0le := r0_le_scale_neg hshi hx hW htneg + obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW have hDEN_ge := DENv_ge_ev_neg hx hW htneg obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 - set r0 := int256 (r0Tree x) with hr0def + have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h + set r0 := int256 (r0ScaledTree scale x) with hr0def set t := int256 (tTree x) with htdef set v := vTree x with hvdef have hev : (415147853590918758559635130244235626256 : Int) ≤ (evTree x : Int) := by @@ -971,19 +1005,20 @@ theorem jitter_over_budget_neg {x : Nat} (hx : x < 2 ^ 256) have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr htlo push_cast at h linarith [h] - have hr0pR : (0:Real) ≤ (r0 : Real) + 0x6f05b59d3b2000000000000000000000 := by + have hr0pR : (0:Real) ≤ (r0 : Real) + (scale : Real) := by have h : (0:Int) ≤ r0 := by - have : (0:Int) < 2 ^ 124 := by positivity + have : (0:Int) < 2 ^ 123 := by positivity linarith [hr0lo] have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr h push_cast at this - linarith [this] - have hr0pH : (r0 : Real) + 0x6f05b59d3b2000000000000000000000 ≤ + have hsnn : (0:Real) ≤ (scale : Real) := by positivity + linarith [this, hsnn] + have hr0pH : (r0 : Real) + (scale : Real) ≤ 2 * 0x6f05b59d3b2000000000000000000000 := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h - linarith [h] - have hnum_le : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + 0x6f05b59d3b2000000000000000000000) ≤ + linarith [h, hshiR] + have hnum_le : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * (2 * (0x6f05b59d3b2000000000000000000000 : Real)) := by have h1 : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 := @@ -997,7 +1032,7 @@ theorem jitter_over_budget_neg {x : Nat} (hx : x < 2 ^ 256) (2 * (0x6f05b59d3b2000000000000000000000 : Real)) ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * ((2:Real) ^ 637 * 415147853590918758559635130244235626256) := by norm_num - calc (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + 0x6f05b59d3b2000000000000000000000) + calc (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * (2 * (0x6f05b59d3b2000000000000000000000 : Real)) := hnum_le _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * @@ -1007,34 +1042,42 @@ theorem jitter_over_budget_neg {x : Nat} (hx : x < 2 ^ 256) /-- **The per-point never-over (nonpositive half).** The granularity is free here; the `Mp` factor and reduced-argument gap shrink (`Et ≤ 1`), so the same budget `B` covers the half. -/ -theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) +theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : - (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + + (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by have htdom := tdom_neg hx hW htneg have hvle := vTree_le_vmax_wide hx hW + have hsRnn : (0:Real) ≤ (scale : Real) := by positivity + have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h set t := int256 (tTree x) with htdef set v := vTree x with hvdef - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def have hD : 1108965543718 * 2 ^ 725 ≤ DENv v t := DENv_ge_neg (by omega) htneg have hDpos : (0:Int) < DENv v t := lt_of_lt_of_le (by positivity) hD have hDR : (0:Real) < (DENv v t : Real) := by exact_mod_cast hDpos have hDEpos : (0:Int) < evalPoly ExpCertV.denExpV t := (certNE_pos_neg_aux htneg htdom).2 have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by exact_mod_cast hDEpos - -- link 1: r0 ≤ scaleQ67·Qv + jitter - have hlink1 : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + + -- link 1: r0 ≤ scale·Qv + jitter + have hlink1 : (r0 : Real) ≤ (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by - have hi := link1_over_neg hx hW htneg - have hiR : (r0 : Real) * (DENv v t : Real) - (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) ≤ - (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + 0x6f05b59d3b2000000000000000000000) := by + have hi := link1_over_neg hslo hshi hx hW htneg + have hiR : (r0 : Real) * (DENv v t : Real) - (scale : Real) * (NUMv v t : Real) ≤ + (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] - have hstep : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * (NUMv v t : Real) / (DENv v t : Real) + - (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + 0x6f05b59d3b2000000000000000000000) / + have hstep : (r0 : Real) ≤ (scale : Real) * (NUMv v t : Real) / (DENv v t : Real) + + (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) / (DENv v t : Real) := by rw [div_add_div_same, le_div_iff₀ hDR]; nlinarith [hiR, hDR] rw [mul_div_assoc] at hstep - linarith [hstep, jitter_over_budget_neg hx hW htneg] + linarith [hstep, jitter_over_budget_neg hslo hshi hx hW htneg] -- link 2 (free): Qv ≤ NE/DE obtain ⟨hgran1, _⟩ := gran_under_pair hx hW htneg -- link 3: NE/DE ≤ Et·Mpp with Et ≤ 1 @@ -1084,7 +1127,8 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) have h4 : (2 ^ 126 : Real) * ((1 / (32 * (2 ^ 129 : Real))) * 1) ≤ 55242717280199026 / 10000000000000000000 := by norm_num linarith [h2, h3, h4] - -- assemble + -- assemble: links 2–4 at the 2^126 normalization, then rescale by `scale/2^126` and relax the + -- constant to the maximal scale have hNEMp : (2 ^ 126 : Real) * ((NE : Real) / (DE : Real)) ≤ (2 ^ 126 : Real) * Et + (2 ^ 126 : Real) * Et * (Mpp - 1) := by have h := mul_le_mul_of_nonneg_left hNEDE_le (by positivity : (0:Real) ≤ (2 ^ 126 : Real)) @@ -1094,18 +1138,38 @@ theorem r0_real_over_tight_neg {x : Nat} (hx : x < 2 ^ 256) have hgranR : (2 ^ 126 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (2 ^ 126 : Real) * ((NE : Real) / (DE : Real)) := mul_le_mul_of_nonneg_left hgran1 (by positivity) + have h234 : (2 ^ 126 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ + (2 ^ 126 : Real) * Ert + 276213586400995128 / 10000000000000000000 := by + linarith [hgranR, hNEMp, hcMp, hEtErt] + have h234S := mul_le_mul_of_nonneg_left h234 hsRnn + have hCs : (scale : Real) * (276213586400995128 / 10000000000000000000) ≤ + (0x6f05b59d3b2000000000000000000000 : Real) * (276213586400995128 / 10000000000000000000) := + mul_le_mul_of_nonneg_right hshiR (by positivity) rw [hErtdef] at * - linarith [hlink1, hgranR, hNEMp, hcMp, hEtErt] + nlinarith [hlink1, h234S, hCs] + +/-- **Per-point never-over (tight, any sign):** `r0 ≤ scale·exp(rt) + (5¹⁸/2⁴⁰)·B` +(the budget's image is strictly below `MARGIN = 1`; the budget is certified at the maximal +scale, and smaller scales only shrink the true error). -/ +theorem r0Scaled_real_over_within {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) : + (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg + · exact r0_real_over_tight hslo hshi hx hW htnn + · exact r0_real_over_tight_neg hslo hshi hx hW (le_of_lt htneg) -/-- **Per-point never-over (tight, any sign):** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴⁰)·B` -(the budget's image is strictly below `MARGIN = 1`). -/ theorem r0_real_over_within_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by - rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg - · exact r0_real_over_tight hx hW htnn - · exact r0_real_over_tight_neg hx hW (le_of_lt htneg) + have h := r0Scaled_real_over_within (scale := scaleQ67) (by unfold scaleQ67; norm_num) + (le_refl _) hx hW + rw [r0Tree_eq_scaled] + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [← hs] + exact h theorem r0_real_over_within {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean index 69ef33935..ae01f96f5 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean @@ -3,8 +3,9 @@ import ExpProof.Floor.R0Exp /-! # The deficit (under) side of the per-point `r0`-vs-`exp` bridge, and the seam bound -This module contains the counterpart to the never-over `r0_real_over_within`: the per-point deficit -`scaleQ67·exp(rt) ≤ r0 + 2993/1000` (`r0_real_under_within`), both signs, with the same four-link chain: +This module contains the counterpart to the never-over `r0Scaled_real_over_within`: the per-point +deficit `scale·exp(rt) ≤ r0 + 2993/1000` (`r0Scaled_real_under_within`), both signs and any scale +`2¹²⁵ ≤ scale ≤ scaleQ67`, with the same four-link chain: 1. link-1 deficit against the grid rational including the `div` floor, `≤ 2378/1000`; 2. the argument granularity (`Floor.GranV`) — free on the `t ≥ 0` half, `≤ (5¹⁸/2⁴¹)·1644901622230542074/10¹⁹` @@ -78,14 +79,15 @@ theorem exp_reducedArg_le_sqrt2bound {x : Nat} (hx : x < 2 ^ 256) /-! ## The `r0` bracket on the nonneg half -/ /-- `r0` is bracketed on the nonneg half: `scaleQ67 ≤ r0` and `100·r0 ≤ 145·scaleQ67`. -/ -theorem r0_bracket_nonneg {x : Nat} (hx : x < 2 ^ 256) +theorem r0_bracket_nonneg {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - (0x6f05b59d3b2000000000000000000000 : Int) ≤ int256 (r0Tree x) ∧ - 100 * (int256 (r0Tree x)) ≤ 145 * (0x6f05b59d3b2000000000000000000000 : Int) := by - obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hx hW + (scale : Int) ≤ int256 (r0ScaledTree scale x) ∧ + 100 * (int256 (r0ScaledTree scale x)) ≤ 145 * (scale : Int) := by + obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hshi hx hW have h145 := num_le_145_den hx hW htnn - set r0 := int256 (r0Tree x) with hr0def + have hSnn : (0:Int) ≤ (scale : Int) := Int.natCast_nonneg _ + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef have hden072 : (330077261860684142693791478386293573392 : Int) ≤ ev - tod := by @@ -99,17 +101,18 @@ theorem r0_bracket_nonneg {x : Nat} (hx : x < 2 ^ 256) have hpos : (0:Int) ≤ int256 (tTree x) * (odTree x : Int) := mul_nonneg htnn hodnn nlinarith [htod, hpos] refine ⟨?_, ?_⟩ - · -- 2^126 ≤ r0: 2^126·num < (r0+1)·den, num ≥ den ⟹ 2^126·den < (r0+1)·den ⟹ 2^126 < r0+1 - have hnumden : (0x6f05b59d3b2000000000000000000000 : Int) * (ev - tod) ≤ (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) := by nlinarith [htodnn] - have h : (0x6f05b59d3b2000000000000000000000 : Int) * (ev - tod) < (r0 + 1) * (ev - tod) := lt_of_le_of_lt hnumden hfloor_hi + · -- scale ≤ r0: scale·num < (r0+1)·den, num ≥ den ⟹ scale·den < (r0+1)·den ⟹ scale < r0+1 + have hnumden : (scale : Int) * (ev - tod) ≤ (scale : Int) * (ev + tod) := by + nlinarith [htodnn, hSnn] + have h : (scale : Int) * (ev - tod) < (r0 + 1) * (ev - tod) := lt_of_le_of_lt hnumden hfloor_hi have := lt_of_mul_lt_mul_right h (le_of_lt hdenpos) omega - · -- 100·r0 ≤ 145·2^126: 100·r0·den ≤ 100·2^126·num ≤ 2^126·145·den - have h1 : 100 * (r0 * (ev - tod)) ≤ 100 * ((0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod)) := + · -- 100·r0 ≤ 145·scale: 100·r0·den ≤ 100·scale·num ≤ scale·145·den + have h1 : 100 * (r0 * (ev - tod)) ≤ 100 * ((scale : Int) * (ev + tod)) := mul_le_mul_of_nonneg_left hfloor_lo (by norm_num) - have h2 : (0x6f05b59d3b2000000000000000000000 : Int) * (100 * (ev + tod)) ≤ (0x6f05b59d3b2000000000000000000000 : Int) * (145 * (ev - tod)) := - mul_le_mul_of_nonneg_left h145 (by positivity) - have hchain : 100 * r0 * (ev - tod) ≤ 145 * (0x6f05b59d3b2000000000000000000000 : Int) * (ev - tod) := by nlinarith [h1, h2] + have h2 : (scale : Int) * (100 * (ev + tod)) ≤ (scale : Int) * (145 * (ev - tod)) := + mul_le_mul_of_nonneg_left h145 hSnn + have hchain : 100 * r0 * (ev - tod) ≤ 145 * (scale : Int) * (ev - tod) := by nlinarith [h1, h2] exact le_of_mul_le_mul_right hchain hdenpos /-! ## The piecewise link-1 carry table -/ @@ -182,42 +185,51 @@ theorem link1Pieces_hold : ∀ p ∈ ExpCertV.granPieces, Link1PieceOK p := by costs one denominator; the odd-truncation carry `(2⁶³⁷ + Wod·2⁴⁸⁰·t)·(scaleQ67 + r0)` is aggregated piecewise over `granPieces` (`t ≤ T` and `DO·2⁷²⁵ ≤ DENv` per piece, the certified `Link1PieceOK` row closing the quadratic), fitting `1.378` denominators. -/ -theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) +theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - 1000 * ((0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x))) ≤ + 1000 * ((scale : Int) * NUMv (vTree x) (int256 (tTree x)) - + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x))) ≤ 2378 * DENv (vTree x) (int256 (tTree x)) := by - obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hx hW + obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hshi hx hW obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hW htnn - obtain ⟨hr0lo, hr0hi145⟩ := r0_bracket_nonneg hx hW htnn + obtain ⟨hr0lo, hr0hi145⟩ := r0_bracket_nonneg hshi hx hW htnn obtain ⟨hDEN_lo, hDEN_up⟩ := DENv_runtime_bracket hx hW htnn - have hLHS : (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) ≤ + have hshiI : (scale : Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by + have h : ((scale : Nat) : Int) ≤ ((scaleQ67 : Nat) : Int) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Int) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h + have hLHS : (scale : Int) * NUMv (vTree x) (int256 (tTree x)) - + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + - (2 ^ 637 + 269746241 * 2 ^ 480 * int256 (tTree x)) * ((0x6f05b59d3b2000000000000000000000 : Int) + int256 (r0Tree x)) := by + (2 ^ 637 + 269746241 * 2 ^ 480 * int256 (tTree x)) * ((scale : Int) + int256 (r0ScaledTree scale x)) := by unfold NUMv DENv - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef set t := int256 (tTree x) with htdef set Ep := (evNumV (vTree x) : Int) with hEpdef set Op := (odNumV (vTree x) : Int) with hOpdef - have h2126r0_np : (0x6f05b59d3b2000000000000000000000 : Int) - r0 ≤ 0 := by linarith [hr0lo] - have hr0p_nn : (0:Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) + r0 := by linarith [hr0lo] - -- Ep·2^110·(2^126−r0) ≤ 2^637·ev·(2^126−r0) - have hterm1 : Ep * 2 ^ 111 * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) ≤ 2 ^ 637 * ev * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) := by + have h2126r0_np : (scale : Int) - r0 ≤ 0 := by linarith [hr0lo] + have hr0p_nn : (0:Int) ≤ (scale : Int) + r0 := by + have := Int.natCast_nonneg scale + linarith [hr0lo] + -- Ep·2^110·(scale−r0) ≤ 2^637·ev·(scale−r0) + have hterm1 : Ep * 2 ^ 111 * ((scale : Int) - r0) ≤ 2 ^ 637 * ev * ((scale : Int) - r0) := by apply mul_le_mul_of_nonpos_right _ h2126r0_np nlinarith [hEp_lo] - -- t·Op·(2^126+r0) ≤ (2^637·tod + 2^637 + Wod·2^480·t)·(2^126+r0) - have hterm2 : t * Op * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) ≤ - (2 ^ 637 * tod + 2 ^ 637 + 269746241 * 2 ^ 480 * t) * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) := + -- t·Op·(scale+r0) ≤ (2^637·tod + 2^637 + Wod·2^480·t)·(scale+r0) + have hterm2 : t * Op * ((scale : Int) + r0) ≤ + (2 ^ 637 * tod + 2 ^ 637 + 269746241 * 2 ^ 480 * t) * ((scale : Int) + r0) := mul_le_mul_of_nonneg_right htOp_hi hr0p_nn - -- floor: 2^126·num − r0·den < den, scaled by 2^637 - have hfloor : (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) - r0 * (ev - tod) ≤ (ev - tod) := by + -- floor: scale·num − r0·den < den, scaled by 2^637 + have hfloor : (scale : Int) * (ev + tod) - r0 * (ev - tod) ≤ (ev - tod) := by linarith [hfloor_hi] - have hfloor638 : (2:Int) ^ 637 * ((0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) - r0 * (ev - tod)) ≤ + have hfloor638 : (2:Int) ^ 637 * ((scale : Int) * (ev + tod) - r0 * (ev - tod)) ≤ 2 ^ 637 * (ev - tod) := mul_le_mul_of_nonneg_left hfloor (by positivity) nlinarith [hterm1, hterm2, hfloor638] -- select the covering piece; its certified facts drive the aggregation @@ -231,13 +243,16 @@ theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) granPieces_ok _ hp (vTree x) hplo hphi have hrow := (link1Pieces_hold _ hp).1 have hcaps := granPieces_caps _ hp - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def set t := int256 (tTree x) with htdef set den := (evTree x : Int) - int256 (todTree x) with hdendef set D := DENv (vTree x) t with hDdef - set S := (0x6f05b59d3b2000000000000000000000 : Int) with hSdef + set S := (scale : Int) with hSdef set Op := (odNumV (vTree x) : Int) with hOpdef - have hSpos : (0 : Int) < S := by rw [hSdef]; norm_num + have hSpos : (0 : Int) < S := by + rw [hSdef] + exact_mod_cast lt_of_lt_of_le (by norm_num : (0:Nat) < 2 ^ 125) hslo + have hS67 : S ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by rw [hSdef]; exact hshiI have hr0nn : (0 : Int) ≤ r0 := le_trans (le_of_lt hSpos) hr0lo -- `t ≤ T` on the piece have htT : t ≤ T := by @@ -286,10 +301,35 @@ theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) nlinarith [htransfer] -- feed the certified piece row and cancel one factor of `DO·2^725` have hcoefT_nn : (0 : Int) ≤ 2 ^ 637 + 269746241 * 2 ^ 480 * T := by nlinarith [hTnn] + -- the certified row holds at the literal maximal scale; every scale coefficient on its + -- left-hand side is nonnegative, so it holds a fortiori at the symbolic scale + have hrow_s : 1000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * + (200 * S * (DO * 2 ^ 725) + 200 * S * T * odCap + 800 * S * 2 ^ 637)) + + 200000 * 2 ^ 637 * (DO * 2 ^ 725) ≤ + 137800 * ((DO * 2 ^ 725) * (DO * 2 ^ 725)) := by + have hS67S_nn : (0 : Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) - S := by + linarith [hS67] + have hOpcap_nn : (0 : Int) ≤ odCap := le_trans hOpnn hOple + have h1 : 200 * S * (DO * 2 ^ 725) ≤ + 200 * (0x6f05b59d3b2000000000000000000000 : Int) * (DO * 2 ^ 725) := by + nlinarith [mul_nonneg hS67S_nn (le_of_lt hDOpos')] + have h2 : 200 * S * T * odCap ≤ + 200 * (0x6f05b59d3b2000000000000000000000 : Int) * T * odCap := by + nlinarith [mul_nonneg hS67S_nn (mul_nonneg hTnn hOpcap_nn)] + have h3 : 800 * S * 2 ^ 637 ≤ + 800 * (0x6f05b59d3b2000000000000000000000 : Int) * 2 ^ 637 := by + nlinarith [hS67S_nn] + have hsum_le : 200 * S * (DO * 2 ^ 725) + 200 * S * T * odCap + 800 * S * 2 ^ 637 ≤ + 200 * (0x6f05b59d3b2000000000000000000000 : Int) * (DO * 2 ^ 725) + + 200 * (0x6f05b59d3b2000000000000000000000 : Int) * T * odCap + + 800 * (0x6f05b59d3b2000000000000000000000 : Int) * 2 ^ 637 := by + linarith [h1, h2, h3] + have hmul_le := mul_le_mul_of_nonneg_left hsum_le hcoefT_nn + linarith [hrow, hmul_le] have hXY : (100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + 200000 * 2 ^ 637) * (DO * 2 ^ 725) ≤ (137800 * (DO * 2 ^ 725)) * (DO * 2 ^ 725) := by have h1 := mul_le_mul_of_nonneg_left h100DO hcoefT_nn - nlinarith [h1, hrow] + nlinarith [h1, hrow_s] have hDIV : 100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + 200000 * 2 ^ 637 ≤ 137800 * (DO * 2 ^ 725) := le_of_mul_le_mul_right hXY hDOpos' @@ -304,25 +344,33 @@ theorem link1_under_int {x : Nat} (hx : x < 2 ^ 256) /-- **Link-1 under (nonpositive half)**: the same `2378/1000` budget, with no piece machinery: on this half `DENv = Ep·2¹¹¹ − t·Op ≥ 2⁶³⁸·ev`, so the even-truncation width and the `tod`-floor unit are absorbed against `2⁶³⁸·ev ≥ 2⁶³⁸·A0`. -/ -theorem link1_under_int_neg {x : Nat} (hx : x < 2 ^ 256) +theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : - 1000 * ((0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x))) ≤ + 1000 * ((scale : Int) * NUMv (vTree x) (int256 (tTree x)) - + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x))) ≤ 2378 * DENv (vTree x) (int256 (tTree x)) := by - obtain ⟨_, hfloor_hi⟩ := r0_floor_sandwich hx hW + obtain ⟨_, hfloor_hi⟩ := r0_floor_sandwich hshi hx hW obtain ⟨hEp_lo, hEp_hi, _, _⟩ := bridge_facts hx hW obtain ⟨htOp_hi, _⟩ := tOd_bracket_neg hx hW htneg - have hr0le := r0_le_scale_neg hx hW htneg - obtain ⟨hr0lo, _⟩ := r0Tree_bounds_wide hx hW + have hr0le := r0_le_scale_neg hshi hx hW htneg + obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 obtain ⟨htod_lo126, _, _, _⟩ := todTree_bound_wide hx hW - have hLHS : (0x6f05b59d3b2000000000000000000000 : Int) * NUMv (vTree x) (int256 (tTree x)) - - int256 (r0Tree x) * DENv (vTree x) (int256 (tTree x)) ≤ + have hshiI : (scale : Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by + have h : ((scale : Nat) : Int) ≤ ((scaleQ67 : Nat) : Int) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Int) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h + have hSnn : (0:Int) ≤ (scale : Int) := Int.natCast_nonneg _ + have hLHS : (scale : Int) * NUMv (vTree x) (int256 (tTree x)) - + int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + - 72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) + 2 * 2 ^ 637 * (0x6f05b59d3b2000000000000000000000 : Int) := by + 72572599271425 * 2 ^ 591 * (scale : Int) + 2 * 2 ^ 637 * (scale : Int) := by unfold NUMv DENv - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef set t := int256 (tTree x) with htdef @@ -331,33 +379,33 @@ theorem link1_under_int_neg {x : Nat} (hx : x < 2 ^ 256) have hr0nn : (0:Int) ≤ r0 := by have : (0:Int) < 2 ^ 123 := by positivity linarith [hr0lo] - have h2126r0_nn : (0:Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) - r0 := by linarith [hr0le] - have h2126r0_le : (0x6f05b59d3b2000000000000000000000 : Int) - r0 ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by linarith [hr0nn] - have hr0p_nn : (0:Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) + r0 := by positivity - have hr0p_le : (0x6f05b59d3b2000000000000000000000 : Int) + r0 ≤ 2 * (0x6f05b59d3b2000000000000000000000 : Int) := by linarith [hr0le] - -- Ep·2^110·(2^126−r0) ≤ 2^637·ev·(2^126−r0) + Wev·2^590·2^126 - have hterm1 : Ep * 2 ^ 111 * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) ≤ - 2 ^ 637 * ev * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) + 72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) := by - have h1 : Ep * 2 ^ 111 * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) ≤ - (2 ^ 637 * ev + 72572599271425 * 2 ^ 591) * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) := by + have h2126r0_nn : (0:Int) ≤ (scale : Int) - r0 := by linarith [hr0le] + have h2126r0_le : (scale : Int) - r0 ≤ (scale : Int) := by linarith [hr0nn] + have hr0p_nn : (0:Int) ≤ (scale : Int) + r0 := by linarith [hr0nn, hSnn] + have hr0p_le : (scale : Int) + r0 ≤ 2 * (scale : Int) := by linarith [hr0le] + -- Ep·2^110·(scale−r0) ≤ 2^637·ev·(scale−r0) + Wev·2^590·scale + have hterm1 : Ep * 2 ^ 111 * ((scale : Int) - r0) ≤ + 2 ^ 637 * ev * ((scale : Int) - r0) + 72572599271425 * 2 ^ 591 * (scale : Int) := by + have h1 : Ep * 2 ^ 111 * ((scale : Int) - r0) ≤ + (2 ^ 637 * ev + 72572599271425 * 2 ^ 591) * ((scale : Int) - r0) := by apply mul_le_mul_of_nonneg_right _ h2126r0_nn nlinarith [hEp_hi] - have h2 : (72572599271425 : Int) * 2 ^ 590 * ((0x6f05b59d3b2000000000000000000000 : Int) - r0) ≤ - 72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) := by - linarith [h2126r0_le, hr0nn] + have h2 : (72572599271425 : Int) * 2 ^ 590 * ((scale : Int) - r0) ≤ + 72572599271425 * 2 ^ 591 * (scale : Int) := by + nlinarith [h2126r0_le, hr0nn, hSnn] nlinarith [h1, h2] - -- t·Op·(2^126+r0) ≤ (2^637·tod + 2^637)·(2^126+r0) ≤ 2^637·tod·(2^126+r0) + 2·2^637·2^126 - have hterm2 : t * Op * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) ≤ - 2 ^ 637 * tod * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) + 2 * 2 ^ 637 * (0x6f05b59d3b2000000000000000000000 : Int) := by - have h1 : t * Op * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) ≤ (2 ^ 637 * tod + 2 ^ 637) * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) := + -- t·Op·(scale+r0) ≤ (2^637·tod + 2^637)·(scale+r0) ≤ 2^637·tod·(scale+r0) + 2·2^637·scale + have hterm2 : t * Op * ((scale : Int) + r0) ≤ + 2 ^ 637 * tod * ((scale : Int) + r0) + 2 * 2 ^ 637 * (scale : Int) := by + have h1 : t * Op * ((scale : Int) + r0) ≤ (2 ^ 637 * tod + 2 ^ 637) * ((scale : Int) + r0) := mul_le_mul_of_nonneg_right htOp_hi hr0p_nn - have h2 : (2:Int) ^ 637 * ((0x6f05b59d3b2000000000000000000000 : Int) + r0) ≤ 2 ^ 637 * (2 * (0x6f05b59d3b2000000000000000000000 : Int)) := + have h2 : (2:Int) ^ 637 * ((scale : Int) + r0) ≤ 2 ^ 637 * (2 * (scale : Int)) := mul_le_mul_of_nonneg_left hr0p_le (by positivity) nlinarith [h1, h2] - -- floor: 2^126·num − r0·den ≤ den, scaled - have hfloor : (0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) - r0 * (ev - tod) ≤ (ev - tod) := by + -- floor: scale·num − r0·den ≤ den, scaled + have hfloor : (scale : Int) * (ev + tod) - r0 * (ev - tod) ≤ (ev - tod) := by linarith [hfloor_hi] - have hfloor638 : (2:Int) ^ 637 * ((0x6f05b59d3b2000000000000000000000 : Int) * (ev + tod) - r0 * (ev - tod)) ≤ + have hfloor638 : (2:Int) ^ 637 * ((scale : Int) * (ev + tod) - r0 * (ev - tod)) ≤ 2 ^ 637 * (ev - tod) := mul_le_mul_of_nonneg_left hfloor (by positivity) nlinarith [hterm1, hterm2, hfloor638] -- budget against DENv = Ep·2^111 − t·Op ≥ 2^638·ev ≥ 2^638·A0; den ≤ ev + 2^126 @@ -387,27 +435,41 @@ theorem link1_under_int_neg {x : Nat} (hx : x < 2 ^ 256) int256 (tTree x) * (odNumV (vTree x) : Int) := by linarith [hEp111, htOp_np] linarith [h1, h2] - -- 1000·(2^637 + Wev·2^591·S + 2·2^637·S) ≤ 1378·2^637·A0 + -- 1000·(2^637 + Wev·2^591·S + 2·2^637·S) ≤ 1378·2^637·A0, relaxing the symbolic scale to the + -- literal maximal one first + have hSrelax : 1000 * (72572599271425 * 2 ^ 591 * (scale : Int) + + 2 * 2 ^ 637 * (scale : Int)) ≤ + 1000 * (72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) + + 2 * 2 ^ 637 * (0x6f05b59d3b2000000000000000000000 : Int)) := by + nlinarith [hshiI] have hlit : 1000 * (2 ^ 637 : Int) + 1000 * (72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) + 2 * 2 ^ 637 * (0x6f05b59d3b2000000000000000000000 : Int)) ≤ (1378 : Int) * (2 ^ 637 * 415147853590918758559635130244235626256) := by norm_num - linarith [hLHS, hDden, hD_A, hlit] + linarith [hLHS, hDden, hD_A, hlit, hSrelax] /-! ## The per-point deficit (nonneg half) -/ /-- **The per-point deficit (nonneg half).** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`: link-1 `≤ 2378/1000`, the `Mp` factor `≤ 2/25`, the under gap `≤ 307/1000`; the granularity is free on this half. -/ -theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) +theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by + (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW + have hsRnn : (0:Real) ≤ (scale : Real) := by positivity + have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h set t := int256 (tTree x) with htdef set v := vTree x with hvdef - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def have htdom : t ≤ (ExpCertV.H129 : Int) := by rw [show ((ExpCertV.H129 : Nat) : Int) = 235865763225513294137944142764154484399 from by unfold ExpCertV.H129; norm_num] @@ -419,9 +481,9 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by have : (0:Int) < evalPoly ExpCertV.denExpV t := lt_of_lt_of_le one_pos hDE exact_mod_cast this - -- link 1: 2^126·Qv ≤ r0 + 2378/1000 - have hlink1 := link1_under_int hx hW htnn - have hQv_le : (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ + -- link 1: scale·Qv ≤ r0 + 2378/1000 + have hlink1 := link1_under_int hslo hshi hx hW htnn + have hQv_le : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (r0 : Real) + 2378 / 1000 := by rw [mul_div_assoc', div_le_iff₀ hDR] have hR := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hlink1 @@ -447,21 +509,21 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) have hEt_le_Qv : Et ≤ ((NUMv v t : Real) / (DENv v t : Real)) * Mpp := le_trans hEt_le (mul_le_mul_of_nonneg_right hgran1 hMpp_nn) have hMpp1 : Mpp - 1 = 1 / (2 ^ 132 : Real) := by rw [hMppdef]; field_simp - obtain ⟨_, hr0hi145⟩ := r0_bracket_nonneg hx hW htnn + obtain ⟨_, hr0hi145⟩ := r0_bracket_nonneg hshi hx hW htnn have hr0R : (r0 : Real) ≤ (145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0hi145 push_cast at h - linarith [h] - have hEt_bound : (0x6f05b59d3b2000000000000000000000 : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + 2 / 25 := by - have h1 : (0x6f05b59d3b2000000000000000000000 : Real) * Et ≤ - (0x6f05b59d3b2000000000000000000000 : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) := - mul_le_mul_of_nonneg_left hEt_le_Qv (by positivity) - have h2 : (0x6f05b59d3b2000000000000000000000 : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) = - (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + - ((0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) := by ring - have h3 : ((0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) ≤ 2 / 25 := by + nlinarith [h, hshiR] + have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + 2 / 25 := by + have h1 : (scale : Real) * Et ≤ + (scale : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) := + mul_le_mul_of_nonneg_left hEt_le_Qv hsRnn + have h2 : (scale : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) = + (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + + ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) := by ring + have h3 : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) ≤ 2 / 25 := by rw [hMpp1] - have hcap : (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ + have hcap : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000 := by linarith [hQv_le, hr0R] have := mul_le_mul_of_nonneg_right hcap (by positivity : (0:Real) ≤ 1 / (2 ^ 132 : Real)) have hfin : ((145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000) * (1 / (2 ^ 132 : Real)) ≤ @@ -475,20 +537,23 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) have hErt_le := exp_reducedArg_le_sqrt2bound hx hW rw [← hErtdef] at hErt_le have hErt_nn : (0:Real) ≤ Ert := le_of_lt (Real.exp_pos _) - have hgap126 : (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) ≤ 307 / 1000 := by + have hgap126 : (scale : Real) * (Ert - Et) ≤ 307 / 1000 := by have hgap : Ert - Et ≤ (1025 / (1024 * (2 ^ 129 : Real))) * Ert := le_trans hExp_diff (mul_le_mul_of_nonneg_right (le_of_lt hgapunder) hErt_nn) - have h1 : (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := - mul_le_mul_of_nonneg_left hgap (by positivity) - have h2 : (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) ≤ + have h1 : (scale : Real) * (Ert - Et) ≤ (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := + mul_le_mul_of_nonneg_left hgap hsRnn + have h2 : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) ≤ + (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := + mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) hsRnn + have h2' : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := - mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) (by positivity) + mul_le_mul_of_nonneg_right hshiR (by positivity) have h3 : (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ 307 / 1000 := by norm_num - linarith [h1, h2, h3] - have hdist : (0x6f05b59d3b2000000000000000000000 : Real) * Ert = (0x6f05b59d3b2000000000000000000000 : Real) * Et + (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) := by + linarith [h1, h2, h2', h3] + have hdist : (scale : Real) * Ert = (scale : Real) * Et + (scale : Real) * (Ert - Et) := by ring - show (0x6f05b59d3b2000000000000000000000 : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 + show (scale : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 have hsum : (2378 : Real) / 1000 + 2 / 25 + 307 / 1000 ≤ 2993 / 1000 := by norm_num linarith [hEt_bound, hgap126, hdist, hsum] @@ -497,23 +562,31 @@ theorem r0_real_under_tight {x : Nat} (hx : x < 2 ^ 256) /-- **The per-point deficit (nonpositive half).** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`: link-1 `≤ 2378/1000`, the `Mp`-folded granularity `≤ (5¹⁸/2⁴¹)·1644901622230542074/10¹⁹`, the `Mp` factor `≤ 2/25` (via `r0 ≤ scaleQ67`), the under gap `≤ 307/1000`. -/ -theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) +theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : - (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by + (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by have htdom := tdom_neg hx hW htneg have hvle := vTree_le_vmax_wide hx hW + have hsRnn : (0:Real) ≤ (scale : Real) := by positivity + have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [hs] at h + exact h set t := int256 (tTree x) with htdef set v := vTree x with hvdef - set r0 := int256 (r0Tree x) with hr0def + set r0 := int256 (r0ScaledTree scale x) with hr0def have hD : 1108965543718 * 2 ^ 725 ≤ DENv v t := DENv_ge_neg (by omega) htneg have hDpos : (0:Int) < DENv v t := lt_of_lt_of_le (by positivity) hD have hDR : (0:Real) < (DENv v t : Real) := by exact_mod_cast hDpos have hDEpos : (0:Int) < evalPoly ExpCertV.denExpV t := (certNE_pos_neg_aux htneg htdom).2 have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by exact_mod_cast hDEpos - -- link 1: 2^126·Qv ≤ r0 + 2378/1000 - have hlink1 := link1_under_int_neg hx hW htneg - have hQv_le : (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ + -- link 1: scale·Qv ≤ r0 + 2378/1000 + have hlink1 := link1_under_int_neg hslo hshi hx hW htneg + have hQv_le : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (r0 : Real) + 2378 / 1000 := by rw [mul_div_assoc', div_le_iff₀ hDR] have hR := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hlink1 @@ -532,31 +605,52 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) (((2 ^ 132 - 1 : Int) : Real) * (DE : Real)) := by push_cast; field_simp; ring rw [key]; exact hcertup - obtain ⟨_, hgran2⟩ := gran_under_pair hx hW htneg + obtain ⟨hgran1, hgran2⟩ := gran_under_pair hx hW htneg have hMp_nn : (0:Real) ≤ Mp := by rw [hMpdef] have : (0:Real) < (2 ^ 132 : Real) - 1 := by norm_num positivity have hMp1 : Mp - 1 = 1 / ((2 ^ 132 : Real) - 1) := by rw [hMpdef]; field_simp - have hr0le := r0_le_scale_neg hx hW htneg + have hr0le := r0_le_scale_neg hshi hx hW htneg have hr0R : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h - linarith [h] - have hEt_bound : (0x6f05b59d3b2000000000000000000000 : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + 2 / 25 + + linarith [h, hshiR] + -- the certified granularity envelope at the 2^126 normalization, rescaled to the symbolic + -- scale and relaxed to the literal maximal-scale budget + have hgran2S : (scale : Real) * Mp * + ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) ≤ 3814697265625 * 1644901622230542074 / (10000000000000000000 * 2199023255552) := by - have h1 : (0x6f05b59d3b2000000000000000000000 : Real) * Et ≤ (0x6f05b59d3b2000000000000000000000 : Real) * (((NE : Real) / (DE : Real)) * Mp) := - mul_le_mul_of_nonneg_left hEt_le (by positivity) - -- split: 2^126·(NE/DE)·Mp = 2^126·Qv + 2^126·Qv·(Mp−1) + 2^126·Mp·(NE/DE − Qv) - have hsplit : (0x6f05b59d3b2000000000000000000000 : Real) * (((NE : Real) / (DE : Real)) * Mp) = - (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + - ((0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mp - 1) + - (0x6f05b59d3b2000000000000000000000 : Real) * Mp * + have hdiff_nn : (0:Real) ≤ (NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real) := by + linarith [hgran1] + have hMp' : Mp ≤ (2 ^ 131 : Real) / ((2 ^ 131 : Real) - 1) := by + rw [hMpdef, div_le_div_iff₀ (by norm_num) (by norm_num)] + norm_num + have hMp_nn' : (0:Real) ≤ Mp := hMp_nn + have h1 : (scale : Real) * Mp * + ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) ≤ + (scale : Real) * ((2 ^ 131 : Real) / ((2 ^ 131 : Real) - 1)) * + ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) := + mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_left hMp' hsRnn) hdiff_nn + have h2 := mul_le_mul_of_nonneg_left hgran2 hsRnn + have h3 : (scale : Real) * (1644901622230542074 / 10000000000000000000) ≤ + (0x6f05b59d3b2000000000000000000000 : Real) * (1644901622230542074 / 10000000000000000000) := + mul_le_mul_of_nonneg_right hshiR (by positivity) + nlinarith [h1, h2, h3] + have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + 2 / 25 + + 3814697265625 * 1644901622230542074 / (10000000000000000000 * 2199023255552) := by + have h1 : (scale : Real) * Et ≤ (scale : Real) * (((NE : Real) / (DE : Real)) * Mp) := + mul_le_mul_of_nonneg_left hEt_le hsRnn + -- split: scale·(NE/DE)·Mp = scale·Qv + scale·Qv·(Mp−1) + scale·Mp·(NE/DE − Qv) + have hsplit : (scale : Real) * (((NE : Real) / (DE : Real)) * Mp) = + (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + + ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mp - 1) + + (scale : Real) * Mp * ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) := by ring - have hMpterm : ((0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mp - 1) ≤ + have hMpterm : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mp - 1) ≤ 2 / 25 := by rw [hMp1] - have hcap : (0x6f05b59d3b2000000000000000000000 : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ + have hcap : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ (0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000 := by linarith [hQv_le, hr0R] have := mul_le_mul_of_nonneg_right hcap (by positivity : (0:Real) ≤ 1 / ((2 ^ 132 : Real) - 1)) @@ -564,7 +658,7 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) rw [mul_one_div, div_le_div_iff₀ (by norm_num) (by norm_num)] norm_num linarith [this, hfin] - linarith [h1, hsplit ▸ h1, hMpterm, hgran2, hQv_le] + linarith [h1, hsplit ▸ h1, hMpterm, hgran2S, hQv_le] -- link 4 (under gap): 2^126·(Ert − Et) ≤ 307/1000 set Ert := Real.exp (reducedArg x) with hErtdef have hgapunder := reducedArg_close_under_wide hx hW @@ -595,31 +689,46 @@ theorem r0_real_under_tight_neg {x : Nat} (hx : x < 2 ^ 256) have hfin : (1:Real) / (1 - u) ≤ 10001 / 10000 := by rw [div_le_div_iff₀ h1u (by norm_num)]; nlinarith [husmall] linarith [hmono, hexpu, hfin] - have hgap126 : (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) ≤ 218 / 1000 := by + have hgap126 : (scale : Real) * (Ert - Et) ≤ 218 / 1000 := by have hgap : Ert - Et ≤ (1025 / (1024 * (2 ^ 129 : Real))) * Ert := le_trans hExp_diff (mul_le_mul_of_nonneg_right (le_of_lt hgapunder) hErt_nn) - have h1 : (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := - mul_le_mul_of_nonneg_left hgap (by positivity) - have h2 : (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) ≤ + have h1 : (scale : Real) * (Ert - Et) ≤ (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := + mul_le_mul_of_nonneg_left hgap hsRnn + have h2 : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) ≤ + (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := + mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) hsRnn + have h2' : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := - mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) (by positivity) + mul_le_mul_of_nonneg_right hshiR (by positivity) have h3 : (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ 218 / 1000 := by norm_num - linarith [h1, h2, h3] - have hdist : (0x6f05b59d3b2000000000000000000000 : Real) * Ert = (0x6f05b59d3b2000000000000000000000 : Real) * Et + (0x6f05b59d3b2000000000000000000000 : Real) * (Ert - Et) := by + linarith [h1, h2, h2', h3] + have hdist : (scale : Real) * Ert = (scale : Real) * Et + (scale : Real) * (Ert - Et) := by ring - show (0x6f05b59d3b2000000000000000000000 : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 + show (scale : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 have hsum : (2378 : Real) / 1000 + 2 / 25 + 3814697265625 * 1644901622230542074 / (10000000000000000000 * 2199023255552) + 218 / 1000 ≤ 2993 / 1000 := by norm_num linarith [hEt_bound, hgap126, hdist, hsum] -/-- **Per-point deficit (tight, any sign):** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`. -/ +/-- **Per-point deficit (tight, any sign):** `scale·exp(rt) ≤ r0 + 2993/1000` (the deficit budget +is certified at the maximal scale, and smaller scales only shrink the true deficit). -/ +theorem r0Scaled_real_under_within {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) : + (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by + rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg + · exact r0_real_under_tight hslo hshi hx hW htnn + · exact r0_real_under_tight_neg hslo hshi hx hW (le_of_lt htneg) + theorem r0_real_under_within_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by - rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg - · exact r0_real_under_tight hx hW htnn - · exact r0_real_under_tight_neg hx hW (le_of_lt htneg) + have h := r0Scaled_real_under_within (scale := scaleQ67) (by unfold scaleQ67; norm_num) + (le_refl _) hx hW + rw [r0Tree_eq_scaled] + have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by + unfold scaleQ67; norm_num + rw [← hs] + exact h theorem r0_real_under_within {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : @@ -637,6 +746,16 @@ theorem r0Tree_gt_2126 {x : Nat} (hx : x < 2 ^ 256) have h2 : (2 : Real) ^ 123 < ((2 ^ 124 : Int) : Real) := by norm_num linarith [h, h2] +/-- `2¹²² < r0ScaledTree scale x` on the region, for `2^125 ≤ scale ≤ scaleQ67`. -/ +theorem r0Scaled_gt_2122 {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) : + (2 : Real) ^ 122 < (int256 (r0ScaledTree scale x) : Real) := by + obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW + have h : ((2 ^ 123 : Int) : Real) ≤ (int256 (r0ScaledTree scale x) : Real) := by + exact_mod_cast hr0lo + have h2 : (2 : Real) ^ 122 < ((2 ^ 123 : Int) : Real) := by norm_num + linarith [h, h2] + /-- **The seam exp relation.** Across a seam (`X2 = X1 + 1`, `k2 = k1 + 1`), `exp(rt1) = 2·exp(rt2)·exp(−1/RAY)`. -/ theorem reducedArg_seam {x1 x2 : Nat} diff --git a/formal/exp/ExpProof/ExpProof/Mono/Cross.lean b/formal/exp/ExpProof/ExpProof/Mono/Cross.lean index 058382dd1..457071e79 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Cross.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Cross.lean @@ -29,6 +29,7 @@ open FormalYul open FormalYul.Preservation set_option maxRecDepth 100000 +set_option maxHeartbeats 1600000 /-- The cross-product of the two reciprocal-symmetric fractions collapses to a `tod·ev` cross. -/ theorem cross_identity (ev1 ev2 tod1 tod2 : Int) : @@ -41,18 +42,21 @@ theorem numSum_lt {W : Nat} {ev tod : Int} (hW : int256 W = ev + tod) (hev : ev < 3 * 2 ^ 127) (htod : tod < 2 ^ 126) : int256 W < 2 ^ 129 := by rw [hW, show (2:Int)^129 = 3 * 2^127 + 2^127 from by ring]; omega -/-- The `mul scaleQ67 N` dividend as a plain `Nat` product when `N`'s signed value is in -`[0, 2^128)`: `evmMul scaleQ67 N = scaleQ67 * N` (no wrap), and `N` is its own signed value. -/ -theorem mulScale_transport {N : Nat} (hNw : N < 2 ^ 256) (hNnn : 0 ≤ int256 N) +/-- The `mul scale N` dividend as a plain `Nat` product when `N`'s signed value is in +`[0, 2^128)` and `scale ≤ scaleQ67`: `evmMul scale N = scale * N` (no wrap), and `N` is its own +signed value. -/ +theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ scaleQ67) + (hNw : N < 2 ^ 256) (hNnn : 0 ≤ int256 N) (hNlt : int256 N < 2 ^ 129) : - evmMul scaleQ67 N = scaleQ67 * N ∧ N < 2 ^ 129 := by + evmMul scale N = scale * N ∧ N < 2 ^ 129 := by obtain ⟨hNi, _⟩ := int256_eq_of_nonneg hNw hNnn have hNnat : N < 2 ^ 129 := by have : ((N : Nat) : Int) < 2 ^ 129 := by rw [← hNi]; exact hNlt exact_mod_cast this - have hsw : scaleQ67 < 2 ^ 256 := by unfold scaleQ67; norm_num - have hfit : scaleQ67 * N < 2 ^ 256 := by - have h1 : scaleQ67 * N ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul_left _ (le_of_lt hNnat) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hfit : scale * N < 2 ^ 256 := by + have h1 : scale * N ≤ scaleQ67 * 2 ^ 129 := + Nat.mul_le_mul hshi (le_of_lt hNnat) have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num omega exact ⟨evmMul_eq_nat hsw hNw hfit, hNnat⟩ @@ -60,7 +64,7 @@ theorem mulScale_transport {N : Nat} (hNw : N < 2 ^ 256) (hNnn : 0 ≤ int256 N) /-- Abstract `r0` monotonicity from the `tod·ev` cross inequality, over opaque even/odd words. Given the numerator/denominator positivity and `tod1·ev2 ≤ tod2·ev1`, the two `div` quotients are `≤`-ordered. -/ -theorem r0_mono_of_cross {E1 TD1 E2 TD2 : Nat} +theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleQ67) (hE1 : E1 < 2 ^ 256) (hTD1 : TD1 < 2 ^ 256) (hE2 : E2 < 2 ^ 256) (hTD2 : TD2 < 2 ^ 256) (hev1_lo : (415147853590918758559635130244235626256 : Int) ≤ (E1 : Int)) (hev1_hi : (E1 : Int) < 3 * 2 ^ 127) @@ -71,8 +75,8 @@ theorem r0_mono_of_cross {E1 TD1 E2 TD2 : Nat} (htod2_lo : -(85070591730234615865843651857942052864 : Int) ≤ int256 TD2) (htod2_hi : int256 TD2 < 85070591730234615865843651857942052864) (hcross : int256 TD1 * (E2 : Int) ≤ int256 TD2 * (E1 : Int)) : - int256 (evmDiv (evmMul scaleQ67 (evmAdd E1 TD1)) (evmSub E1 TD1)) ≤ - int256 (evmDiv (evmMul scaleQ67 (evmAdd E2 TD2)) (evmSub E2 TD2)) := by + int256 (evmDiv (evmMul scale (evmAdd E1 TD1)) (evmSub E1 TD1)) ≤ + int256 (evmDiv (evmMul scale (evmAdd E2 TD2)) (evmSub E2 TD2)) := by obtain ⟨hadd1, hsub1, hnum1, hden1⟩ := numden_pos_of hE1 hTD1 hev1_lo hev1_hi htod1_lo htod1_hi obtain ⟨hadd2, hsub2, hnum2, hden2⟩ := numden_pos_of hE2 hTD2 hev2_lo hev2_hi htod2_lo htod2_hi -- the tod magnitude in the symbolic power form @@ -89,8 +93,8 @@ theorem r0_mono_of_cross {E1 TD1 E2 TD2 : Nat} have hD1pos : 0 < int256 (evmSub E1 TD1) := by rw [hsub1]; exact hden1 have hD2pos : 0 < int256 (evmSub E2 TD2) := by rw [hsub2]; exact hden2 -- mul dividends as plain Nat products - obtain ⟨hA1, hN1nat⟩ := mulScale_transport (evmAdd_lt _ _) (le_of_lt (hadd1 ▸ hnum1)) hN1lt - obtain ⟨hA2, hN2nat⟩ := mulScale_transport (evmAdd_lt _ _) (le_of_lt (hadd2 ▸ hnum2)) hN2lt + obtain ⟨hA1, hN1nat⟩ := mulScale_transport hshi (evmAdd_lt _ _) (le_of_lt (hadd1 ▸ hnum1)) hN1lt + obtain ⟨hA2, hN2nat⟩ := mulScale_transport hshi (evmAdd_lt _ _) (le_of_lt (hadd2 ▸ hnum2)) hN2lt -- canonical Nat values for the numerators and denominators obtain ⟨hN1i, _⟩ := int256_eq_of_nonneg (evmAdd_lt E1 TD1) (le_of_lt (hadd1 ▸ hnum1)) obtain ⟨hN2i, _⟩ := int256_eq_of_nonneg (evmAdd_lt E2 TD2) (le_of_lt (hadd2 ▸ hnum2)) @@ -104,23 +108,23 @@ theorem r0_mono_of_cross {E1 TD1 E2 TD2 : Nat} exact_mod_cast h have hD1nz : evmSub E1 TD1 ≠ 0 := Nat.pos_iff_ne_zero.mp hD1posN have hD2nz : evmSub E2 TD2 ≠ 0 := Nat.pos_iff_ne_zero.mp hD2posN - have hsw : scaleQ67 < 2 ^ 256 := by unfold scaleQ67; norm_num - have hfit1 : scaleQ67 * evmAdd E1 TD1 < 2 ^ 256 := by - have h1 : scaleQ67 * evmAdd E1 TD1 ≤ scaleQ67 * 2 ^ 129 := - Nat.mul_le_mul_left _ (le_of_lt hN1nat) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hfit1 : scale * evmAdd E1 TD1 < 2 ^ 256 := by + have h1 : scale * evmAdd E1 TD1 ≤ scaleQ67 * 2 ^ 129 := + Nat.mul_le_mul hshi (le_of_lt hN1nat) have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num omega - have hfit2 : scaleQ67 * evmAdd E2 TD2 < 2 ^ 256 := by - have h1 : scaleQ67 * evmAdd E2 TD2 ≤ scaleQ67 * 2 ^ 129 := - Nat.mul_le_mul_left _ (le_of_lt hN2nat) + have hfit2 : scale * evmAdd E2 TD2 < 2 ^ 256 := by + have h1 : scale * evmAdd E2 TD2 ≤ scaleQ67 * 2 ^ 129 := + Nat.mul_le_mul hshi (le_of_lt hN2nat) have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num omega -- the two quotients as plain Nat floor divisions - have hq1 : evmDiv (evmMul scaleQ67 (evmAdd E1 TD1)) (evmSub E1 TD1) = - scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 := by + have hq1 : evmDiv (evmMul scale (evmAdd E1 TD1)) (evmSub E1 TD1) = + scale * evmAdd E1 TD1 / evmSub E1 TD1 := by rw [hA1, evmDiv_eq hfit1 (evmSub_lt _ _) hD1nz] - have hq2 : evmDiv (evmMul scaleQ67 (evmAdd E2 TD2)) (evmSub E2 TD2) = - scaleQ67 * evmAdd E2 TD2 / evmSub E2 TD2 := by + have hq2 : evmDiv (evmMul scale (evmAdd E2 TD2)) (evmSub E2 TD2) = + scale * evmAdd E2 TD2 / evmSub E2 TD2 := by rw [hA2, evmDiv_eq hfit2 (evmSub_lt _ _) hD2nz] -- Nat-level cross monotonicity: q1·D1 ≤ S·N1, S·N1·D2 ≤ S·N2·D1 ⇒ q1·D2 ≤ S·N2 ⇒ q1 ≤ q2 have hcrossN : evmAdd E1 TD1 * evmSub E2 TD2 ≤ evmAdd E2 TD2 * evmSub E1 TD1 := by @@ -132,20 +136,20 @@ theorem r0_mono_of_cross {E1 TD1 E2 TD2 : Nat} exact_mod_cast hInt have hD1pos' : 0 < evmSub E1 TD1 := Nat.pos_of_ne_zero hD1nz have hD2pos' : 0 < evmSub E2 TD2 := Nat.pos_of_ne_zero hD2nz - have hqle : scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 ≤ - scaleQ67 * evmAdd E2 TD2 / evmSub E2 TD2 := by + have hqle : scale * evmAdd E1 TD1 / evmSub E1 TD1 ≤ + scale * evmAdd E2 TD2 / evmSub E2 TD2 := by rw [Nat.le_div_iff_mul_le hD2pos'] - have hfl : scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E1 TD1 ≤ - scaleQ67 * evmAdd E1 TD1 := Nat.div_mul_le_self _ _ + have hfl : scale * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E1 TD1 ≤ + scale * evmAdd E1 TD1 := Nat.div_mul_le_self _ _ -- (q1·D2)·D1 ≤ S·N1·D2 ≤ S·N2·D1 ⇒ q1·D2 ≤ S·N2 (divide by D1 > 0) - have hstep : scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E2 TD2 * evmSub E1 TD1 ≤ - scaleQ67 * evmAdd E2 TD2 * evmSub E1 TD1 := by - calc scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E2 TD2 * evmSub E1 TD1 - = scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E1 TD1 * evmSub E2 TD2 := by ring - _ ≤ scaleQ67 * evmAdd E1 TD1 * evmSub E2 TD2 := Nat.mul_le_mul_right _ hfl - _ = scaleQ67 * (evmAdd E1 TD1 * evmSub E2 TD2) := by ring - _ ≤ scaleQ67 * (evmAdd E2 TD2 * evmSub E1 TD1) := Nat.mul_le_mul_left _ hcrossN - _ = scaleQ67 * evmAdd E2 TD2 * evmSub E1 TD1 := by ring + have hstep : scale * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E2 TD2 * evmSub E1 TD1 ≤ + scale * evmAdd E2 TD2 * evmSub E1 TD1 := by + calc scale * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E2 TD2 * evmSub E1 TD1 + = scale * evmAdd E1 TD1 / evmSub E1 TD1 * evmSub E1 TD1 * evmSub E2 TD2 := by ring + _ ≤ scale * evmAdd E1 TD1 * evmSub E2 TD2 := Nat.mul_le_mul_right _ hfl + _ = scale * (evmAdd E1 TD1 * evmSub E2 TD2) := by ring + _ ≤ scale * (evmAdd E2 TD2 * evmSub E1 TD1) := Nat.mul_le_mul_left _ hcrossN + _ = scale * evmAdd E2 TD2 * evmSub E1 TD1 := by ring exact Nat.le_of_mul_le_mul_right hstep hD1pos' -- transport back to int256 (both quotients are small: den ≥ 2^126) have hD1ge : 2 ^ 126 ≤ evmSub E1 TD1 := by @@ -158,24 +162,22 @@ theorem r0_mono_of_cross {E1 TD1 E2 TD2 : Nat} rw [← hD2i, hsub2] linarith [hev2_lo, htod2_hi] exact_mod_cast h - have hq1small : scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 < 2 ^ 255 := by - have h1 : scaleQ67 * evmAdd E1 TD1 / evmSub E1 TD1 ≤ scaleQ67 * evmAdd E1 TD1 / 2 ^ 126 := + have hq1small : scale * evmAdd E1 TD1 / evmSub E1 TD1 < 2 ^ 255 := by + have h1 : scale * evmAdd E1 TD1 / evmSub E1 TD1 ≤ scale * evmAdd E1 TD1 / 2 ^ 126 := Nat.div_le_div_left hD1ge (Nat.two_pow_pos _) - have h2 : scaleQ67 * evmAdd E1 TD1 / 2 ^ 126 < 2 ^ 130 := by + have h2 : scale * evmAdd E1 TD1 / 2 ^ 126 < 2 ^ 130 := by rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] - calc scaleQ67 * evmAdd E1 TD1 < 2 ^ 256 := hfit1 + calc scale * evmAdd E1 TD1 < 2 ^ 256 := hfit1 _ = 2 ^ 130 * 2 ^ 126 := by norm_num - have h3 : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num - omega - have hq2small : scaleQ67 * evmAdd E2 TD2 / evmSub E2 TD2 < 2 ^ 255 := by - have h1 : scaleQ67 * evmAdd E2 TD2 / evmSub E2 TD2 ≤ scaleQ67 * evmAdd E2 TD2 / 2 ^ 126 := + exact lt_of_le_of_lt h1 (lt_trans h2 (by norm_num)) + have hq2small : scale * evmAdd E2 TD2 / evmSub E2 TD2 < 2 ^ 255 := by + have h1 : scale * evmAdd E2 TD2 / evmSub E2 TD2 ≤ scale * evmAdd E2 TD2 / 2 ^ 126 := Nat.div_le_div_left hD2ge (Nat.two_pow_pos _) - have h2 : scaleQ67 * evmAdd E2 TD2 / 2 ^ 126 < 2 ^ 130 := by + have h2 : scale * evmAdd E2 TD2 / 2 ^ 126 < 2 ^ 130 := by rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] - calc scaleQ67 * evmAdd E2 TD2 < 2 ^ 256 := hfit2 + calc scale * evmAdd E2 TD2 < 2 ^ 256 := hfit2 _ = 2 ^ 130 * 2 ^ 126 := by norm_num - have h3 : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num - omega + exact lt_of_le_of_lt h1 (lt_trans h2 (by norm_num)) rw [hq1, hq2, int256_of_lt hq1small, int256_of_lt hq2small] exact_mod_cast hqle diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean index fdef523eb..4b2694aba 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -53,6 +53,8 @@ def r0MulTree (y x : Nat) : Nat := evmDiv (evmMul (mulScaleTree y) (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) +theorem r0MulTree_eq_scaled (y x : Nat) : r0MulTree y x = r0ScaledTree (mulScaleTree y) x := rfl + /-- The nonnegative magnitude returned by the shared kernel before the `sgn(y)` multiply. -/ def mulMagnitudeTree (y x : Nat) : Nat := evmAdd (evmIszero x) diff --git a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean index 5c8de1977..4ef344c01 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean @@ -264,4 +264,113 @@ theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 130 := r0Tree_bounds_wide hx (wideRegion_of_wad hC hC0) +/-! ## The scaled quotient at a symbolic scale -/ + +/-- Abstract scaled-quotient bounds at a symbolic scale `2^125 ≤ scale ≤ scaleQ67`: `⌊scale·N/D⌋` +lies in `[2^123, 2^130)`. The lower bound is tight at the minimal scale: +`2^123·D < 2^123·2^129 = 2^125·2^127 ≤ scale·N`. -/ +theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD : D < 2 ^ 256) + (hDi : int256 D = (D : Int)) + (hNpos : 0 < (N : Int)) (hDpos : 0 < (D : Int)) + (hNlo : 2 ^ 127 ≤ N) + (hND : (N : Int) < 4 * (D : Int)) : + 2 ^ 123 ≤ int256 (evmDiv (evmMul scale N) D) ∧ + int256 (evmDiv (evmMul scale N) D) < 2 ^ 130 := by + have hNw : N < 2 ^ 256 := by + have : (2:Nat) ^ 128 < 2 ^ 256 := by norm_num + omega + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hfit : scale * N < 2 ^ 256 := by + have h1 : scale * N ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hN) + have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + omega + have hmul : evmMul scale N = scale * N := evmMul_eq_nat hsw hNw hfit + have hDnat_pos : 0 < D := by exact_mod_cast hDpos + have hdiv : evmDiv (evmMul scale N) D = scale * N / D := by + rw [hmul, evmDiv_eq hfit hD (by omega)] + set q := scale * N / D with hq + have hspos : 0 < scale := lt_of_lt_of_le (by norm_num) hslo + have hq_lt : q < 2 ^ 130 := by + rw [hq, Nat.div_lt_iff_lt_mul hDnat_pos] + have hND' : N < 4 * D := by + have h4 : ((4 * D : Nat) : Int) = 4 * (D : Int) := by push_cast; ring + rw [← h4] at hND; exact_mod_cast hND + have h1 : scale * N < scale * (4 * D) := (Nat.mul_lt_mul_left hspos).mpr hND' + have h2 : scale * (4 * D) ≤ scaleQ67 * (4 * D) := Nat.mul_le_mul_right _ hshi + have h3 : scaleQ67 * (4 * D) ≤ 2 ^ 130 * D := by + have h4S : (4:Nat) * scaleQ67 ≤ 2 ^ 130 := by unfold scaleQ67; norm_num + calc scaleQ67 * (4 * D) = (4 * scaleQ67) * D := by ring + _ ≤ 2 ^ 130 * D := Nat.mul_le_mul_right _ h4S + omega + have hq_ge : 2 ^ 123 ≤ q := by + rw [hq, Nat.le_div_iff_mul_le hDnat_pos] + have h1 : (2:Nat) ^ 123 * D ≤ 2 ^ 123 * 2 ^ 129 := Nat.mul_le_mul_left _ (le_of_lt hDlt) + have h2 : (2:Nat) ^ 123 * 2 ^ 129 ≤ 2 ^ 125 * 2 ^ 127 := by norm_num + have h3 : (2:Nat) ^ 125 * 2 ^ 127 ≤ scale * N := Nat.mul_le_mul hslo hNlo + omega + have hqi : int256 (evmDiv (evmMul scale N) D) = (q : Int) := by + rw [hdiv] + exact int256_of_lt (by + have : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num + omega) + rw [hqi] + exact ⟨by exact_mod_cast hq_ge, by exact_mod_cast hq_lt⟩ + +/-- Abstract scaled `r0` bounds over opaque even/odd words: `2^123 ≤ r0 < 2^130` with +`r0 = div(scale·(E+TD), E−TD)` at any `2^125 ≤ scale ≤ scaleQ67`. -/ +theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ scaleQ67) (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) + (hev_lo : (415147853590918758559635130244235626256 : Int) ≤ (E : Int)) + (hev_hi : (E : Int) < 3 * 2 ^ 127) + (htod_lo : -(85070591730234615865843651857942052864 : Int) ≤ int256 TD) + (htod_hi : int256 TD < 85070591730234615865843651857942052864) : + 2 ^ 123 ≤ int256 (evmDiv (evmMul scale (evmAdd E TD)) (evmSub E TD)) ∧ + int256 (evmDiv (evmMul scale (evmAdd E TD)) (evmSub E TD)) < 2 ^ 130 := by + obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_of hevw htodw hev_lo hev_hi htod_lo htod_hi + have hNwlt : evmAdd E TD < 2 ^ 256 := evmAdd_lt _ _ + have hDwlt : evmSub E TD < 2 ^ 256 := evmSub_lt _ _ + have h128 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num + have h127 : (3:Int) * 2 ^ 127 = 510423550381407695195061911147652317184 := by norm_num + rw [h127] at hev_hi + obtain ⟨hNi, hNlt255⟩ := int256_eq_of_nonneg hNwlt (by rw [hadd]; omega) + obtain ⟨hDi, hDlt255⟩ := int256_eq_of_nonneg hDwlt (by rw [hsub]; omega) + have hNlt128 : evmAdd E TD < 2 ^ 129 := by + have : ((evmAdd E TD : Nat) : Int) < 2 ^ 129 := by rw [← hNi, hadd, h128]; omega + exact_mod_cast this + have hDlt128 : evmSub E TD < 2 ^ 129 := by + have : ((evmSub E TD : Nat) : Int) < 2 ^ 129 := by rw [← hDi, hsub, h128]; omega + exact_mod_cast this + have hNlo : 2 ^ 127 ≤ evmAdd E TD := by + have : (2 ^ 127 : Int) ≤ ((evmAdd E TD : Nat) : Int) := by + rw [← hNi, hadd, show (2:Int)^127 = 170141183460469231731687303715884105728 by norm_num] + omega + exact_mod_cast this + have hND : ((evmAdd E TD : Nat) : Int) < 4 * ((evmSub E TD : Nat) : Int) := by + rw [← hNi, ← hDi, hadd, hsub]; omega + have hNpos : 0 < ((evmAdd E TD : Nat) : Int) := by rw [← hNi, hadd]; omega + have hDpos : 0 < ((evmSub E TD : Nat) : Int) := by rw [← hDi, hsub]; omega + exact r0Scaled_bounds_of hslo hshi hNlt128 hDlt128 hDwlt hDi hNpos hDpos hNlo hND + +/-- `2^123 ≤ r0ScaledTree scale x < 2^130` on the wide region, for `2^125 ≤ scale ≤ scaleQ67`. -/ +theorem r0Scaled_bounds {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) : + 2 ^ 123 ≤ int256 (r0ScaledTree scale x) ∧ int256 (r0ScaledTree scale x) < 2 ^ 130 := by + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW + obtain ⟨hev_lo, hev_hi⟩ := evTree_facts hvlt + obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound_wide hx hW + have hr0 : r0ScaledTree scale x = + evmDiv (evmMul scale (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) := rfl + rw [hr0] + have hevw : evTree x < 2 ^ 256 := by unfold evTree; exact evmAdd_lt _ _ + have htodw : todTree x < 2 ^ 256 := by unfold todTree; exact evmSar_lt _ _ + refine r0Scaled_bounds_ofEvTod hslo hshi hevw htodw ?_ ?_ ?_ ?_ + · have : (0x1385291795942d41ba5fd317688e18710 : Int) ≤ (evTree x : Int) := by exact_mod_cast hev_lo + rw [show (0x1385291795942d41ba5fd317688e18710 : Int) = 415147853590918758559635130244235626256 by norm_num] at this + exact this + · have : (evTree x : Int) < ((3 * 2 ^ 127 : Nat) : Int) := by exact_mod_cast hev_hi + rw [show ((3 * 2 ^ 127 : Nat) : Int) = 3 * 2 ^ 127 by norm_num] at this; exact this + · rw [show (85070591730234615865843651857942052864 : Int) = 2 ^ 126 by norm_num]; exact htod_lo + · rw [show (85070591730234615865843651857942052864 : Int) = 2 ^ 126 by norm_num]; exact htod_hi + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean b/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean index 6adeda798..dc13c2fc3 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean @@ -51,8 +51,8 @@ theorem r0_mono_adjacent {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) have hr02 : r0Tree x2 = evmDiv (evmMul scaleQ67 (evmAdd (evTree x2) (todTree x2))) (evmSub (evTree x2) (todTree x2)) := rfl rw [hr01, hr02] - exact r0_mono_of_cross hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo htod1hi - hev2lo hev2hi htod2lo htod2hi hcross + exact r0_mono_of_cross (le_refl scaleQ67) hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo + htod1hi hev2lo hev2hi htod2lo htod2hi hcross /-- The closing shift words coincide across an octave. -/ theorem closing_shift_eq {x1 x2 : Nat} diff --git a/formal/exp/ExpProof/ExpProof/Mono/Tree.lean b/formal/exp/ExpProof/ExpProof/Mono/Tree.lean index 824a3a426..c0871ae80 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Tree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Tree.lean @@ -47,11 +47,18 @@ def odTree (x : Nat) : Nat := /-- `t * Od(v)` in Q89. -/ def todTree (x : Nat) : Nat := evmSar todShift (evmMul (tTree x) (odTree x)) +/-- The scaled rational at an explicit scale word: `⌊scale·(ev + tod)/(ev − tod)⌋`. `r0Tree` is +its `scaleQ67` instance and the `mulExpRay` quotient its dynamic-scale instance. -/ +def r0ScaledTree (scale x : Nat) : Nat := + evmDiv (evmMul scale (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) + /-- `10¹⁸·exp(t)` on the `2⁶⁷` output grid: the numerator is pre-scaled by `10¹⁸·2⁶⁷ = 5¹⁸·2⁸⁵` before the single `DIV`. -/ def r0Tree (x : Nat) : Nat := evmDiv (evmMul scaleQ67 (evmAdd (evTree x) (todTree x))) (evmSub (evTree x) (todTree x)) +theorem r0Tree_eq_scaled (x : Nat) : r0Tree x = r0ScaledTree scaleQ67 x := rfl + /-- The floored, octave-scaled, margin-subtracted accumulator on the `2⁶⁷` output grid. -/ def r1Tree (x : Nat) : Nat := evmShr (evmSub foldShift (kTree x)) (evmSub (r0Tree x) marginWord) From 7c38e40227dd05c5b7371cbc6a5ccac74956d840 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 13:09:36 +0200 Subject: [PATCH 069/107] Prove the mulExpRay bracket on the whole value domain Mul/Transport.lean carries the dynamic-scale word facts: the headroom shift is at most 127, a nonzero magnitude's scale is maximal (one more doubling overshoots scaleQ67) and therefore lives in [2^125, scaleQ67], and on the live region the closing-shift word is the plain signed difference S - k in [2, 254]. Mul/Accum.lean folds the scale-symbolic per-point brackets through the closing shift: the target fold A*2^shift = scale*exp(rt) turns the shr floor sandwich on the decremented quotient into the two-unit magnitude bracket, sign reapplication gives the signed public bracket, and the shell regions (zero multiplier, scale point, zero clamp) close the remaining accepted inputs. The result magnitude is floor(A) or floor(A) - 1, and a target below one output unit pins it to zero. The signpost gates the new theorems; only the runtime monotonicity statements remain as facade hypotheses. Co-Authored-By: Claude Fable 5 --- formal/exp/ExpProof/ExpProof/Mul/Accum.lean | 356 ++++++++++++++++++ .../exp/ExpProof/ExpProof/Mul/Transport.lean | 251 ++++++++++++ formal/exp/ExpProof/ExpProof/Theorems.lean | 43 ++- 3 files changed, 646 insertions(+), 4 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Mul/Accum.lean create mode 100644 formal/exp/ExpProof/ExpProof/Mul/Transport.lean diff --git a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean new file mode 100644 index 000000000..9d127ad22 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean @@ -0,0 +1,356 @@ +import ExpProof.Mul.Transport +import ExpProof.Floor.R0ExpUnder + +/-! +# The live-region accumulator of `mulExpRay` + +On the live region — `x` strictly between the zero clamp and the overflow guard, a nonzero +magnitude, and at least two bits of closing shift — the kernel magnitude is the closing shift of +the decremented dynamic-scale quotient. The scale-symbolic per-point brackets +(`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) confine that quotient to +`(scale·exp(rt) − 2993/1000 − 1, scale·exp(rt) + 1)` at `scale = mulScaleTree y ∈ +[2^125, scaleQ67]`, and the target fold `A·2^shift = scale·exp(rt)` (`A = abs(y)·exp(x/10²⁷)`) +turns the `shr` floor sandwich into the two-unit magnitude bracket `0 ≤ m ≤ A < m + 2`. Sign +reapplication then yields the public signed bracket on the whole value domain, with the floor +membership `m ∈ {⌊A⌋, ⌊A⌋ − 1}` and the `A < 1 → m = 0` pin as corollaries. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word +open ExpRealSpec + +set_option maxRecDepth 100000 +set_option maxHeartbeats 1600000 + +/-! ## Word plumbing -/ + +private theorem u256_self {a : Nat} (h : a < 2 ^ 256) : u256 a = a := u256_of_lt_pow256 h + +private theorem evmSub_small {a b : Nat} (hb : b ≤ a) (ha : a < 2 ^ 256) : + evmSub a b = a - b := by + unfold evmSub + rw [u256_self ha, u256_self (lt_of_le_of_lt hb ha)] + unfold u256 WORD_MOD + omega + +private theorem evmAdd_zero_left {W : Nat} (hW : W < 2 ^ 256) : evmAdd 0 W = W := by + unfold evmAdd + rw [u256_self (a := 0) (by norm_num), u256_self (a := W) hW, Nat.zero_add] + exact u256_self hW + +private theorem evmMul_one_left {W : Nat} (hW : W < 2 ^ 256) : evmMul 1 W = W := by + unfold evmMul + rw [u256_self (a := 1) (by norm_num), u256_self (a := W) hW, Nat.one_mul] + exact u256_self hW + +private theorem int256_zero_word : int256 (0 : Nat) = 0 := by unfold int256; norm_num + +/-- A nonzero word has a nonzero magnitude. -/ +theorem absTree_pos {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) : 1 ≤ absTree y := by + by_cases hneg : y < 2 ^ 255 + · rw [absTree_nonneg hneg] + omega + · rw [absTree_neg (by omega) hy] + omega + +/-- On the live region the magnitude word is the closing shift of the decremented quotient: +the pin and the clamp multiplier are both inert. -/ +theorem mulMagnitudeTree_live {y x : Nat} (hx : x < 2 ^ 256) + (hx0 : int256 x ≠ 0) (hxgt : int256 mulExpRayZeroMax < int256 x) : + mulMagnitudeTree y x = + evmShr (mulShiftTree y x) (evmSub (r0MulTree y x) marginWord) := by + have hxw0 : x ≠ 0 := by + intro h + subst h + exact hx0 int256_zero_word + have hslt : evmSlt mulExpRayZeroMax x = 1 := by + rw [evmSlt_eq_ite, u256_self mulExpRayZeroMax_lt, u256_self hx, if_pos hxgt] + have hisz : evmIszero x = 0 := by + unfold evmIszero + rw [u256_self hx, if_neg hxw0] + unfold mulMagnitudeTree + rw [hslt, hisz, evmMul_one_left (evmShr_lt _ _), evmAdd_zero_left (evmShr_lt _ _)] + +noncomputable section + +/-! ## The live-region magnitude bracket -/ + +/-- **Live-region magnitude bracket.** On the live region the kernel magnitude `m` is a +nonnegative value below `2^128` with `m ≤ A < m + 2`. -/ +theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (hy0 : y ≠ 0) (habs : absTree y ≤ scaleQ67) + (hx0 : int256 x ≠ 0) (hW : WideRegion x) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + 0 ≤ int256 (mulMagnitudeTree y x) ∧ + int256 (mulMagnitudeTree y x) < 2 ^ 128 ∧ + (int256 (mulMagnitudeTree y x) : Real) ≤ mulExpRayMagnitudeTarget (int256 y) (int256 x) ∧ + mulExpRayMagnitudeTarget (int256 y) (int256 x) < + (int256 (mulMagnitudeTree y x) : Real) + 2 := by + -- the dynamic scale is live: 2^125 ≤ scale ≤ scaleQ67 + have hpos : 1 ≤ absTree y := absTree_pos hy hy0 + have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs + obtain ⟨hs256, hscale_eq, hshi⟩ := mulScaleTree_spec hy habs + -- quotient bounds at the dynamic scale + have hr0eq : r0MulTree y x = r0ScaledTree (mulScaleTree y) x := r0MulTree_eq_scaled y x + obtain ⟨hr0lo, hr0hi⟩ := r0Scaled_bounds hslo hshi hx hW + rw [← hr0eq] at hr0lo hr0hi + have hr0w : r0MulTree y x < 2 ^ 256 := r0MulTree_lt y x + have hr0nn : 0 ≤ int256 (r0MulTree y x) := le_trans (by positivity) hr0lo + obtain ⟨hr0i, hr0255⟩ := int256_eq_of_nonneg hr0w hr0nn + have hr0nat1 : 1 ≤ r0MulTree y x := by + have h : (1 : Int) ≤ ((r0MulTree y x : Nat) : Int) := by + rw [← hr0i] + calc (1:Int) ≤ 2 ^ 123 := by norm_num + _ ≤ int256 (r0MulTree y x) := hr0lo + exact_mod_cast h + -- the decremented quotient word + have hsub : evmSub (r0MulTree y x) marginWord = r0MulTree y x - 1 := by + unfold marginWord + exact evmSub_small hr0nat1 hr0w + have hr0nat130 : r0MulTree y x < 2 ^ 130 := by + have h : ((r0MulTree y x : Nat) : Int) < 2 ^ 130 := by rw [← hr0i]; exact hr0hi + exact_mod_cast h + set W := r0MulTree y x - 1 with hWdef + have hWnat130 : W < 2 ^ 130 := lt_of_le_of_lt (Nat.sub_le _ _) hr0nat130 + have hWw : W < 2 ^ 256 := lt_trans hWnat130 (by norm_num) + have hWi : int256 W = (W : Int) := int256_of_lt (lt_trans hWnat130 (by norm_num)) + have hWnn : 0 ≤ int256 W := by rw [hWi]; exact Int.natCast_nonneg _ + have hWhi : int256 W < 2 ^ 130 := by + rw [hWi] + exact_mod_cast hWnat130 + -- the closing-shift word + obtain ⟨hsh2, hsh256, hsheq⟩ := mulShift_word_facts hy hx habs hW hlive + set sh := mulShiftTree y x with hshdef + -- the magnitude word and its floor sandwich + have hmag : mulMagnitudeTree y x = evmShr sh W := by + rw [mulMagnitudeTree_live hx hx0 hW.1, hsub] + obtain ⟨hfl_lo, hfl_hi⟩ := shr_floor_sandwich (W := W) (s := sh) hsh256 hWw hWnn + obtain ⟨hm_nn, hm_lt⟩ := mulShr_facts hWw hsh2 (Nat.le_of_lt_succ hsh256) hWnn hWhi + rw [← hmag] at hfl_lo hfl_hi hm_nn hm_lt + -- the per-point brackets at the dynamic scale + have hover := r0Scaled_real_over_within hslo hshi hx hW + have hunder := r0Scaled_real_under_within hslo hshi hx hW + rw [← hr0eq] at hover hunder + -- the target fold A·2^sh = scale·exp(rt) + have htransport := mulShiftTree_transport hy hx habs hW + have hkS : int256 (kTree x) + ((sh : Nat) : Int) = ((scaleShiftTree (absTree y) : Nat) : Int) := by + have h1 := hsheq + rw [htransport] at h1 + linarith [h1] + have hfold : mulExpRayMagnitudeTarget (int256 y) (int256 x) * ((2 : Real) ^ (sh : Nat)) = + (mulScaleTree y : Real) * Real.exp (reducedArg x) := by + unfold mulExpRayMagnitudeTarget + have hRAY : ((RAY : Nat) : Real) = (10 ^ 27 : Real) := by unfold RAY; push_cast; norm_num + rw [hRAY, exp_X_over_RAY] + have hay : ((int256 y).natAbs : Real) = ((absTree y : Nat) : Real) := by + rw [absTree_eq_natAbs hy] + have hscaleR : ((mulScaleTree y : Nat) : Real) = + ((absTree y : Nat) : Real) * (2 : Real) ^ (scaleShiftTree (absTree y) : Nat) := by + rw [hscale_eq] + push_cast + ring + have hzpow : (2 : Real) ^ (int256 (kTree x)) * (2 : Real) ^ (sh : Nat) = + (2 : Real) ^ (scaleShiftTree (absTree y) : Nat) := by + have h1 : (2:Real) ^ (sh : Nat) = (2:Real) ^ (((sh : Nat) : Int)) := (zpow_natCast 2 _).symm + have h2 : (2:Real) ^ (scaleShiftTree (absTree y) : Nat) = + (2:Real) ^ (((scaleShiftTree (absTree y) : Nat) : Int)) := (zpow_natCast 2 _).symm + rw [h1, h2, ← zpow_add₀ (by norm_num : (2:Real) ≠ 0)] + rw [hkS] + rw [hay, hscaleR, ← hzpow] + ring + -- the sandwich in Real form + have hshpowpos : (0:Real) < (2 : Real) ^ (sh : Nat) := by positivity + have hWR : (int256 W : Real) = (int256 (r0MulTree y x) : Real) - 1 := by + rw [hWi, hr0i] + have h2 : ((W : Nat) : Int) = ((r0MulTree y x : Nat) : Int) - 1 := by + rw [hWdef] + exact Int.ofNat_sub hr0nat1 + rw [h2] + push_cast + ring + have hfl_loR : ((2 : Real) ^ (sh : Nat)) * (int256 (mulMagnitudeTree y x) : Real) ≤ + (int256 (r0MulTree y x) : Real) - 1 := by + have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hfl_lo + push_cast at h + rw [← hWR] + linarith [h] + have hfl_hiR : (int256 (r0MulTree y x) : Real) - 1 < + ((2 : Real) ^ (sh : Nat)) * (int256 (mulMagnitudeTree y x) : Real) + + (2 : Real) ^ (sh : Nat) := by + have h := (@Int.cast_lt Real _ _ _ _ _ _ _).mpr hfl_hi + push_cast at h + rw [← hWR] + linarith [h] + have hBlt1 : (3814697265625 * 5737291786393199862 / + (10000000000000000000 * 2199023255552) : Real) < 1 := by norm_num + have h4 : (4:Real) ≤ (2 : Real) ^ (sh : Nat) := by + calc (4:Real) = (2:Real) ^ (2:Nat) := by norm_num + _ ≤ (2 : Real) ^ (sh : Nat) := by + apply pow_le_pow_right₀ (by norm_num) + exact hsh2 + refine ⟨hm_nn, hm_lt, ?_, ?_⟩ + · -- over side: 2^sh·m ≤ r0 − 1 < scale·exp(rt) = A·2^sh, so m < A + have hchain : (int256 (mulMagnitudeTree y x) : Real) * ((2 : Real) ^ (sh : Nat)) < + mulExpRayMagnitudeTarget (int256 y) (int256 x) * ((2 : Real) ^ (sh : Nat)) := by + rw [hfold] + linarith [hfl_loR, hover, hBlt1] + exact le_of_lt ((mul_lt_mul_right hshpowpos).mp hchain) + · -- under side: A·2^sh = scale·exp(rt) ≤ r0 + 2993/1000 < (m + 2)·2^sh at two bits of shift + have hchain : mulExpRayMagnitudeTarget (int256 y) (int256 x) * ((2 : Real) ^ (sh : Nat)) < + ((int256 (mulMagnitudeTree y x) : Real) + 2) * ((2 : Real) ^ (sh : Nat)) := by + rw [hfold] + linarith [hfl_hiR, hunder, h4] + exact (mul_lt_mul_right hshpowpos).mp hchain + +/-! ## Sign application -/ + +/-- Live-region signed bracket for the tree result. -/ +theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (hy0 : y ≠ 0) (habs : absTree y ≤ scaleQ67) + (hx0 : int256 x ≠ 0) (hW : WideRegion x) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + MulExpRayBracket (int256 y) (int256 x) (int256 (mulExpTree y x)) := by + obtain ⟨hm0, hmlt, hmle, hmlt2⟩ := mulMagnitude_bracket_live hy hx hy0 habs hx0 hW hlive + have hmagw : mulMagnitudeTree y x < 2 ^ 256 := mulMagnitudeTree_lt y x + obtain ⟨hmi, hm255⟩ := int256_eq_of_nonneg hmagw hm0 + by_cases hneg : y < 2 ^ 255 + · have hypos : 0 < y := Nat.pos_of_ne_zero hy0 + have hynn : ¬ (int256 y < 0) := by + have : int256 y = (y : Int) := int256_of_lt hneg + rw [this] + exact not_lt.mpr (Int.natCast_nonneg y) + rw [mulExpTree_pos hypos hneg] + unfold MulExpRayBracket + rw [if_neg hynn] + exact ⟨hm0, hmle, hmlt2⟩ + · have hlo : 2 ^ 255 ≤ y := by omega + have hyneg : int256 y < 0 := by + unfold int256 + rw [if_neg (by omega)] + have h1 : (y : Int) < 2 ^ 256 := by exact_mod_cast hy + omega + rcases Nat.eq_zero_or_pos (mulMagnitudeTree y x) with hmz | hmpos + · have hzero : mulExpTree y x = 0 := by + unfold mulExpTree + rw [hmz] + unfold evmMul + rw [u256_self (by norm_num : (0:Nat) < 2 ^ 256)] + simp [u256, WORD_MOD] + rw [hzero, int256_zero_word] + unfold MulExpRayBracket + rw [if_pos hyneg] + have hmz' : int256 (mulMagnitudeTree y x) = 0 := by rw [hmz]; exact int256_zero_word + rw [hmz'] at hmle hmlt2 + exact ⟨le_refl 0, by simpa using hmle, by rw [neg_zero]; simpa using hmlt2⟩ + · rw [mulExpTree_negative hlo hy hmpos] + have hmnat255 : mulMagnitudeTree y x < 2 ^ 255 := by + have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 128 := by rw [← hmi]; exact hmlt + have h' : mulMagnitudeTree y x < 2 ^ 128 := by exact_mod_cast h + have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + omega + have hres : int256 (2 ^ 256 - mulMagnitudeTree y x) = -(int256 (mulMagnitudeTree y x)) := by + unfold int256 + rw [if_neg (by omega), if_pos hmnat255] + have h1 : ((2 ^ 256 - mulMagnitudeTree y x : Nat) : Int) = + 2 ^ 256 - ((mulMagnitudeTree y x : Nat) : Int) := by + push_cast + omega + rw [h1] + ring + rw [hres] + unfold MulExpRayBracket + rw [if_pos hyneg, neg_neg] + exact ⟨hm0, hmle, hmlt2⟩ + +/-! ## The bracket on the whole value domain -/ + +/-- **The public runtime bracket on the value domain.** Every accepted input returns a result +satisfying the signed two-unit magnitude bracket. -/ +theorem mulExpRay_run_bracket {y x : Nat} (h : MulExpRayValueDomain y x) : + MulExpRayRunBracket y x := by + obtain ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ := h + rcases Nat.eq_zero_or_pos y with hy0 | hypos + · subst hy0 + exact mulExpRay_run_bracket_zero x + ((valueDomain_iff_guard_eq_zero ⟨hy, hx⟩).mp ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩) + by_cases hclamp : int256 x ≤ int256 mulExpRayZeroMax + · exact mulExpRay_run_bracket_clamped hy hx habs hclamp + by_cases hx0 : int256 x = 0 + · have hxw0 : x = 0 := by + have h := (int256_zero_iff_of_canonical hx).1 hx0 + exact h + subst hxw0 + exact mulExpRay_run_bracket_scale_point hy habs + · -- the live region + have hlive : 2 ≤ int256 (mulShiftTree y x) := by + rcases hcase with h0 | hcl | hsh + · exact absurd h0 hx0 + · omega + · exact hsh + have hWx : WideRegion x := ⟨by omega, hxhi⟩ + have hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := + run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ + exact mulExpRay_run_bracket_of_tree hrun + (mulExpTree_bracket_live hy hx (by omega) habs hx0 hWx hlive) + +/-! ## Floor membership and the small-target pin -/ + +/-- The bracketed magnitude is the floor of the target or one below it. -/ +theorem mulExpRayMagnitudeBracket_mem_floor {y x m : Int} + (h : MulExpRayMagnitudeBracket y x m) : + m = ⌊mulExpRayMagnitudeTarget y x⌋ ∨ m = ⌊mulExpRayMagnitudeTarget y x⌋ - 1 := by + obtain ⟨hm0, hle, hlt⟩ := h + have h1 : m ≤ ⌊mulExpRayMagnitudeTarget y x⌋ := Int.le_floor.mpr hle + have h2 : ⌊mulExpRayMagnitudeTarget y x⌋ < m + 2 := by + rw [Int.floor_lt] + push_cast + exact hlt + omega + +/-- A target below one output unit pins the bracketed magnitude to zero. -/ +theorem mulExpRayMagnitudeBracket_pins_zero {y x m : Int} + (h : MulExpRayMagnitudeBracket y x m) + (hA : mulExpRayMagnitudeTarget y x < 1) : m = 0 := by + obtain ⟨hm0, hle, _⟩ := h + have h1 : (m : Real) < 1 := lt_of_le_of_lt hle hA + have h2 : m < 1 := by exact_mod_cast h1 + omega + +/-- **Floor membership on the value domain.** Every accepted input's result magnitude is `⌊A⌋` +or `⌊A⌋ − 1`. -/ +theorem mulExpRay_run_floor_membership {y x : Nat} (h : MulExpRayValueDomain y x) : + ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ + ((if int256 y < 0 then -(int256 r) else int256 r) = + ⌊mulExpRayMagnitudeTarget (int256 y) (int256 x)⌋ ∨ + (if int256 y < 0 then -(int256 r) else int256 r) = + ⌊mulExpRayMagnitudeTarget (int256 y) (int256 x)⌋ - 1) := by + obtain ⟨r, hrun, hbracket⟩ := mulExpRay_run_bracket h + refine ⟨r, hrun, ?_⟩ + unfold MulExpRayBracket at hbracket + split_ifs with hneg + · rw [if_pos hneg] at hbracket + exact mulExpRayMagnitudeBracket_mem_floor hbracket + · rw [if_neg hneg] at hbracket + exact mulExpRayMagnitudeBracket_mem_floor hbracket + +/-- **The small-target pin on the value domain.** A target magnitude below one output unit +forces a zero result. -/ +theorem mulExpRay_run_pins_zero {y x : Nat} (h : MulExpRayValueDomain y x) + (hA : mulExpRayMagnitudeTarget (int256 y) (int256 x) < 1) : + run_mul_exp_ray_evm y x = .ok 0 ∨ + ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ int256 r = 0 := by + obtain ⟨r, hrun, hbracket⟩ := mulExpRay_run_bracket h + unfold MulExpRayBracket at hbracket + right + refine ⟨r, hrun, ?_⟩ + split_ifs at hbracket with hneg + · have := mulExpRayMagnitudeBracket_pins_zero hbracket hA + omega + · exact mulExpRayMagnitudeBracket_pins_zero hbracket hA + +end + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean new file mode 100644 index 000000000..c2c4f2f68 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -0,0 +1,251 @@ +import ExpProof.Mul.Domain +import ExpProof.Mul.Shell +import ExpProof.Mono.Quot +import ExpProof.Floor.Spec + +/-! +# Shared word transports for the dynamic scale + +The `mulExpRay` kernel call runs at the dynamic scale `mulScaleTree y = abs(y)·2^S` and closing +shift `S − k`. This module transports those words to arithmetic facts the accumulator and the +monotonicity arguments consume: + +* the headroom shift `S` is at most `127`, and for a nonzero magnitude the scale is *maximal* — + one more doubling overshoots `scaleQ67` — which pins it into `(scaleQ67/2, scaleQ67]`, so every + live scale satisfies `2^125 ≤ scale ≤ scaleQ67`; +* the closing-shift word is the signed difference `S − k` on the wide region, and on the live + region (`2 ≤ shift` from the guard) it is a plain small `Nat` in `[2, 254]`; +* the closing `shr` keeps nonnegative small values small for any shift below the word size. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word + +set_option maxRecDepth 100000 + +/-! ## Word plumbing -/ + +private theorem u256_self {a : Nat} (h : a < 2 ^ 256) : u256 a = a := u256_of_lt_pow256 h + +private theorem evmSub_small {a b : Nat} (hb : b ≤ a) (ha : a < 2 ^ 256) : + evmSub a b = a - b := by + unfold evmSub + rw [u256_self ha, u256_self (lt_of_le_of_lt hb ha)] + unfold u256 WORD_MOD + omega + +private theorem evmShl_small {s v : Nat} (hs : s < 256) (hv : v < 2 ^ 256) + (h : v * 2 ^ s < 2 ^ 256) : evmShl s v = v * 2 ^ s := by + unfold evmShl + rw [u256_self (lt_trans hs (by norm_num)), u256_self hv, if_pos hs] + unfold u256 WORD_MOD + omega + +/-! ## The headroom shift: range and scale maximality -/ + +/-- The corrected headroom shift, by cases on the magnitude: `127` exactly at zero, and otherwise +at most `126` with the shifted scale maximal (one more doubling overshoots `scaleQ67`). -/ +private theorem scaleShiftTree_cases (ay : Nat) (hy : ay < 2 ^ 256) (habs : ay ≤ scaleQ67) : + (ay = 0 → scaleShiftTree ay = 127) ∧ + (1 ≤ ay → scaleShiftTree ay ≤ 126 ∧ + scaleQ67 < ay * 2 ^ (scaleShiftTree ay + 1)) := by + constructor + · intro h0 + subst h0 + have hclz : evmClz 0 = 256 := by + unfold evmClz + rw [u256_self (by norm_num)] + simp + have hs0 : evmSub 256 scaleMaxClz = 127 := by + rw [evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] + unfold scaleMaxClz + norm_num + have hshl : evmShl 127 (0 : Nat) = 0 := by + rw [evmShl_small (by norm_num) (by norm_num) (by norm_num)] + ring + have hgt : evmGt (0 : Nat) scaleQ67 = 0 := by + unfold evmGt + rw [u256_self (by norm_num), u256_self (by unfold scaleQ67; norm_num), if_neg (by omega)] + have hsub : evmSub 127 (0 : Nat) = 127 := evmSub_small (by omega) (by norm_num) + unfold scaleShiftTree + simp only [hclz, hs0, hshl, hgt, hsub] + · intro hpos + have hlog : Nat.log2 ay ≤ 126 := by + have h1 : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) + have hQ : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num + by_contra h + push_neg at h + have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 ay := + Nat.pow_le_pow_right (by norm_num) h + omega + have hloglo : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) + have hlt : ay < 2 ^ (Nat.log2 ay + 1) := Nat.lt_log2_self + have hclz : evmClz ay = 255 - Nat.log2 ay := by + unfold evmClz + rw [u256_self hy, if_neg (by omega)] + have hs0eq : evmSub (evmClz ay) scaleMaxClz = 126 - Nat.log2 ay := by + rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] + unfold scaleMaxClz + omega + have hfit : ay * 2 ^ (126 - Nat.log2 ay) < 2 ^ 127 := by + calc ay * 2 ^ (126 - Nat.log2 ay) + < 2 ^ (Nat.log2 ay + 1) * 2 ^ (126 - Nat.log2 ay) := + mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) + _ = 2 ^ (Nat.log2 ay + 1 + (126 - Nat.log2 ay)) := by rw [← pow_add] + _ ≤ 2 ^ 127 := Nat.pow_le_pow_right (by norm_num) (by omega) + have hshl : evmShl (126 - Nat.log2 ay) ay = ay * 2 ^ (126 - Nat.log2 ay) := + evmShl_small (by omega) hy (lt_trans hfit (by norm_num)) + -- the uncorrected scale already clears half of scaleQ67: ay·2^(126−log2) ≥ 2^126 > scaleQ67/2 + have hbig : (2 : Nat) ^ 126 ≤ ay * 2 ^ (126 - Nat.log2 ay) := by + calc (2:Nat) ^ 126 ≤ 2 ^ Nat.log2 ay * 2 ^ (126 - Nat.log2 ay) := by + rw [← pow_add] + exact Nat.pow_le_pow_right (by norm_num) (by omega) + _ ≤ ay * 2 ^ (126 - Nat.log2 ay) := Nat.mul_le_mul_right _ hloglo + by_cases hover : ay * 2 ^ (126 - Nat.log2 ay) > scaleQ67 + · have hgt : evmGt (ay * 2 ^ (126 - Nat.log2 ay)) scaleQ67 = 1 := by + unfold evmGt + rw [u256_self (lt_trans hfit (by norm_num)), + u256_self (by unfold scaleQ67; norm_num), if_pos hover] + have hs0pos : 0 < 126 - Nat.log2 ay := by + rcases Nat.eq_zero_or_pos (126 - Nat.log2 ay) with h | h + · rw [h] at hover + simp at hover + omega + · exact h + have hsub : evmSub (126 - Nat.log2 ay) 1 = 126 - Nat.log2 ay - 1 := + evmSub_small (by omega) (by omega) + have hsst : scaleShiftTree ay = 126 - Nat.log2 ay - 1 := by + unfold scaleShiftTree + simp only [hs0eq, hshl, hgt, hsub] + refine ⟨by omega, ?_⟩ + rw [hsst] + have hexp : 126 - Nat.log2 ay - 1 + 1 = 126 - Nat.log2 ay := by omega + rw [hexp] + exact hover + · have hgt : evmGt (ay * 2 ^ (126 - Nat.log2 ay)) scaleQ67 = 0 := by + unfold evmGt + rw [u256_self (lt_trans hfit (by norm_num)), + u256_self (by unfold scaleQ67; norm_num), if_neg hover] + have hsub : evmSub (126 - Nat.log2 ay) 0 = 126 - Nat.log2 ay := + evmSub_small (by omega) (by omega) + have hsst : scaleShiftTree ay = 126 - Nat.log2 ay := by + unfold scaleShiftTree + simp only [hs0eq, hshl, hgt, hsub] + refine ⟨by omega, ?_⟩ + rw [hsst] + -- doubling the uncorrected scale clears 2^127 > scaleQ67 + have hQ : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num + calc scaleQ67 < 2 ^ 127 := hQ + _ = 2 ^ 126 * 2 := by ring + _ ≤ ay * 2 ^ (126 - Nat.log2 ay) * 2 := Nat.mul_le_mul_right _ hbig + _ = ay * 2 ^ (126 - Nat.log2 ay + 1) := by rw [pow_succ]; ring + +/-- The headroom shift never exceeds `127` on supported magnitudes. -/ +theorem scaleShiftTree_le_127 {y : Nat} (habs : absTree y ≤ scaleQ67) : + scaleShiftTree (absTree y) ≤ 127 := by + obtain ⟨h0, hpos⟩ := scaleShiftTree_cases (absTree y) (absTree_lt y) habs + rcases Nat.eq_zero_or_pos (absTree y) with h | h + · omega + · have := (hpos h).1 + omega + +/-- **Scale maximality.** For a nonzero supported magnitude, one more doubling of the headroom +scale overshoots `scaleQ67`. -/ +theorem mulScaleTree_max {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) + (habs : absTree y ≤ scaleQ67) : scaleQ67 < 2 * mulScaleTree y := by + obtain ⟨_, hspec, _⟩ := mulScaleTree_spec hy habs + obtain ⟨_, hposcase⟩ := scaleShiftTree_cases (absTree y) (absTree_lt y) habs + obtain ⟨_, hmax⟩ := hposcase hpos + rw [hspec] + calc scaleQ67 < absTree y * 2 ^ (scaleShiftTree (absTree y) + 1) := hmax + _ = 2 * (absTree y * 2 ^ scaleShiftTree (absTree y)) := by rw [pow_succ]; ring + +/-- **Scale lower bound.** Every nonzero supported magnitude's headroom scale is at least +`2^125`. -/ +theorem mulScaleTree_lower {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) + (habs : absTree y ≤ scaleQ67) : 2 ^ 125 ≤ mulScaleTree y := by + have hmax := mulScaleTree_max hy hpos habs + have hQ : (2:Nat) ^ 126 ≤ scaleQ67 := by unfold scaleQ67; norm_num + omega + +/-! ## The closing-shift word -/ + +/-- The closing-shift word carries the signed difference `S − k` on the wide region. -/ +theorem mulShiftTree_transport {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) : + int256 (mulShiftTree y x) = + (scaleShiftTree (absTree y) : Int) - int256 (kTree x) := by + have hs127 := scaleShiftTree_le_127 habs + obtain ⟨hklo, hkhi⟩ := kTree_bound_wide hx hW + have hsw : scaleShiftTree (absTree y) < 2 ^ 256 := scaleShiftTree_lt _ + have hkw : kTree x < 2 ^ 256 := by unfold kTree; exact evmSar_lt _ _ + have hsi : int256 (scaleShiftTree (absTree y)) = (scaleShiftTree (absTree y) : Int) := + int256_of_lt (by + have : (127:Nat) < 2 ^ 255 := by norm_num + omega) + unfold mulShiftTree + rw [evmSub_transport hsw hkw ?_ ?_, hsi] + · rw [hsi] + have hs : (scaleShiftTree (absTree y) : Int) ≤ 127 := by exact_mod_cast hs127 + have hs0 : (0 : Int) ≤ (scaleShiftTree (absTree y) : Int) := Int.natCast_nonneg _ + simp only [ipow255] + linarith [hs, hs0, hklo, hkhi] + · rw [hsi] + have hs0 : (0 : Int) ≤ (scaleShiftTree (absTree y) : Int) := Int.natCast_nonneg _ + have hs : (scaleShiftTree (absTree y) : Int) ≤ 127 := by exact_mod_cast hs127 + simp only [ipow255] + linarith [hs, hs0, hklo, hkhi] + +/-- On the live region the closing-shift word is a plain small `Nat` in `[2, 254]`, equal to +`S − k` on the signed side. -/ +theorem mulShift_word_facts {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + 2 ≤ mulShiftTree y x ∧ mulShiftTree y x < 256 ∧ + (mulShiftTree y x : Int) = int256 (mulShiftTree y x) := by + have htrans := mulShiftTree_transport hy hx habs hW + have hs127 := scaleShiftTree_le_127 habs + obtain ⟨hklo, hkhi⟩ := kTree_bound_wide hx hW + have hs : (scaleShiftTree (absTree y) : Int) ≤ 127 := by exact_mod_cast hs127 + have hhi : int256 (mulShiftTree y x) ≤ 254 := by + rw [htrans] + omega + have hword : mulShiftTree y x < 2 ^ 256 := mulShiftTree_lt y x + have hnn : 0 ≤ int256 (mulShiftTree y x) := by omega + obtain ⟨heq, _⟩ := int256_eq_of_nonneg hword hnn + refine ⟨?_, ?_, heq.symm⟩ + · have : (2 : Int) ≤ (mulShiftTree y x : Int) := by rw [← heq]; exact hlive + exact_mod_cast this + · have : (mulShiftTree y x : Int) ≤ 254 := by rw [← heq]; exact hhi + have h254 : mulShiftTree y x ≤ 254 := by exact_mod_cast this + omega + +/-- Closing `shr` at any shift `s ∈ [2, 255]`: a nonnegative argument below `2^130` floors to a +nonnegative value below `2^128`. -/ +theorem mulShr_facts {W s : Nat} (hWw : W < 2 ^ 256) (hslo : 2 ≤ s) (hshi : s ≤ 255) + (hWnn : 0 ≤ int256 W) (hWhi : int256 W < 2 ^ 130) : + 0 ≤ int256 (evmShr s W) ∧ int256 (evmShr s W) < 2 ^ 128 := by + obtain ⟨hWi, _⟩ := int256_eq_of_nonneg hWw hWnn + have hWnat : W < 2 ^ 130 := by + have : ((W : Nat) : Int) < 2 ^ 130 := by rw [← hWi]; exact hWhi + exact_mod_cast this + rw [evmShr_eq_div (by omega) hWw] + have hqlt : W / 2 ^ s < 2 ^ 128 := by + have h4 : (2:Nat) ^ 2 ≤ 2 ^ s := Nat.pow_le_pow_right (by norm_num) hslo + have h1 : W / 2 ^ s ≤ W / 2 ^ 2 := Nat.div_le_div_left h4 (Nat.two_pow_pos _) + have h2 : W / 2 ^ 2 < 2 ^ 128 := by + rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] + calc W < 2 ^ 130 := hWnat + _ = 2 ^ 128 * 2 ^ 2 := by rw [← Nat.pow_add] + omega + rw [int256_of_lt (by + have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + omega)] + constructor + · positivity + · exact_mod_cast hqlt + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index a1f88817f..61ea119ef 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -7,6 +7,7 @@ import ExpProof.Floor.R0BoundHolds import ExpProof.Floor.R0Bound import ExpProof.Floor.RoundTrip import ExpProof.Mul.Shell +import ExpProof.Mul.Accum /-! # `expRayToWad` and `mulExpRay` — compiled-runtime proof signpost @@ -104,14 +105,18 @@ arguments. Discharged today, axiom-clean: | Guard word ↔ domain bridge | `valueDomain_iff_guard_eq_zero` | | Value path returns the compiled tree | `run_mul_exp_ray_evm_eq_tree` | | Rejected inputs revert | `run_mul_exp_ray_evm_revert` | +| Signed bracket `0 ≤ m ≤ A < m + 2` on the domain | `mulExpRay_run_bracket` | +| Result magnitude is `⌊A⌋` or `⌊A⌋ − 1` | `mulExpRay_run_floor_membership` | +| `A < 1` pins the result to zero | `mulExpRay_run_pins_zero` | | Zero multiplier returns zero (and its bracket) | `run_mul_exp_ray_evm_zero_of_guard` | | Scale point `mulExpRay(y, 0) = y` (and its bracket) | `run_mul_exp_ray_evm_scale_point` | | Zero clamp at deep-negative `x` (and its bracket) | `run_mul_exp_ray_evm_clamped` | -Still open, visible below as explicit hypotheses of the facade lemmas: the bracket on the live -region (`x` strictly between the clamp cutoff and the scale point's octave limit) and the runtime -monotonicity statements, both of which need the `Floor` certificates generalized from the fixed -wad scale `10¹⁸·2⁶⁷` to the dynamic scale `abs(y)·2ˢ`. +The bracket is proven on the whole value domain: the scale-symbolic per-point certificates +(`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) instantiate at the dynamic scale +`abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`, and the accumulator fold (`Mul.Accum`) closes the live region. +Still open, visible below as explicit hypotheses of the facade lemmas: the runtime monotonicity +statements. -/ /-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ @@ -119,6 +124,24 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := mulExpRay_value_or_panic_of_canonical hcanon +/-- **The signed bracket on the whole value domain.** Every accepted input returns a result whose +magnitude `m` satisfies `0 ≤ m ≤ A ∧ A < m + 2` for `A = abs(y)·exp(x/10²⁷)`. -/ +example {y x : Nat} (h : MulExpRayValueDomain y x) : MulExpRayRunBracket y x := + mulExpRay_run_bracket h + +/-- **Floor membership.** Every accepted input's result magnitude is `⌊A⌋` or `⌊A⌋ − 1`. -/ +example {y x : Nat} (h : MulExpRayValueDomain y x) : + ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ + ((if FormalYul.Preservation.int256 y < 0 + then -(FormalYul.Preservation.int256 r) else FormalYul.Preservation.int256 r) = + ⌊ExpRealSpec.mulExpRayMagnitudeTarget (FormalYul.Preservation.int256 y) + (FormalYul.Preservation.int256 x)⌋ ∨ + (if FormalYul.Preservation.int256 y < 0 + then -(FormalYul.Preservation.int256 r) else FormalYul.Preservation.int256 r) = + ⌊ExpRealSpec.mulExpRayMagnitudeTarget (FormalYul.Preservation.int256 y) + (FormalYul.Preservation.int256 x)⌋ - 1) := + mulExpRay_run_floor_membership h + /-- The value and panic guards are disjoint on canonical inputs. -/ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ↔ ¬ MulExpRayPanicDomain y x := @@ -273,6 +296,18 @@ example {y1 y2 x1 x2 : Int} ExpRealSpec.mulExpRayTarget y1 x1 ≤ ExpRealSpec.mulExpRayTarget y2 x2 := ExpRealSpec.mulExpRayTarget_joint_mono h +/-- info: 'ExpYul.mulExpRay_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_bracket + +/-- info: 'ExpYul.mulExpRay_run_floor_membership' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_floor_membership + +/-- info: 'ExpYul.mulExpRay_run_pins_zero' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpRay_run_pins_zero + /-- info: 'ExpYul.mulExpRay_run_bracket_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms mulExpRay_run_bracket_of_tree From c69c85e0c77e0f91830cba5a01e052b506dd0cb5 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 14:34:03 +0200 Subject: [PATCH 070/107] Prove mulExpRay monotone in the exponent on the value domain The same-octave step machinery gains wide-region variants (the reduced- and squared-argument step gaps, the smooth certificate, and the tod*ev cross inequality), and the scaled quotient inherits the seam doubling bound r0_1 + 3 <= 2*r0_2 at any live scale, where the exp(-1/RAY) slack against r0_2 > 2^122 still dwarfs the per-point envelopes. Mul/XMono.lean assembles the sign-directed monotonicity: within an octave the dynamic-scale quotient is monotone through the cross certificate and the closing shift is constant; across a seam the shift loses one bit and seam_close absorbs the doubling; the unit-step induction sweeps the live region, which the octave-monotone shift keeps downward closed, and never crosses the scale point - a negative live exponent's magnitude sits below abs(y) outright while a positive one clears abs(y) through the analytic pin step at x = 1 (one exponent unit is worth scale/10^27 >= 2^98 quotient units). Sign reapplication and the clamp/scale-point shells close the public statement, gated in the signpost. Co-Authored-By: Claude Fable 5 --- .../ExpProof/ExpProof/Floor/R0ExpUnder.lean | 76 ++ .../exp/ExpProof/ExpProof/Mono/CrossCert.lean | 57 ++ formal/exp/ExpProof/ExpProof/Mono/Gaps.lean | 70 ++ formal/exp/ExpProof/ExpProof/Mul/XMono.lean | 726 ++++++++++++++++++ formal/exp/ExpProof/ExpProof/Theorems.lean | 24 +- 5 files changed, 948 insertions(+), 5 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Mul/XMono.lean diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean index ae01f96f5..4cf8aa1aa 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean @@ -854,6 +854,82 @@ theorem r0_seam_double {x1 x2 : Nat} int256 (r0Tree x1) + 3 ≤ 2 * int256 (r0Tree x2) := r0_seam_double_wide hx1 hx2 (wideRegion_of_wad hC1 hC01) (wideRegion_of_wad hC2 hC02) hk hadj +/-- **The scaled quotient at most doubles across a seam, three units short**, at any live scale: +the seam slack `exp(−1/RAY) < 1` against `r0₂ > 2¹²²` (worth `≈ 5·10⁹` grid units at the minimal +scale) still dwarfs the per-point envelopes and the three integer units. -/ +theorem r0Scaled_seam_double {scale x1 x2 : Nat} + (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x2) = int256 (kTree x1) + 1) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (r0ScaledTree scale x1) + 3 ≤ 2 * int256 (r0ScaledTree scale x2) := by + have hover1 := r0Scaled_real_over_within hslo hshi hx1 hW1 + have hunder2 := r0Scaled_real_under_within hslo hshi hx2 hW2 + have hr0_2_big := r0Scaled_gt_2122 hslo hshi hx2 hW2 + have hseam := reducedArg_seam hk hadj + set E1 := Real.exp (reducedArg x1) with hE1 + set E2 := Real.exp (reducedArg x2) with hE2 + set y := Real.exp (-(1 / (10 ^ 27 : Real))) with hy + have hy_pos : 0 < y := Real.exp_pos _ + have hy_bound : y ≤ 1 - 1 / (2 * (10 ^ 27 : Real)) := by + rw [hy] + have hz : (0:Real) < 1 / (10 ^ 27 : Real) := by positivity + have hez : (1 : Real) + 1 / (10 ^ 27 : Real) ≤ Real.exp (1 / (10 ^ 27 : Real)) := by + have := Real.add_one_le_exp (1 / (10 ^ 27 : Real)); linarith [this] + rw [Real.exp_neg] + have hexppos : 0 < Real.exp (1 / (10 ^ 27 : Real)) := Real.exp_pos _ + rw [inv_le_iff_one_le_mul₀ hexppos] + have h1z : (1 - 1 / (2 * (10 ^ 27 : Real))) * (1 + 1 / (10 ^ 27 : Real)) ≥ 1 := by + rw [ge_iff_le]; nlinarith [sq_nonneg (1 / (10 ^ 27 : Real))] + nlinarith [hez, h1z, hexppos, mul_pos (by positivity : (0:Real) < 1 - 1/(2*(10^27:Real))) hexppos] + have hE2bound : (scale : Real) * E2 ≤ (int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real) := + hunder2 + have hr0_1 : (int256 (r0ScaledTree scale x1) : Real) ≤ + 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y + + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + have h1 : (scale : Real) * E1 = 2 * ((scale : Real) * E2) * y := by + rw [hseam]; ring + have h2 : (int256 (r0ScaledTree scale x1) : Real) ≤ (scale : Real) * E1 + + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := hover1 + rw [h1] at h2 + have h3 : 2 * ((scale : Real) * E2) * y ≤ + 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y := + mul_le_mul_of_nonneg_right + (by linarith [mul_le_mul_of_nonneg_left hE2bound (by norm_num : (0:Real) ≤ 2)]) + (le_of_lt hy_pos) + linarith [h2, h3] + have hr0_2nn : (0:Real) ≤ (int256 (r0ScaledTree scale x2) : Real) := by + linarith [hr0_2_big, (by positivity : (0:Real) ≤ (2:Real)^122)] + have hkey : 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y + + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) + 3 < + 2 * (int256 (r0ScaledTree scale x2) : Real) := by + have hyb : 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y ≤ + 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * (1 - 1 / (2 * (10 ^ 27 : Real))) := by + apply mul_le_mul_of_nonneg_left hy_bound + linarith [hr0_2nn] + have hexpand : 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * + (1 - 1 / (2 * (10 ^ 27 : Real))) = + 2 * (int256 (r0ScaledTree scale x2) : Real) + 2 * (2993 / 1000 : Real) - + ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) / (10 ^ 27 : Real) := by + field_simp + ring + have hbig : ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) / (10 ^ 27 : Real) > 30 := by + rw [gt_iff_lt, lt_div_iff₀ (by positivity)] + nlinarith [hr0_2_big, (by norm_num : (30:Real) * 10 ^ 27 + 1 < 2 ^ 122)] + have hUB : 2 * (2993 / 1000 : Real) + + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) + 3 < 30 := by + norm_num + linarith [hyb, hexpand ▸ hyb, hbig, hUB] + have hreal : (int256 (r0ScaledTree scale x1) : Real) + 3 ≤ + 2 * (int256 (r0ScaledTree scale x2) : Real) := by + linarith [hr0_1, hkey] + have hcast : ((int256 (r0ScaledTree scale x1) + 3 : Int) : Real) ≤ + ((2 * int256 (r0ScaledTree scale x2) : Int) : Real) := by + push_cast + linarith [hreal] + exact_mod_cast hcast + end end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/CrossCert.lean b/formal/exp/ExpProof/ExpProof/Mono/CrossCert.lean index 7b4aaca14..e2138885e 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/CrossCert.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/CrossCert.lean @@ -224,4 +224,61 @@ theorem tod_cross {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) exact tod_cross_of hfl1 hfu2 hev1pos hev2nn (smooth_cross hx1 hx2 hC1 hC01 hC2 hC02 hk hadj) +/-- The squared-argument step gap on the wide region, as a `Nat` two-sided gap. -/ +theorem vTree_step_nat_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x1) = int256 (kTree x2)) + (hadj : int256 x2 = int256 x1 + 1) : + vTree x1 ≤ vTree x2 + Wstep ∧ vTree x2 ≤ vTree x1 + Wstep := by + obtain ⟨hlo, hhi⟩ := vTree_step_wide hx1 hx2 hW1 hW2 hk hadj + have c1 : (vTree x1 : Int) ≤ (vTree x2 : Int) + Wstep := by omega + have c2 : (vTree x2 : Int) ≤ (vTree x1 : Int) + Wstep := by omega + exact ⟨by exact_mod_cast c1, by exact_mod_cast c2⟩ + +/-- **The smooth certificate on the wide region.** -/ +theorem smooth_cross_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x1) = int256 (kTree x2)) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (tTree x1) * (odTree x1 : Int) * (evTree x2 : Int) + + 2 ^ 129 * (evTree x1 : Int) ≤ + int256 (tTree x2) * (odTree x2 : Int) * (evTree x1 : Int) := by + have hv1 : vTree x1 < 2 ^ 120 := (vTree_eq_wide hx1 hW1).2 + have hv2 : vTree x2 < 2 ^ 120 := (vTree_eq_wide hx2 hW2).2 + obtain ⟨hg1, hg2⟩ := vTree_step_nat_wide hx1 hx2 hW1 hW2 hk hadj + obtain ⟨hev1lo, hev1hi⟩ := evTree_int hv1 + obtain ⟨hev2lo, hev2hi⟩ := evTree_int hv2 + obtain ⟨hod2lo, hod2hi⟩ := odTree_int hv2 + obtain ⟨hevd1, hevd2⟩ := evTree_lip_int hv1 hv2 hg1 hg2 + obtain ⟨hodd1, hodd2⟩ := odTree_lip_int hv1 hv2 hg1 hg2 + obtain ⟨htg1, -⟩ := tTree_step_wide hx1 hx2 hW1 hW2 hk hadj + obtain ⟨htlo1, hthi1⟩ := tTree_bound_wide hx1 hW1 + have hGv : (Gstep : Int) = 680564733841 := by unfold Gstep; norm_num + rw [hGv] at htg1 + rw [show (2 : Int) ^ 128 = 340282366920938463463374607431768211456 by norm_num] at htlo1 hthi1 + rw [show (3 : Int) * 2 ^ 127 = 510423550381407695195061911147652317184 by norm_num] at hev1hi hev2hi + rw [show (5 : Int) * 2 ^ 125 = 212676479325586539664609129644855132160 by norm_num] at hod2hi + rw [show (2 : Int) ^ 129 = 680564733841876926926749214863536422912 by norm_num] + have ht2eq : int256 (tTree x2) = int256 (tTree x1) + (int256 (tTree x2) - int256 (tTree x1)) := by + ring + rw [ht2eq] + exact smooth_cross_of htg1 htlo1 hthi1 hev1lo hev1hi hev2lo hev2hi hod2lo hod2hi + hevd1 hevd2 hodd1 hodd2 + +/-- **The same-octave cross inequality on the wide region.** -/ +theorem tod_cross_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x1) = int256 (kTree x2)) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (todTree x1) * (evTree x2 : Int) ≤ int256 (todTree x2) * (evTree x1 : Int) := by + obtain ⟨_, _, hfl1, _⟩ := todTree_bound_wide hx1 hW1 + obtain ⟨_, _, _, hfu2⟩ := todTree_bound_wide hx2 hW2 + have hv1 : vTree x1 < 2 ^ 120 := (vTree_eq_wide hx1 hW1).2 + have hv2 : vTree x2 < 2 ^ 120 := (vTree_eq_wide hx2 hW2).2 + have hev1pos : 0 < (evTree x1 : Int) := by + have := (evTree_int hv1).1; linarith + have hev2nn : 0 ≤ (evTree x2 : Int) := Int.natCast_nonneg _ + exact tod_cross_of hfl1 hfu2 hev1pos hev2nn + (smooth_cross_wide hx1 hx2 hW1 hW2 hk hadj) + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/Gaps.lean b/formal/exp/ExpProof/ExpProof/Mono/Gaps.lean index 17b948327..9a14e90c9 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Gaps.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Gaps.lean @@ -116,4 +116,74 @@ theorem vTree_step {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) · nlinarith [hvlo1, hvhi1, hvlo2, hvhi2, htg1, htg2, htlo1, hthi1, htlo2, hthi2, hsqdiff] · nlinarith [hvlo1, hvhi1, hvlo2, hvhi2, htg1, htg2, htlo1, hthi1, htlo2, hthi2, hsqdiff] +/-- The reduced-argument step on the wide region: `G` or `G + 1`. -/ +theorem tTree_step_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x1) = int256 (kTree x2)) + (hadj : int256 x2 = int256 x1 + 1) : + (Gstep : Int) ≤ int256 (tTree x2) - int256 (tTree x1) ∧ + int256 (tTree x2) - int256 (tTree x1) ≤ Gstep + 1 := by + obtain ⟨hlo1, hhi1⟩ := tTree_sandwich_wide hx1 hW1 + obtain ⟨hlo2, hhi2⟩ := tTree_sandwich_wide hx2 hW2 + rw [hk] at hlo1 hhi1 + have hK27 := K27_decomp + have hp107 : (0 : Int) < 2 ^ 106 := by norm_num + set K27 := (0x279d346de4781f921dd7a89933d54d1f72928 : Int) with hK27def + set LN2 := (0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d : Int) with hLN2def + set k := int256 (kTree x2) + set t1 := int256 (tTree x1) + set t2 := int256 (tTree x2) + set X1 := int256 x1 + set X2 := int256 x2 + have hstep : K27 * X2 - LN2 * k = (K27 * X1 - LN2 * k) + K27 := by rw [hadj]; ring + rw [hstep] at hlo2 hhi2 + set A := K27 * X1 - LN2 * k + have hrem_pos := Gstep_rem_pos + have hrem_lt := Gstep_rem_lt + constructor + · nlinarith [hlo1, hhi1, hlo2, hhi2, hK27, hrem_pos, hrem_lt, hp107] + · nlinarith [hlo1, hhi1, hlo2, hhi2, hK27, hrem_pos, hrem_lt, hp107] + +/-- The squared-argument floor sandwich on the wide region. -/ +theorem vTree_sandwich_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : + (2 ^ 135 : Int) * (vTree x : Int) ≤ (int256 (tTree x)) ^ 2 ∧ + (int256 (tTree x)) ^ 2 < (2 ^ 135 : Int) * (vTree x : Int) + 2 ^ 135 := by + obtain ⟨hveq, _⟩ := vTree_eq_wide hx hW + rw [hveq] + set a := (int256 (tTree x)) ^ 2 with ha + have h1 := Int.ediv_add_emod a (2 ^ 135) + have h2 := Int.emod_nonneg a (by norm_num : (2 : Int) ^ 135 ≠ 0) + have h3 := Int.emod_lt_of_pos a (by norm_num : (0 : Int) < 2 ^ 135) + constructor <;> nlinarith [h1, h2, h3] + +/-- The squared-argument step on the wide region is bounded by `W`. -/ +theorem vTree_step_wide {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x1) = int256 (kTree x2)) + (hadj : int256 x2 = int256 x1 + 1) : + -((Wstep : Int)) ≤ (vTree x2 : Int) - (vTree x1 : Int) ∧ + (vTree x2 : Int) - (vTree x1 : Int) ≤ Wstep := by + obtain ⟨htg1, htg2⟩ := tTree_step_wide hx1 hx2 hW1 hW2 hk hadj + obtain ⟨htlo1, hthi1⟩ := tTree_bound_wide hx1 hW1 + obtain ⟨htlo2, hthi2⟩ := tTree_bound_wide hx2 hW2 + obtain ⟨hvlo1, hvhi1⟩ := vTree_sandwich_wide hx1 hW1 + obtain ⟨hvlo2, hvhi2⟩ := vTree_sandwich_wide hx2 hW2 + have hGpos : (0 : Int) ≤ Gstep := by unfold Gstep; norm_num + have hp128 : (2 : Int) ^ 128 = 340282366920938463463374607431768211456 := by norm_num + have hp135 : (2 : Int) ^ 135 = 43556142965880123323311949751266331066368 := by norm_num + rw [hp128] at htlo1 hthi1 htlo2 hthi2 + rw [hp135] at hvlo1 hvhi1 hvlo2 hvhi2 + set t1 := int256 (tTree x1) + set t2 := int256 (tTree x2) + set v1 := (vTree x1 : Int) + set v2 := (vTree x2 : Int) + have hsqdiff : t2 ^ 2 - t1 ^ 2 = (t2 - t1) * (t2 + t1) := by ring + have hGv : (Gstep : Int) = 680564733841 := by unfold Gstep; norm_num + have hWv : (Wstep : Int) = 10633823967 := by unfold Wstep; norm_num + rw [hGv] at htg1 htg2 + rw [hWv] + constructor + · nlinarith [hvlo1, hvhi1, hvlo2, hvhi2, htg1, htg2, htlo1, hthi1, htlo2, hthi2, hsqdiff] + · nlinarith [hvlo1, hvhi1, hvlo2, hvhi2, htg1, htg2, htlo1, hthi1, htlo2, hthi2, hsqdiff] + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean new file mode 100644 index 000000000..97faf935a --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean @@ -0,0 +1,726 @@ +import ExpProof.Mul.Accum +import ExpProof.Mono.CrossCert +import ExpProof.Mono.Seam + +/-! +# `mulExpRay` monotonicity in the exponent + +At a fixed multiplier the kernel magnitude is nondecreasing in the exponent over the accepted +inputs. The live region is swept by a unit-step induction: within an octave the scaled quotient is +monotone (the `tod·ev` cross certificate at the dynamic scale), and across a seam the closing +shift loses one bit while the quotient at most doubles three units short +(`r0Scaled_seam_double`), so the shifted floors stay ordered (`seam_close`). The scale point +`x = 0` never sits inside an induction range: a negative live exponent's magnitude is below +`abs(y)` outright (its target is), and a positive live exponent's magnitude is at least `abs(y)` +through the analytic pin step at `x = 1` (`exp(10⁻²⁷) ≥ 1 + 10⁻²⁷` is worth `scale/10²⁷ ≥ 2⁹⁸` +quotient units, far above the deficit envelope). Sign reapplication turns magnitude monotonicity +into the signed public statement on the whole value domain. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word +open ExpRealSpec + +set_option maxRecDepth 100000 +set_option maxHeartbeats 1600000 + +/-! ## Word plumbing -/ + +private theorem int256_inj {a b : Nat} (ha : a < 2 ^ 256) (hb : b < 2 ^ 256) + (h : int256 a = int256 b) : a = b := by + have hp : (2 : Int) ^ 256 = 115792089237316195423570985008687907853269984665640564039457584007913129639936 := + intPow256 + have ha' : (a : Int) < 2 ^ 256 := by exact_mod_cast ha + have hb' : (b : Int) < 2 ^ 256 := by exact_mod_cast hb + rw [hp] at ha' hb' + unfold int256 at h + split at h <;> split at h <;> first | (rw [hp] at h; omega) | omega + +/-- The shift word is constant within an octave (fixed multiplier). -/ +private theorem mulShift_word_eq {y x1 x2 : Nat} + (hk : int256 (kTree x1) = int256 (kTree x2)) : + mulShiftTree y x1 = mulShiftTree y x2 := by + have hk1w : kTree x1 < 2 ^ 256 := by unfold kTree; exact evmSar_lt _ _ + have hk2w : kTree x2 < 2 ^ 256 := by unfold kTree; exact evmSar_lt _ _ + unfold mulShiftTree + rw [int256_inj hk1w hk2w hk] + +/-- The signed shift is antitone in the exponent (the octave index is monotone). -/ +theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (habs : absTree y ≤ scaleQ67) (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hle : int256 x1 ≤ int256 x2) : + int256 (mulShiftTree y x2) ≤ int256 (mulShiftTree y x1) := by + rw [mulShiftTree_transport hy hx1 habs hW1, mulShiftTree_transport hy hx2 habs hW2] + have hkmono := kTree_mono_wide hx1 hx2 hW1.1 hle hW2.2 + linarith [hkmono] + +/-- The decremented quotient word: transport and range at the dynamic scale. -/ +private theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) : + int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 ∧ + 0 ≤ int256 (r0MulTree y x) - 1 ∧ int256 (r0MulTree y x) - 1 < 2 ^ 130 := by + have hpos : 1 ≤ absTree y := absTree_pos hy hy0 + have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs + obtain ⟨_, _, hshi⟩ := mulScaleTree_spec hy habs + have hr0eq : r0MulTree y x = r0ScaledTree (mulScaleTree y) x := r0MulTree_eq_scaled y x + obtain ⟨hr0lo, hr0hi⟩ := r0Scaled_bounds hslo hshi hx hW + rw [← hr0eq] at hr0lo hr0hi + have hr0w : r0MulTree y x < 2 ^ 256 := r0MulTree_lt y x + have hmarlt : (marginWord : Nat) < 2 ^ 256 := by unfold marginWord; norm_num + have hmari : int256 (marginWord : Nat) = 1 := by + unfold marginWord + rw [int256_of_lt (by norm_num)] + norm_num + have hp123 : (2:Int)^123 = 10633823966279326983230456482242756608 := by norm_num + have hp130 : (2:Int)^130 = 1361129467683753853853498429727072845824 := by norm_num + rw [hp123] at hr0lo + rw [hp130] at hr0hi + have hsub : int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 := by + have := evmSub_transport hr0w hmarlt + (by rw [hmari]; simp only [ipow255]; linarith [hr0lo, hr0hi]) + (by rw [hmari]; simp only [ipow255]; linarith [hr0lo, hr0hi]) + rw [hmari] at this + exact this + exact ⟨hsub, by linarith [hr0lo], by linarith [hr0hi]⟩ + +/-! ## The unit step on the live region -/ + +/-- Adjacent same-octave quotient monotonicity at the dynamic scale. -/ +theorem r0Mul_mono_adjacent {y x1 x2 : Nat} (hy : y < 2 ^ 256) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hk : int256 (kTree x1) = int256 (kTree x2)) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (r0MulTree y x1) ≤ int256 (r0MulTree y x2) := by + obtain ⟨_, _, hshi⟩ := mulScaleTree_spec hy habs + have hv1 : vTree x1 < 2 ^ 120 := (vTree_eq_wide hx1 hW1).2 + have hv2 : vTree x2 < 2 ^ 120 := (vTree_eq_wide hx2 hW2).2 + obtain ⟨hev1lo, hev1hi⟩ := evTree_int hv1 + obtain ⟨hev2lo, hev2hi⟩ := evTree_int hv2 + obtain ⟨htod1lo, htod1hi, _, _⟩ := todTree_bound_wide hx1 hW1 + obtain ⟨htod2lo, htod2hi, _, _⟩ := todTree_bound_wide hx2 hW2 + have hevw1 : evTree x1 < 2 ^ 256 := by unfold evTree; exact evmAdd_lt _ _ + have hevw2 : evTree x2 < 2 ^ 256 := by unfold evTree; exact evmAdd_lt _ _ + have htodw1 : todTree x1 < 2 ^ 256 := by unfold todTree; exact evmSar_lt _ _ + have htodw2 : todTree x2 < 2 ^ 256 := by unfold todTree; exact evmSar_lt _ _ + have hcross := tod_cross_wide hx1 hx2 hW1 hW2 hk hadj + have hp126 : (2:Int)^126 = 85070591730234615865843651857942052864 := by norm_num + rw [hp126] at htod1lo htod1hi htod2lo htod2hi + have hr01 : r0MulTree y x1 = + evmDiv (evmMul (mulScaleTree y) (evmAdd (evTree x1) (todTree x1))) + (evmSub (evTree x1) (todTree x1)) := rfl + have hr02 : r0MulTree y x2 = + evmDiv (evmMul (mulScaleTree y) (evmAdd (evTree x2) (todTree x2))) + (evmSub (evTree x2) (todTree x2)) := rfl + rw [hr01, hr02] + exact r0_mono_of_cross hshi hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo htod1hi + hev2lo hev2hi htod2lo htod2hi hcross + +/-- **The live unit step**: for adjacent live exponents the kernel magnitude is nondecreasing. -/ +theorem mulMagnitude_step {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hx10 : int256 x1 ≠ 0) (hx20 : int256 x2 ≠ 0) + (hlive1 : 2 ≤ int256 (mulShiftTree y x1)) (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) + (hadj : int256 x2 = int256 x1 + 1) : + int256 (mulMagnitudeTree y x1) ≤ int256 (mulMagnitudeTree y x2) := by + have hm1 := mulMagnitudeTree_live (y := y) hx1 hx10 hW1.1 + have hm2 := mulMagnitudeTree_live (y := y) hx2 hx20 hW2.1 + obtain ⟨harg1eq, harg1nn, harg1hi⟩ := mulShiftArg_facts hy hy0 hx1 habs hW1 + obtain ⟨harg2eq, harg2nn, harg2hi⟩ := mulShiftArg_facts hy hy0 hx2 habs hW2 + obtain ⟨hsh1lo, hsh1lt, hsh1eq⟩ := mulShift_word_facts hy hx1 habs hW1 hlive1 + obtain ⟨hsh2lo, hsh2lt, hsh2eq⟩ := mulShift_word_facts hy hx2 habs hW2 hlive2 + rw [hm1, hm2] + rcases kTree_step_wide hx1 hx2 hW1 hW2 hadj with hsame | hseam + · -- same octave: shift words coincide, quotient monotone, same-shift floor monotone + have hkeq : int256 (kTree x1) = int256 (kTree x2) := hsame.symm + have hsheq' : mulShiftTree y x1 = mulShiftTree y x2 := mulShift_word_eq hkeq + have hr0mono := r0Mul_mono_adjacent hy hx1 hx2 habs hW1 hW2 hkeq hadj + rw [← hsheq'] + set arg1 := evmSub (r0MulTree y x1) marginWord with harg1def + set arg2 := evmSub (r0MulTree y x2) marginWord with harg2def + have ha1lt : arg1 < 2 ^ 256 := by rw [harg1def]; exact evmSub_lt _ _ + have ha2lt : arg2 < 2 ^ 256 := by rw [harg2def]; exact evmSub_lt _ _ + clear_value arg1 arg2 + have hargle : int256 arg1 ≤ int256 arg2 := by + rw [harg1eq, harg2eq] + exact sub_le_sub_right hr0mono 1 + obtain ⟨he1, hlt1⟩ := int256_eq_of_nonneg ha1lt (by rw [harg1eq]; exact harg1nn) + obtain ⟨he2, hlt2⟩ := int256_eq_of_nonneg ha2lt (by rw [harg2eq]; exact harg2nn) + have hargleN : arg1 ≤ arg2 := by + have : ((arg1 : Nat) : Int) ≤ ((arg2 : Nat) : Int) := by rw [← he1, ← he2]; exact hargle + exact_mod_cast this + rw [evmShr_eq_div hsh1lt ha1lt, evmShr_eq_div hsh1lt ha2lt] + have hqle : arg1 / 2 ^ mulShiftTree y x1 ≤ arg2 / 2 ^ mulShiftTree y x1 := + Nat.div_le_div_right hargleN + have hq1lt : arg1 / 2 ^ mulShiftTree y x1 < 2 ^ 255 := by + have h1 : arg1 / 2 ^ mulShiftTree y x1 ≤ arg1 := Nat.div_le_self _ _ + exact lt_of_le_of_lt h1 hlt1 + have hq2lt : arg2 / 2 ^ mulShiftTree y x1 < 2 ^ 255 := by + have h1 : arg2 / 2 ^ mulShiftTree y x1 ≤ arg2 := Nat.div_le_self _ _ + exact lt_of_le_of_lt h1 hlt2 + rw [int256_of_lt hq1lt, int256_of_lt hq2lt] + exact_mod_cast hqle + · -- octave seam: shift drops one bit, the quotient at most doubles three units short + have hpos : 1 ≤ absTree y := absTree_pos hy hy0 + have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs + obtain ⟨_, _, hshi⟩ := mulScaleTree_spec hy habs + have htr1 := mulShiftTree_transport hy hx1 habs hW1 + have htr2 := mulShiftTree_transport hy hx2 habs hW2 + have hseq : mulShiftTree y x2 + 1 = mulShiftTree y x1 := by + have h1 : (mulShiftTree y x1 : Int) = + (scaleShiftTree (absTree y) : Int) - int256 (kTree x1) := by rw [hsh1eq, htr1] + have h2 : (mulShiftTree y x2 : Int) = + (scaleShiftTree (absTree y) : Int) - int256 (kTree x2) := by rw [hsh2eq, htr2] + have : (mulShiftTree y x2 : Int) + 1 = (mulShiftTree y x1 : Int) := by + rw [h1, h2, hseam] + ring + exact_mod_cast this + have hdouble : int256 (r0MulTree y x1) + 3 ≤ 2 * int256 (r0MulTree y x2) := by + have h := r0Scaled_seam_double hslo hshi hx1 hx2 hW1 hW2 hseam hadj + rw [← r0MulTree_eq_scaled, ← r0MulTree_eq_scaled] at h + exact h + set arg1 := evmSub (r0MulTree y x1) marginWord with harg1def + set arg2 := evmSub (r0MulTree y x2) marginWord with harg2def + have ha1lt : arg1 < 2 ^ 256 := by rw [harg1def]; exact evmSub_lt _ _ + have ha2lt : arg2 < 2 ^ 256 := by rw [harg2def]; exact evmSub_lt _ _ + clear_value arg1 arg2 + have hargle : int256 arg1 ≤ 2 * int256 arg2 := by + rw [harg1eq, harg2eq] + linarith [hdouble] + exact seam_close ha1lt ha2lt hsh1lt hsh2lt hseq + (by rw [harg1eq]; exact harg1nn) (by rw [harg2eq]; exact harg2nn) hargle + +/-! ## The region induction -/ + +/-- Unit-step induction over the live region: `n` steps up from `x1`, all inside the live region +(the endpoint's live shift bounds every intermediate through octave monotonicity, and the sign +condition keeps the scale point outside the range). -/ +theorem mulMagnitude_mono_steps {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (habs : absTree y ≤ scaleQ67) (n : Nat) : + ∀ x1 : Nat, x1 < 2 ^ 256 → + int256 mulExpRayZeroMax < int256 x1 → + int256 x1 + n < int256 mulExpRayHi → + (int256 x1 + n < 0 ∨ 0 < int256 x1) → + 2 ≤ int256 (mulShiftTree y (uint256OfInt (int256 x1 + n))) → + int256 x1 + n = int256 (uint256OfInt (int256 x1 + n)) → + int256 (mulMagnitudeTree y x1) ≤ + int256 (mulMagnitudeTree y (uint256OfInt (int256 x1 + n))) := by + induction n with + | zero => + intro x1 hx1 hlo _ _ _ _ + have hw : uint256OfInt (int256 x1 + (0 : Nat)) = x1 := by + rw [show ((0 : Nat) : Int) = 0 by rfl, Int.add_zero] + exact uint256OfInt_int256 hx1 + rw [hw] + | succ m ih => + intro x1 hx1 hlo hbnd hsign hlive htgt + obtain ⟨hzm, hhi⟩ : int256 mulExpRayZeroMax < int256 x1 + 1 ∧ + int256 x1 + 1 < int256 mulExpRayHi := by + have h1 : int256 x1 + (m + 1 : Nat) < int256 mulExpRayHi := hbnd + push_cast at h1 + omega + have hw1lt : uint256OfInt (int256 x1 + 1) < 2 ^ 256 := uint256OfInt_lt _ + have hw1eq : int256 (uint256OfInt (int256 x1 + 1)) = int256 x1 + 1 := by + refine int256_uint256OfInt ?_ ?_ + · rw [int256_mulExpRayZeroMax] at hzm + simp only [ipow255] + omega + · rw [int256_mulExpRayHi] at hhi + simp only [ipow255] + omega + set x' := uint256OfInt (int256 x1 + 1) with hx' + have hW1 : WideRegion x1 := ⟨hlo, by + have h1 : int256 x1 + (m + 1 : Nat) < int256 mulExpRayHi := hbnd + push_cast at h1 + omega⟩ + have hW' : WideRegion x' := ⟨by omega, by omega⟩ + -- the top endpoint of the range + set xt := uint256OfInt (int256 x1 + (m + 1 : Nat)) with hxt + have hxtlt : xt < 2 ^ 256 := uint256OfInt_lt _ + have hWt : WideRegion xt := by + constructor + · rw [← htgt] + push_cast + omega + · rw [← htgt] + exact hbnd + -- every point below the top endpoint keeps at least its shift + have hlive' : 2 ≤ int256 (mulShiftTree y x') := by + have hmono := mulShift_antitone hy hw1lt hxtlt habs hW' hWt (by + rw [hw1eq, ← htgt] + push_cast + omega) + linarith [hmono, hlive] + have hlive1 : 2 ≤ int256 (mulShiftTree y x1) := by + have hmono := mulShift_antitone hy hx1 hxtlt habs hW1 hWt (by + rw [← htgt] + push_cast + omega) + linarith [hmono, hlive] + -- the scale point stays outside the range + have hx10 : int256 x1 ≠ 0 := by + rcases hsign with h | h + · push_cast at h + omega + · omega + have hx'0 : int256 x' ≠ 0 := by + rw [hw1eq] + rcases hsign with h | h + · push_cast at h + omega + · omega + have hstep : int256 (mulMagnitudeTree y x1) ≤ int256 (mulMagnitudeTree y x') := + mulMagnitude_step hy hy0 hx1 hw1lt habs hW1 hW' hx10 hx'0 hlive1 hlive' hw1eq + -- the remaining `m` steps from `x'` + have hsum : int256 x' + (m : Int) = int256 x1 + (m + 1 : Nat) := by + rw [hw1eq] + push_cast + ring + have hrec := ih x' hw1lt (by omega) (by rw [hsum]; exact hbnd) + (by + rcases hsign with h | h + · left + rw [hsum] + push_cast at h ⊢ + omega + · right + rw [hw1eq] + omega) + (by rw [hsum]; exact hlive) + (by rw [hsum]; exact htgt) + rw [hsum] at hrec + calc int256 (mulMagnitudeTree y x1) ≤ int256 (mulMagnitudeTree y x') := hstep + _ ≤ int256 (mulMagnitudeTree y (uint256OfInt (int256 x1 + (m + 1 : Nat)))) := hrec + +/-- **Region monotonicity of the live magnitude**: for live exponents `x1 ≤ x2` on a common sign +side, the kernel magnitude is nondecreasing. -/ +theorem mulMagnitude_region_mono {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (habs : absTree y ≤ scaleQ67) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hle : int256 x1 ≤ int256 x2) + (hsign : int256 x2 < 0 ∨ 0 < int256 x1) + (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) : + int256 (mulMagnitudeTree y x1) ≤ int256 (mulMagnitudeTree y x2) := by + set n := (int256 x2 - int256 x1).toNat with hn + have hnval : (n : Int) = int256 x2 - int256 x1 := by + rw [hn] + exact Int.toNat_of_nonneg (by omega) + have hx2eq : int256 x1 + (n : Int) = int256 x2 := by rw [hnval]; ring + have hcanon : uint256OfInt (int256 x1 + (n : Int)) = x2 := by + rw [hx2eq] + exact uint256OfInt_int256 hx2 + have h := mulMagnitude_mono_steps hy hy0 habs n x1 hx1 hW1.1 + (by rw [hx2eq]; exact hW2.2) + (by + rcases hsign with h | h + · left + rw [hx2eq] + exact h + · right + exact h) + (by rw [hcanon]; exact hlive2) + (by rw [hcanon, hx2eq]) + rw [hcanon] at h + exact h + +/-! ## The scale-point comparisons -/ + +/-- The octave index at `x = 1` is zero. -/ +private theorem kTree_one : int256 (kTree 1) = 0 := by + have hW : WideRegion 1 := by + constructor + · rw [int256_mulExpRayZeroMax, int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + · rw [int256_mulExpRayHi, int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + obtain ⟨hlo, hhi⟩ := kTree_sandwich_wide (by norm_num) hW + rw [int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] at hlo hhi + have hcinv : (0x724d54edbacbebbb95c52a0f60 : Int) = 9055943544797870567083544809312 := by + norm_num + rw [hcinv] at hlo hhi + have p199 : (2 : Int) ^ 191 = + 3138550867693340381917894711603833208051177722232017256448 := by norm_num + have p200 : (2 : Int) ^ 192 = + 6277101735386680763835789423207666416102355444464034512896 := by norm_num + rw [p199, p200] at hlo hhi + set k := int256 (kTree 1) with hk + clear_value k + omega + +/-- The magnitude at the scale point is the multiplier's magnitude. -/ +private theorem int256_mulMagnitude_zero {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (habs : absTree y ≤ scaleQ67) : + int256 (mulMagnitudeTree y 0) = (absTree y : Int) := by + have hpos : 0 < absTree y := absTree_pos hy hy0 + rw [mulMagnitudeTree_scale_point hy hpos habs] + exact int256_of_lt (lt_of_le_of_lt habs (by unfold scaleQ67; norm_num)) + +/-- **The analytic pin step.** At `x = 1` the live magnitude is at least the multiplier's +magnitude: one exponent unit is worth `scale/10²⁷ ≥ 2⁹⁸` quotient units, far above the deficit +envelope, so the decremented quotient still clears `scale` and its closing shift clears +`abs(y)`. -/ +theorem mulMagnitude_pin_step {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (habs : absTree y ≤ scaleQ67) + (hlive1 : 2 ≤ int256 (mulShiftTree y 1)) : + (absTree y : Int) ≤ int256 (mulMagnitudeTree y 1) := by + have hx1 : (1 : Nat) < 2 ^ 256 := by norm_num + have hW : WideRegion 1 := by + constructor + · rw [int256_mulExpRayZeroMax, int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + · rw [int256_mulExpRayHi, int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + have hi1 : int256 (1 : Nat) = 1 := by + rw [int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + have hpos : 1 ≤ absTree y := absTree_pos hy hy0 + have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs + obtain ⟨hs256, hscale_eq, hshi⟩ := mulScaleTree_spec hy habs + have hunder := r0Scaled_real_under_within (scale := mulScaleTree y) hslo hshi hx1 hW + have hr0eqM : r0ScaledTree (mulScaleTree y) 1 = r0MulTree y 1 := (r0MulTree_eq_scaled y 1).symm + rw [hr0eqM] at hunder + have hm := mulMagnitudeTree_live (y := y) hx1 (by rw [hi1]; norm_num) (by + rw [int256_mulExpRayZeroMax, hi1] + norm_num) + obtain ⟨hargeq, hargnn, harghi⟩ := mulShiftArg_facts hy hy0 hx1 habs hW + obtain ⟨hshlo, hshlt, hsheq⟩ := mulShift_word_facts hy hx1 habs hW hlive1 + have htr := mulShiftTree_transport hy hx1 habs hW + have hshS : mulShiftTree y 1 = scaleShiftTree (absTree y) := by + have h1 : (mulShiftTree y 1 : Int) = (scaleShiftTree (absTree y) : Int) := by + rw [hsheq, htr, kTree_one] + ring + exact_mod_cast h1 + rw [hm, hshS] + -- every deep word becomes an opaque name before the arithmetic + set r0w := r0MulTree y 1 with hr0w_def + have hr0wlt : r0w < 2 ^ 256 := by rw [hr0w_def]; exact r0MulTree_lt y 1 + clear_value r0w + set sc := mulScaleTree y with hsc_def + clear_value sc + set ay := absTree y with hay_def + set S := scaleShiftTree ay with hS_def + clear_value S + clear_value ay + -- the quotient clears the scale by at least two units + have hred : reducedArg 1 = 1 / (10 ^ 27 : Real) := by + unfold reducedArg + rw [hi1, kTree_one] + push_cast + ring + have hexp1 : (1 : Real) + 1 / (10 ^ 27 : Real) ≤ Real.exp (reducedArg 1) := by + rw [hred] + have := Real.add_one_le_exp (1 / (10 ^ 27 : Real)) + linarith [this] + have hscaleR : (2:Real) ^ 125 ≤ ((sc : Nat) : Real) := by exact_mod_cast hslo + have hscale_nn : (0:Real) ≤ ((sc : Nat) : Real) := Nat.cast_nonneg sc + have hgain : ((sc : Nat) : Real) + 5 ≤ ((sc : Nat) : Real) * Real.exp (reducedArg 1) := by + have h1 : ((sc : Nat) : Real) * ((1 : Real) + 1 / (10 ^ 27 : Real)) ≤ + ((sc : Nat) : Real) * Real.exp (reducedArg 1) := + mul_le_mul_of_nonneg_left hexp1 hscale_nn + have h2 : (5:Real) ≤ ((sc : Nat) : Real) * (1 / (10 ^ 27 : Real)) := by + have h3 : (5:Real) ≤ ((2:Real) ^ 125) * (1 / (10 ^ 27 : Real)) := by norm_num + have h4 : ((2:Real) ^ 125) * (1 / (10 ^ 27 : Real)) ≤ + ((sc : Nat) : Real) * (1 / (10 ^ 27 : Real)) := + mul_le_mul_of_nonneg_right hscaleR (by positivity) + linarith [h3, h4] + have hdistrib : ((sc : Nat) : Real) * ((1 : Real) + 1 / (10 ^ 27 : Real)) = + ((sc : Nat) : Real) + ((sc : Nat) : Real) * (1 / (10 ^ 27 : Real)) := by ring + linarith [h1, h2, hdistrib] + have hq2 : ((sc : Nat) : Real) + 2 ≤ (int256 r0w : Real) := by + linarith [hunder, hgain] + have hq2I : ((sc : Nat) : Int) + 2 ≤ int256 r0w := by + have h : (((sc : Nat) : Int) + 2 : Real) ≤ ((int256 r0w : Int) : Real) := by + push_cast + linarith [hq2] + exact_mod_cast h + -- word-level: the shifted decremented quotient clears the magnitude + set arg := evmSub r0w marginWord with hargdef + have halt : arg < 2 ^ 256 := by rw [hargdef]; exact evmSub_lt _ _ + clear_value arg + obtain ⟨hae, halt255⟩ := int256_eq_of_nonneg halt (by rw [hargeq]; exact hargnn) + have hargN : sc + 1 ≤ arg := by + have h1 : ((sc + 1 : Nat) : Int) ≤ ((arg : Nat) : Int) := by + rw [← hae, hargeq] + push_cast + linarith [hq2I] + exact_mod_cast h1 + rw [evmShr_eq_div hs256 halt] + have hdiv : ay ≤ arg / 2 ^ S := by + rw [Nat.le_div_iff_mul_le (Nat.two_pow_pos _)] + calc ay * 2 ^ S = sc := hscale_eq.symm + _ ≤ arg := le_trans (Nat.le_add_right _ 1) hargN + have hqlt : arg / 2 ^ S < 2 ^ 255 := by + have h1 : arg / 2 ^ S ≤ arg := Nat.div_le_self _ _ + exact lt_of_le_of_lt h1 halt255 + rw [int256_of_lt hqlt] + exact_mod_cast hdiv + +/-- A negative live exponent's magnitude never exceeds the multiplier's magnitude: its real +target is already below it. -/ +theorem mulMagnitude_le_abs_of_neg {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hW : WideRegion x) (hxneg : int256 x < 0) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + int256 (mulMagnitudeTree y x) ≤ (absTree y : Int) := by + obtain ⟨hm0, _, hmle, _⟩ := mulMagnitude_bracket_live hy hx hy0 habs (by omega) hW hlive + have hAlt : mulExpRayMagnitudeTarget (int256 y) (int256 x) < ((absTree y : Nat) : Real) := by + unfold mulExpRayMagnitudeTarget + have hay : ((int256 y).natAbs : Real) = ((absTree y : Nat) : Real) := by + rw [absTree_eq_natAbs hy] + rw [hay] + have hexplt : Real.exp ((int256 x : Real) / ((RAY : Nat) : Real)) < 1 := by + apply Real.exp_lt_one_iff.mpr + apply div_neg_of_neg_of_pos + · exact_mod_cast hxneg + · have : ((RAY : Nat) : Real) = (10 ^ 27 : Real) := by unfold RAY; push_cast; norm_num + rw [this] + positivity + have hpos : (0:Real) < ((absTree y : Nat) : Real) := by + have h1 : 1 ≤ absTree y := absTree_pos hy hy0 + exact_mod_cast h1 + have h5 := mul_lt_mul_of_pos_left hexplt hpos + rw [mul_one] at h5 + exact h5 + have h1 : (int256 (mulMagnitudeTree y x) : Real) < ((absTree y : Nat) : Real) := + lt_of_le_of_lt hmle hAlt + have h2 : int256 (mulMagnitudeTree y x) < ((absTree y : Nat) : Int) := by exact_mod_cast h1 + exact le_of_lt h2 + +/-! ## Sign transports -/ + +private theorem int256_zero_word' : int256 (0 : Nat) = 0 := by unfold int256; norm_num + +private theorem int256_pos_eq_abs {y : Nat} (hneg : y < 2 ^ 255) : + int256 y = (absTree y : Int) := by + rw [absTree_nonneg hneg, int256_of_lt hneg] + +private theorem int256_neg_eq_abs {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : + int256 y = -(absTree y : Int) := by + rw [absTree_neg hlo hy] + unfold int256 + rw [if_neg (by omega)] + omega + +private theorem int256_y_neg {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : + int256 y < 0 := by + unfold int256 + rw [if_neg (by omega)] + have h1 : (y : Int) < 2 ^ 256 := by exact_mod_cast hy + omega + +private theorem int256_y_nonneg {y : Nat} (hneg : y < 2 ^ 255) : + ¬ (int256 y < 0) := by + rw [int256_of_lt hneg] + exact not_lt.mpr (Int.natCast_nonneg y) + +/-- The signed tree result under a positive multiplier is the magnitude. -/ +private theorem int256_tree_pos {y x : Nat} (hpos : 0 < y) (hneg : y < 2 ^ 255) : + int256 (mulExpTree y x) = int256 (mulMagnitudeTree y x) := by + rw [mulExpTree_pos hpos hneg] + +/-- The signed tree result under a negative multiplier is the negated magnitude. -/ +private theorem int256_tree_neg {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) + (hm255 : mulMagnitudeTree y x < 2 ^ 255) : + int256 (mulExpTree y x) = -(int256 (mulMagnitudeTree y x)) := by + rcases Nat.eq_zero_or_pos (mulMagnitudeTree y x) with hmz | hmpos + · have hzero : mulExpTree y x = 0 := by + unfold mulExpTree + rw [hmz] + unfold evmMul + rw [u256_of_lt_pow256 (by norm_num : (0:Nat) < 2 ^ 256)] + simp [u256, WORD_MOD] + rw [hzero, hmz, int256_zero_word'] + norm_num + · rw [mulExpTree_negative hlo hy hmpos] + have hres : int256 (2 ^ 256 - mulMagnitudeTree y x) = -(int256 (mulMagnitudeTree y x)) := by + unfold int256 + rw [if_neg (by omega), if_pos hm255] + omega + exact hres + +/-- The live magnitude word stays below `2^255`. -/ +private theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx0 : int256 x ≠ 0) (hW : WideRegion x) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + mulMagnitudeTree y x < 2 ^ 255 := by + obtain ⟨hm0, hmlt, _, _⟩ := mulMagnitude_bracket_live hy hx hy0 habs hx0 hW hlive + obtain ⟨hmi, _⟩ := int256_eq_of_nonneg (mulMagnitudeTree_lt y x) hm0 + have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 128 := by rw [← hmi]; exact hmlt + have h' : mulMagnitudeTree y x < 2 ^ 128 := by exact_mod_cast h + have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + omega + +/-! ## Magnitude monotonicity over the live region -/ + +/-- A positive live exponent's magnitude is at least the multiplier's magnitude (through the +analytic pin step at `x = 1`). -/ +theorem mulMagnitude_ge_abs_of_pos {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hW : WideRegion x) (hxpos : 0 < int256 x) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + (absTree y : Int) ≤ int256 (mulMagnitudeTree y x) := by + have hW1 : WideRegion 1 := by + constructor + · rw [int256_mulExpRayZeroMax, int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + · rw [int256_mulExpRayHi, int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + have hi1 : int256 (1 : Nat) = 1 := by + rw [int256_of_lt (by norm_num : (1:Nat) < 2 ^ 255)] + norm_num + have h1le : int256 (1 : Nat) ≤ int256 x := by + rw [hi1] + omega + have hsh1 : 2 ≤ int256 (mulShiftTree y 1) := by + have h := mulShift_antitone hy (by norm_num) hx habs hW1 hW h1le + linarith [h, hlive] + have hpin := mulMagnitude_pin_step hy hy0 habs hsh1 + have hmono := mulMagnitude_region_mono hy hy0 habs (by norm_num) hx hW1 hW h1le + (Or.inr (by rw [hi1]; norm_num)) hlive + linarith [hpin, hmono] + +/-- **Magnitude monotonicity over the live region**, both sign sides, through the scale point. -/ +theorem mulMagnitude_mono_pair {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (hx10 : int256 x1 ≠ 0) (hx20 : int256 x2 ≠ 0) + (hlive1 : 2 ≤ int256 (mulShiftTree y x1)) (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) + (hle : int256 x1 ≤ int256 x2) : + int256 (mulMagnitudeTree y x1) ≤ int256 (mulMagnitudeTree y x2) := by + rcases lt_or_gt_of_ne hx20 with hx2neg | hx2pos + · -- both negative: one sign side + exact mulMagnitude_region_mono hy hy0 habs hx1 hx2 hW1 hW2 hle (Or.inl hx2neg) hlive2 + · rcases lt_or_gt_of_ne hx10 with hx1neg | hx1pos + · -- crossing the scale point: below it the magnitude is under `abs(y)`, above it at least + calc int256 (mulMagnitudeTree y x1) + ≤ (absTree y : Int) := mulMagnitude_le_abs_of_neg hy hy0 hx1 habs hW1 hx1neg hlive1 + _ ≤ int256 (mulMagnitudeTree y x2) := + mulMagnitude_ge_abs_of_pos hy hy0 hx2 habs hW2 hx2pos hlive2 + · -- both positive: one sign side + exact mulMagnitude_region_mono hy hy0 habs hx1 hx2 hW1 hW2 hle (Or.inr hx1pos) hlive2 + +/-! ## The public runtime statement -/ + +/-- **Monotonicity in the exponent on the value domain.** For a fixed multiplier and accepted +exponents `x1 ≤ x2`, the signed results are ordered along the multiplier's sign. -/ +theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} + (h1 : MulExpRayValueDomain y x1) (h2 : MulExpRayValueDomain y x2) + (hle : int256 x1 ≤ int256 x2) : + MulExpRayRunMonotone y x1 x2 := by + obtain ⟨⟨hy, hx1w⟩, habs1, hxhi1, hcase1⟩ := h1 + obtain ⟨⟨_, hx2w⟩, habs2, hxhi2, hcase2⟩ := h2 + have hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1) := + run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx1w⟩, habs1, hxhi1, hcase1⟩ + have hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2) := + run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx2w⟩, habs2, hxhi2, hcase2⟩ + refine ⟨mulExpTree y x1, mulExpTree y x2, hrun1, hrun2, hle, ?_⟩ + rcases Nat.eq_zero_or_pos y with hy0 | hypos + · subst hy0 + rw [mulExpTree_zero, mulExpTree_zero, int256_zero_word'] + split <;> exact le_refl 0 + have hy0 : y ≠ 0 := Nat.pos_iff_ne_zero.mp hypos + -- the signed magnitude of each accepted result + have habs := habs1 + -- classify each exponent: clamp, scale point, or live + have hclass : ∀ x : Nat, x < 2 ^ 256 → int256 x < int256 mulExpRayHi → + (int256 x = 0 ∨ int256 x ≤ int256 mulExpRayZeroMax ∨ 2 ≤ int256 (mulShiftTree y x)) → + int256 x ≤ int256 mulExpRayZeroMax ∨ x = 0 ∨ + (int256 mulExpRayZeroMax < int256 x ∧ int256 x ≠ 0 ∧ + 2 ≤ int256 (mulShiftTree y x)) := by + intro x hxw hxhi hcase + by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax + · exact Or.inl hcl + by_cases hx0 : int256 x = 0 + · exact Or.inr (Or.inl ((int256_zero_iff_of_canonical hxw).1 hx0)) + · rcases hcase with h | h | h + · exact absurd h hx0 + · exact absurd h hcl + · exact Or.inr (Or.inr ⟨by omega, hx0, h⟩) + -- the two sign branches share the magnitude comparisons + rcases hclass x1 hx1w hxhi1 hcase1 with hc1 | hp1 | ⟨hzm1, hx10, hlv1⟩ <;> + rcases hclass x2 hx2w hxhi2 hcase2 with hc2 | hp2 | ⟨hzm2, hx20, hlv2⟩ + -- (clamp, clamp) + · rw [mulExpTree_clamped hx1w hc1, mulExpTree_clamped hx2w hc2] + split <;> exact le_refl _ + -- (clamp, pin) + · subst hp2 + rw [mulExpTree_clamped hx1w hc1, mulExpTree_scale_point hy habs, int256_zero_word'] + split_ifs with hneg + · exact le_of_lt hneg + · exact not_lt.mp hneg + -- (clamp, live) + · rw [mulExpTree_clamped hx1w hc1, int256_zero_word'] + have hW2 : WideRegion x2 := ⟨hzm2, hxhi2⟩ + obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy hx2w hy0 habs hx20 hW2 hlv2 + have hm255 := mag_word_small hy hy0 hx2w habs hx20 hW2 hlv2 + by_cases hneg : y < 2 ^ 255 + · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg] + exact hm0 + · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255] + linarith [hm0] + -- (pin, clamp): impossible, the scale point is above the clamp + · exfalso + subst hp1 + rw [int256_zero_word'] at hle + rw [int256_mulExpRayZeroMax] at hc2 + omega + -- (pin, pin) + · subst hp1 + subst hp2 + split <;> exact le_refl _ + -- (pin, live): the exponent is positive, the magnitude clears `abs(y)` + · subst hp1 + have hW2 : WideRegion x2 := ⟨hzm2, hxhi2⟩ + have hx2pos : 0 < int256 x2 := by + rw [int256_zero_word'] at hle + omega + have hge := mulMagnitude_ge_abs_of_pos hy hy0 hx2w habs hW2 hx2pos hlv2 + have hm255 := mag_word_small hy hy0 hx2w habs hx20 hW2 hlv2 + rw [mulExpTree_scale_point hy habs] + by_cases hneg : y < 2 ^ 255 + · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg, int256_pos_eq_abs hneg] + exact hge + · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255, + int256_neg_eq_abs (by omega) hy] + linarith [hge] + -- (live, clamp): impossible + · exfalso + rw [int256_mulExpRayZeroMax] at hzm1 hc2 + omega + -- (live, pin): the exponent is negative, the magnitude stays under `abs(y)` + · subst hp2 + have hW1 : WideRegion x1 := ⟨hzm1, hxhi1⟩ + have hx1neg : int256 x1 < 0 := by + rw [int256_zero_word'] at hle + omega + have hlt := mulMagnitude_le_abs_of_neg hy hy0 hx1w habs hW1 hx1neg hlv1 + have hm255 := mag_word_small hy hy0 hx1w habs hx10 hW1 hlv1 + rw [mulExpTree_scale_point hy habs] + by_cases hneg : y < 2 ^ 255 + · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg, int256_pos_eq_abs hneg] + exact hlt + · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255, + int256_neg_eq_abs (by omega) hy] + linarith [hlt] + -- (live, live) + · have hW1 : WideRegion x1 := ⟨hzm1, hxhi1⟩ + have hW2 : WideRegion x2 := ⟨hzm2, hxhi2⟩ + have hmono := mulMagnitude_mono_pair hy hy0 hx1w hx2w habs hW1 hW2 hx10 hx20 hlv1 hlv2 hle + have hm255a := mag_word_small hy hy0 hx1w habs hx10 hW1 hlv1 + have hm255b := mag_word_small hy hy0 hx2w habs hx20 hW2 hlv2 + by_cases hneg : y < 2 ^ 255 + · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg, + int256_tree_pos hypos hneg] + exact hmono + · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255a, + int256_tree_neg (by omega) hy hm255b] + linarith [hmono] + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 61ea119ef..ef137801b 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -8,6 +8,7 @@ import ExpProof.Floor.R0Bound import ExpProof.Floor.RoundTrip import ExpProof.Mul.Shell import ExpProof.Mul.Accum +import ExpProof.Mul.XMono /-! # `expRayToWad` and `mulExpRay` — compiled-runtime proof signpost @@ -106,17 +107,20 @@ arguments. Discharged today, axiom-clean: | Value path returns the compiled tree | `run_mul_exp_ray_evm_eq_tree` | | Rejected inputs revert | `run_mul_exp_ray_evm_revert` | | Signed bracket `0 ≤ m ≤ A < m + 2` on the domain | `mulExpRay_run_bracket` | +| Sign-directed monotonicity in the exponent | `run_mul_exp_ray_evm_mono_x` | | Result magnitude is `⌊A⌋` or `⌊A⌋ − 1` | `mulExpRay_run_floor_membership` | | `A < 1` pins the result to zero | `mulExpRay_run_pins_zero` | | Zero multiplier returns zero (and its bracket) | `run_mul_exp_ray_evm_zero_of_guard` | | Scale point `mulExpRay(y, 0) = y` (and its bracket) | `run_mul_exp_ray_evm_scale_point` | | Zero clamp at deep-negative `x` (and its bracket) | `run_mul_exp_ray_evm_clamped` | -The bracket is proven on the whole value domain: the scale-symbolic per-point certificates -(`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) instantiate at the dynamic scale -`abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`, and the accumulator fold (`Mul.Accum`) closes the live region. -Still open, visible below as explicit hypotheses of the facade lemmas: the runtime monotonicity -statements. +The bracket and the monotonicity in the exponent are proven on the whole value domain: the +scale-symbolic per-point certificates (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) +instantiate at the dynamic scale `abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`, the accumulator fold +(`Mul.Accum`) closes the live-region bracket, and the unit-step induction with the scaled seam +doubling (`Mul.XMono`) closes the sign-directed exponent monotonicity. Still open, visible below +as explicit hypotheses of the facade lemmas: the runtime monotonicity statements in the +multiplier and the joint form. -/ /-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ @@ -129,6 +133,12 @@ magnitude `m` satisfies `0 ≤ m ≤ A ∧ A < m + 2` for `A = abs(y)·exp(x/10 example {y x : Nat} (h : MulExpRayValueDomain y x) : MulExpRayRunBracket y x := mulExpRay_run_bracket h +/-- **Sign-directed monotonicity in the exponent on the value domain.** -/ +example {y x1 x2 : Nat} (h1 : MulExpRayValueDomain y x1) (h2 : MulExpRayValueDomain y x2) + (hle : FormalYul.Preservation.int256 x1 ≤ FormalYul.Preservation.int256 x2) : + MulExpRayRunMonotone y x1 x2 := + run_mul_exp_ray_evm_mono_x h1 h2 hle + /-- **Floor membership.** Every accepted input's result magnitude is `⌊A⌋` or `⌊A⌋ − 1`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ @@ -300,6 +310,10 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_bracket +/-- info: 'ExpYul.run_mul_exp_ray_evm_mono_x' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_mono_x + /-- info: 'ExpYul.mulExpRay_run_floor_membership' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms mulExpRay_run_floor_membership From 5c9c95c659e2ebbef88fc2367cb0507893d7366b Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 14:54:05 +0200 Subject: [PATCH 071/107] Prove mulExpRay monotone in the multiplier on the value domain Mul/YMono.lean closes the multiplier monotonicity in pure word arithmetic. Scale maximality alone pins the headroom behavior: the headroom shift is antitone in the magnitude and drops at most one bit per unit step. When it holds, the scale grows by one headroom unit and the same-shift floor is monotone; when it drops, the doubled new scale exceeds the old by exactly one headroom unit, so the quotient at most doubles one unit short (2*num > den, from the even accumulator dominating three tod magnitudes, pays the halving floor's loss), and the decremented shift argument lands at most one over the doubled new one - an odd excess that cannot cross the even closing modulus (seam_close_odd, via Nat.succ_div_of_not_dvd). The magnitude induction sweeps accepted magnitudes, which the antitone headroom keeps downward closed; sign composition and the scale-point/clamp shells give the signed public statement, gated in the signpost. The XMono word transports the assembly shares are now public. Co-Authored-By: Claude Fable 5 --- formal/exp/ExpProof/ExpProof/Mul/XMono.lean | 20 +- formal/exp/ExpProof/ExpProof/Mul/YMono.lean | 665 ++++++++++++++++++++ formal/exp/ExpProof/ExpProof/Theorems.lean | 20 +- 3 files changed, 691 insertions(+), 14 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Mul/YMono.lean diff --git a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean index 97faf935a..bc0dd261f 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean @@ -59,7 +59,7 @@ theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) linarith [hkmono] /-- The decremented quotient word: transport and range at the dynamic scale. -/ -private theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) +theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) : int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 ∧ 0 ≤ int256 (r0MulTree y x) - 1 ∧ int256 (r0MulTree y x) - 1 < 2 ^ 130 := by @@ -354,7 +354,7 @@ private theorem kTree_one : int256 (kTree 1) = 0 := by omega /-- The magnitude at the scale point is the multiplier's magnitude. -/ -private theorem int256_mulMagnitude_zero {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) +theorem int256_mulMagnitude_zero {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) (habs : absTree y ≤ scaleQ67) : int256 (mulMagnitudeTree y 0) = (absTree y : Int) := by have hpos : 0 < absTree y := absTree_pos hy hy0 @@ -494,38 +494,38 @@ theorem mulMagnitude_le_abs_of_neg {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0 /-! ## Sign transports -/ -private theorem int256_zero_word' : int256 (0 : Nat) = 0 := by unfold int256; norm_num +theorem int256_zero_word' : int256 (0 : Nat) = 0 := by unfold int256; norm_num -private theorem int256_pos_eq_abs {y : Nat} (hneg : y < 2 ^ 255) : +theorem int256_pos_eq_abs {y : Nat} (hneg : y < 2 ^ 255) : int256 y = (absTree y : Int) := by rw [absTree_nonneg hneg, int256_of_lt hneg] -private theorem int256_neg_eq_abs {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : +theorem int256_neg_eq_abs {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : int256 y = -(absTree y : Int) := by rw [absTree_neg hlo hy] unfold int256 rw [if_neg (by omega)] omega -private theorem int256_y_neg {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : +theorem int256_y_neg {y : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) : int256 y < 0 := by unfold int256 rw [if_neg (by omega)] have h1 : (y : Int) < 2 ^ 256 := by exact_mod_cast hy omega -private theorem int256_y_nonneg {y : Nat} (hneg : y < 2 ^ 255) : +theorem int256_y_nonneg {y : Nat} (hneg : y < 2 ^ 255) : ¬ (int256 y < 0) := by rw [int256_of_lt hneg] exact not_lt.mpr (Int.natCast_nonneg y) /-- The signed tree result under a positive multiplier is the magnitude. -/ -private theorem int256_tree_pos {y x : Nat} (hpos : 0 < y) (hneg : y < 2 ^ 255) : +theorem int256_tree_pos {y x : Nat} (hpos : 0 < y) (hneg : y < 2 ^ 255) : int256 (mulExpTree y x) = int256 (mulMagnitudeTree y x) := by rw [mulExpTree_pos hpos hneg] /-- The signed tree result under a negative multiplier is the negated magnitude. -/ -private theorem int256_tree_neg {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) +theorem int256_tree_neg {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) (hm255 : mulMagnitudeTree y x < 2 ^ 255) : int256 (mulExpTree y x) = -(int256 (mulMagnitudeTree y x)) := by rcases Nat.eq_zero_or_pos (mulMagnitudeTree y x) with hmz | hmpos @@ -545,7 +545,7 @@ private theorem int256_tree_neg {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ exact hres /-- The live magnitude word stays below `2^255`. -/ -private theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) +theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : diff --git a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean new file mode 100644 index 000000000..ca67e17f4 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean @@ -0,0 +1,665 @@ +import ExpProof.Mul.XMono + +/-! +# `mulExpRay` monotonicity in the multiplier + +At a fixed exponent the kernel magnitude is nondecreasing in the multiplier's magnitude, by a +unit-step induction in pure word arithmetic. A unit step in the magnitude either keeps the +headroom shift — the scale grows by one headroom unit and the same-shift floor is monotone — or +drops it by exactly one bit, where the doubled new scale exceeds the old one by exactly `2^S` +(`2·(a+1)·2^(S−1) = a·2^S + 2^S`), so the quotient at most doubles one unit short +(`2·num > den` absorbs the floor loss), and the decremented shift argument satisfies +`arg1 ≤ 2·arg2 + 1`; since the old closing modulus is even and `2·arg2 + 1` is the largest value +sharing `arg2`'s floor at the dropped shift, the shifted floors stay ordered +(`seam_close_odd`). The scale point orders trivially and the clamp is constant; sign composition +yields the signed public statement on the whole value domain. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open Common.Word +open ExpRealSpec + +set_option maxRecDepth 100000 +set_option maxHeartbeats 1600000 + +/-! ## Magnitude words normalize through the absolute value -/ + +/-- A supported magnitude word is its own absolute value. -/ +private theorem absTree_of_small {a : Nat} (ha : a ≤ scaleQ67) : absTree a = a := + absTree_nonneg (lt_of_le_of_lt ha (by unfold scaleQ67; norm_num)) + +/-- The kernel magnitude depends on the multiplier only through its magnitude word. -/ +theorem mulMagnitude_abs_norm {y : Nat} (habs : absTree y ≤ scaleQ67) (x : Nat) : + mulMagnitudeTree y x = mulMagnitudeTree (absTree y) x := by + have h : absTree (absTree y) = absTree y := absTree_of_small habs + unfold mulMagnitudeTree mulShiftTree r0MulTree mulScaleTree + rw [h] + +/-- The closing shift depends on the multiplier only through its magnitude word. -/ +theorem mulShift_abs_norm {y : Nat} (habs : absTree y ≤ scaleQ67) (x : Nat) : + mulShiftTree y x = mulShiftTree (absTree y) x := by + have h : absTree (absTree y) = absTree y := absTree_of_small habs + unfold mulShiftTree + rw [h] + +/-! ## Headroom arithmetic from scale maximality -/ + +/-- The headroom shift is antitone in the magnitude. -/ +theorem scaleShift_antitone {a b : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleQ67) : + scaleShiftTree b ≤ scaleShiftTree a := by + have haQ : a ≤ scaleQ67 := le_trans hab hb + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) + have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleQ67; norm_num) + have haa : absTree a = a := absTree_of_small haQ + have hba : absTree b = b := absTree_of_small hb + have hmax := mulScaleTree_max (y := a) haw (by rw [haa]; exact ha) (by rw [haa]; exact haQ) + obtain ⟨_, hspec_a, _⟩ := mulScaleTree_spec (y := a) haw (by rw [haa]; exact haQ) + obtain ⟨_, hspec_b, hcap_b⟩ := mulScaleTree_spec (y := b) hbw (by rw [hba]; exact hb) + rw [hspec_a, haa] at hmax + rw [hspec_b, hba] at hcap_b + rw [haa] at hspec_a + rw [hba] at hspec_b + -- b·2^Sb ≤ Q < 2·a·2^Sa ≤ 2·b·2^Sa, so 2^Sb < 2^(Sa+1) + by_contra hcon + push_neg at hcon + have h1 : b * 2 ^ scaleShiftTree b < 2 * (a * 2 ^ scaleShiftTree a) := + lt_of_le_of_lt hcap_b hmax + have h2 : 2 * (a * 2 ^ scaleShiftTree a) ≤ 2 * (b * 2 ^ scaleShiftTree a) := by + have := Nat.mul_le_mul_right (2 ^ scaleShiftTree a) hab + omega + have h3 : b * 2 ^ scaleShiftTree b < b * 2 ^ (scaleShiftTree a + 1) := by + have h4 : 2 * (b * 2 ^ scaleShiftTree a) = b * 2 ^ (scaleShiftTree a + 1) := by + rw [pow_succ] + ring + omega + have h5 : 2 ^ scaleShiftTree b < 2 ^ (scaleShiftTree a + 1) := + lt_of_mul_lt_mul_left h3 (Nat.zero_le b) + have h6 : scaleShiftTree b < scaleShiftTree a + 1 := + (Nat.pow_lt_pow_iff_right (by norm_num)).mp h5 + omega + +/-- A unit magnitude step drops the headroom shift by at most one. -/ +theorem scaleShift_step {a : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleQ67) : + scaleShiftTree a ≤ scaleShiftTree (a + 1) + 1 := by + have haQ : a ≤ scaleQ67 := le_trans (Nat.le_succ a) ha1 + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) + have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleQ67; norm_num) + have haa : absTree a = a := absTree_of_small haQ + have ha1a : absTree (a + 1) = a + 1 := absTree_of_small ha1 + obtain ⟨_, hspec_a, hcap_a⟩ := mulScaleTree_spec (y := a) haw (by rw [haa]; exact haQ) + have hmax1 := mulScaleTree_max (y := a + 1) ha1w (by rw [ha1a]; omega) + (by rw [ha1a]; exact ha1) + obtain ⟨_, hspec_a1, _⟩ := mulScaleTree_spec (y := a + 1) ha1w (by rw [ha1a]; exact ha1) + rw [hspec_a, haa] at hcap_a + rw [hspec_a1, ha1a] at hmax1 + -- a·2^Sa ≤ Q < 2·(a+1)·2^S(a+1): if Sa ≥ S(a+1)+2, then 2a < a+1, impossible for a ≥ 1 + by_contra hcon + push_neg at hcon + have h1 : a * 2 ^ scaleShiftTree a < 2 * ((a + 1) * 2 ^ scaleShiftTree (a + 1)) := + lt_of_le_of_lt hcap_a hmax1 + have h2 : (2:Nat) ^ (scaleShiftTree (a + 1) + 2) ≤ 2 ^ scaleShiftTree a := + Nat.pow_le_pow_right (by norm_num) hcon + have h3 : a * 2 ^ (scaleShiftTree (a + 1) + 2) ≤ a * 2 ^ scaleShiftTree a := + Nat.mul_le_mul_left a h2 + have h4 : a * 2 ^ (scaleShiftTree (a + 1) + 2) = + (2 * a) * (2 * 2 ^ scaleShiftTree (a + 1)) := by + rw [pow_succ, pow_succ] + ring + have h5 : 2 * ((a + 1) * 2 ^ scaleShiftTree (a + 1)) = + (a + 1) * (2 * 2 ^ scaleShiftTree (a + 1)) := by ring + have hppos : 0 < 2 * 2 ^ scaleShiftTree (a + 1) := by positivity + have h6 : 2 * a < a + 1 := by + have h7 : (2 * a) * (2 * 2 ^ scaleShiftTree (a + 1)) < + (a + 1) * (2 * 2 ^ scaleShiftTree (a + 1)) := by omega + exact lt_of_mul_lt_mul_right h7 (Nat.zero_le _) + omega + +/-! ## Quotient comparisons at a fixed exponent -/ + +/-- `2·num > den` at any live exponent: the even accumulator dominates three `tod` magnitudes. -/ +theorem num_den_ratio {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : + (evTree x : Int) - int256 (todTree x) < + 2 * ((evTree x : Int) + int256 (todTree x)) := by + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW + obtain ⟨hev_lo, _⟩ := evTree_facts hvlt + obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound_wide hx hW + have hev : (0x1385291795942d41ba5fd317688e18710 : Int) ≤ (evTree x : Int) := by + exact_mod_cast hev_lo + have h1 : (0x1385291795942d41ba5fd317688e18710 : Int) = + 415147853590918758559635130244235626256 := by norm_num + rw [h1] at hev + have hp126 : (2:Int)^126 = 85070591730234615865843651857942052864 := by norm_num + rw [hp126] at htod_lo htod_hi + linarith [hev, htod_lo, htod_hi] + +/-- The scaled quotient is monotone in the scale at a fixed exponent. -/ +theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) : + int256 (r0ScaledTree sc1 x) ≤ int256 (r0ScaledTree sc2 x) := by + obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW + obtain ⟨hevlo, hevhi⟩ := evTree_facts hvlt + obtain ⟨_, htod_hi, _, _⟩ := todTree_bound_wide hx hW + set num := evmAdd (evTree x) (todTree x) with hnumdef + set den := evmSub (evTree x) (todTree x) with hdendef + have hnumw : num < 2 ^ 256 := evmAdd_lt _ _ + have hdenw : den < 2 ^ 256 := evmSub_lt _ _ + obtain ⟨hnumeq, hnum255⟩ := int256_eq_of_nonneg hnumw (by rw [hadd]; exact le_of_lt hnum_pos) + obtain ⟨hdeneq, hden255⟩ := int256_eq_of_nonneg hdenw (by rw [hsub]; exact le_of_lt hden_pos) + have hevhiI : (evTree x : Int) < 3 * 2 ^ 127 := by exact_mod_cast hevhi + have hnumlt : int256 num < 2 ^ 129 := by + rw [hadd] + have hp126 : (2:Int)^126 = 85070591730234615865843651857942052864 := by norm_num + rw [hp126] at htod_hi + have hp : (3:Int) * 2 ^ 127 + 85070591730234615865843651857942052864 < 2 ^ 129 := by norm_num + linarith [hevhiI, htod_hi] + have hnumnat : num < 2 ^ 129 := by + have hh : ((num : Nat) : Int) < 2 ^ 129 := by rw [hnumeq] at hnumlt; exact hnumlt + exact_mod_cast hh + have hdennat : 0 < den := by + have hh : (0:Int) < ((den : Nat) : Int) := by rw [← hdeneq, hsub]; exact hden_pos + exact_mod_cast hh + have hden126 : 2 ^ 126 ≤ den := by + have hev : (0x1385291795942d41ba5fd317688e18710 : Int) ≤ (evTree x : Int) := by + exact_mod_cast hevlo + have h : (2 ^ 126 : Int) ≤ ((den : Nat) : Int) := by + rw [← hdeneq, hsub] + have h1 : (0x1385291795942d41ba5fd317688e18710 : Int) = + 415147853590918758559635130244235626256 := by norm_num + rw [h1] at hev + have hp126 : (2:Int)^126 = 85070591730234615865843651857942052864 := by norm_num + rw [hp126] at htod_hi + rw [hp126] + linarith [hev, htod_hi] + exact_mod_cast h + have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt (le_trans h12 hshi2) (by unfold scaleQ67; norm_num) + have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleQ67; norm_num) + have hfit1 : sc1 * num < 2 ^ 256 := by + have h1 : sc1 * num ≤ scaleQ67 * 2 ^ 129 := + Nat.mul_le_mul (le_trans h12 hshi2) (le_of_lt hnumnat) + have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + omega + have hfit2 : sc2 * num < 2 ^ 256 := by + have h1 : sc2 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) + have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + omega + have hq1 : r0ScaledTree sc1 x = sc1 * num / den := by + show evmDiv (evmMul sc1 num) den = _ + rw [evmMul_eq_nat hsw1 hnumw hfit1, evmDiv_eq hfit1 hdenw (Nat.pos_iff_ne_zero.mp hdennat)] + have hq2 : r0ScaledTree sc2 x = sc2 * num / den := by + show evmDiv (evmMul sc2 num) den = _ + rw [evmMul_eq_nat hsw2 hnumw hfit2, evmDiv_eq hfit2 hdenw (Nat.pos_iff_ne_zero.mp hdennat)] + clear_value num den + have hqle : sc1 * num / den ≤ sc2 * num / den := + Nat.div_le_div_right (Nat.mul_le_mul_right num h12) + have hsmall : ∀ sc : Nat, sc * num < 2 ^ 256 → sc * num / den < 2 ^ 255 := by + intro sc hfit + have h1 : sc * num / den ≤ sc * num / 2 ^ 126 := + Nat.div_le_div_left hden126 (Nat.two_pow_pos _) + have h2 : sc * num / 2 ^ 126 < 2 ^ 130 := by + rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] + calc sc * num < 2 ^ 256 := hfit + _ = 2 ^ 130 * 2 ^ 126 := by norm_num + have h3 : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num + omega + rw [hq1, hq2, int256_of_lt (hsmall sc1 hfit1), int256_of_lt (hsmall sc2 hfit2)] + exact_mod_cast hqle + +/-- The scaled quotient at most doubles when the doubled scale gains exactly one headroom unit: +`2·sc2 = sc1 + 2^S` with `S ≥ 1` gives `r0(sc1) ≤ 2·r0(sc2)` (`2·num > den` pays the floor +loss). -/ +theorem r0Scaled_double_scale {sc1 sc2 S x : Nat} (hS : 1 ≤ S) + (hid : 2 * sc2 = sc1 + 2 ^ S) (hshi1 : sc1 ≤ scaleQ67) (hshi2 : sc2 ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) : + int256 (r0ScaledTree sc1 x) ≤ 2 * int256 (r0ScaledTree sc2 x) := by + obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW + obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW + obtain ⟨hevlo, hevhi⟩ := evTree_facts hvlt + obtain ⟨_, htod_hi, _, _⟩ := todTree_bound_wide hx hW + have hratio := num_den_ratio hx hW + set num := evmAdd (evTree x) (todTree x) with hnumdef + set den := evmSub (evTree x) (todTree x) with hdendef + have hnumw : num < 2 ^ 256 := evmAdd_lt _ _ + have hdenw : den < 2 ^ 256 := evmSub_lt _ _ + obtain ⟨hnumeq, hnum255⟩ := int256_eq_of_nonneg hnumw (by rw [hadd]; exact le_of_lt hnum_pos) + obtain ⟨hdeneq, hden255⟩ := int256_eq_of_nonneg hdenw (by rw [hsub]; exact le_of_lt hden_pos) + have hevhiI : (evTree x : Int) < 3 * 2 ^ 127 := by exact_mod_cast hevhi + have hnumlt : int256 num < 2 ^ 129 := by + rw [hadd] + have hp126 : (2:Int)^126 = 85070591730234615865843651857942052864 := by norm_num + rw [hp126] at htod_hi + have hp : (3:Int) * 2 ^ 127 + 85070591730234615865843651857942052864 < 2 ^ 129 := by norm_num + linarith [hevhiI, htod_hi] + have hnumnat : num < 2 ^ 129 := by + have hh : ((num : Nat) : Int) < 2 ^ 129 := by rw [hnumeq] at hnumlt; exact hnumlt + exact_mod_cast hh + have hdennat : 0 < den := by + have hh : (0:Int) < ((den : Nat) : Int) := by rw [← hdeneq, hsub]; exact hden_pos + exact_mod_cast hh + have hden126 : 2 ^ 126 ≤ den := by + have hev : (0x1385291795942d41ba5fd317688e18710 : Int) ≤ (evTree x : Int) := by + exact_mod_cast hevlo + have h : (2 ^ 126 : Int) ≤ ((den : Nat) : Int) := by + rw [← hdeneq, hsub] + have h1 : (0x1385291795942d41ba5fd317688e18710 : Int) = + 415147853590918758559635130244235626256 := by norm_num + rw [h1] at hev + have hp126 : (2:Int)^126 = 85070591730234615865843651857942052864 := by norm_num + rw [hp126] at htod_hi + rw [hp126] + linarith [hev, htod_hi] + exact_mod_cast h + -- `2·num > den` as Nats + have hratioN : den < 2 * num := by + have h1 : ((den : Nat) : Int) < 2 * ((num : Nat) : Int) := by + rw [← hdeneq, ← hnumeq, hadd, hsub] + exact hratio + exact_mod_cast h1 + have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt hshi1 (by unfold scaleQ67; norm_num) + have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleQ67; norm_num) + have hfit1 : sc1 * num < 2 ^ 256 := by + have h1 : sc1 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi1 (le_of_lt hnumnat) + have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + omega + have hfit2 : sc2 * num < 2 ^ 256 := by + have h1 : sc2 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) + have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + omega + have hq1 : r0ScaledTree sc1 x = sc1 * num / den := by + show evmDiv (evmMul sc1 num) den = _ + rw [evmMul_eq_nat hsw1 hnumw hfit1, evmDiv_eq hfit1 hdenw (Nat.pos_iff_ne_zero.mp hdennat)] + have hq2 : r0ScaledTree sc2 x = sc2 * num / den := by + show evmDiv (evmMul sc2 num) den = _ + rw [evmMul_eq_nat hsw2 hnumw hfit2, evmDiv_eq hfit2 hdenw (Nat.pos_iff_ne_zero.mp hdennat)] + clear_value num den + -- Nat inequality: sc1·num/den ≤ 2·(sc2·num/den) + have hkey : sc1 * num / den ≤ 2 * (sc2 * num / den) := by + -- 2·(sc2·num/den) ≥ (2·sc2·num)/den − 1 = ((sc1 + 2^S)·num)/den − 1 + -- ≥ sc1·num/den + (2^S·num)/den − 1 ≥ sc1·num/den (2^S·num ≥ 2·num > den) + have hsplit : 2 * sc2 * num = sc1 * num + 2 ^ S * num := by + rw [show sc1 * num + 2 ^ S * num = (sc1 + 2 ^ S) * num from by ring, ← hid] + have hdbl : 2 * sc2 * num / den ≤ 2 * (sc2 * num / den) + 1 := by + have hdm := Nat.div_add_mod (sc2 * num) den + have hmod : (sc2 * num) % den < den := Nat.mod_lt _ hdennat + have h2c : 2 * (sc2 * num) < (2 * (sc2 * num / den) + 2) * den := by + calc 2 * (sc2 * num) + = 2 * (den * (sc2 * num / den)) + 2 * ((sc2 * num) % den) := by omega + _ < 2 * (den * (sc2 * num / den)) + 2 * den := by omega + _ = (2 * (sc2 * num / den) + 2) * den := by ring + have harg : 2 * sc2 * num < (2 * (sc2 * num / den) + 2) * den := by + rw [show 2 * sc2 * num = 2 * (sc2 * num) from by ring] + exact h2c + have hlt := (Nat.div_lt_iff_lt_mul hdennat).mpr harg + omega + have hsuper : sc1 * num / den + 2 ^ S * num / den ≤ (sc1 * num + 2 ^ S * num) / den := by + rw [Nat.le_div_iff_mul_le hdennat] + have ha := Nat.div_mul_le_self (sc1 * num) den + have hb := Nat.div_mul_le_self (2 ^ S * num) den + calc (sc1 * num / den + 2 ^ S * num / den) * den + = sc1 * num / den * den + 2 ^ S * num / den * den := by ring + _ ≤ sc1 * num + 2 ^ S * num := Nat.add_le_add ha hb + have hSnum : 1 ≤ 2 ^ S * num / den := by + rw [Nat.le_div_iff_mul_le hdennat] + have h1 : 2 * num ≤ 2 ^ S * num := by + have h2 : (2:Nat) ≤ 2 ^ S := by + calc (2:Nat) = 2 ^ 1 := by norm_num + _ ≤ 2 ^ S := Nat.pow_le_pow_right (by norm_num) hS + exact Nat.mul_le_mul_right num h2 + calc 1 * den = den := Nat.one_mul den + _ ≤ 2 * num := le_of_lt hratioN + _ ≤ 2 ^ S * num := h1 + have hchain : sc1 * num / den + 1 ≤ 2 * sc2 * num / den := by + calc sc1 * num / den + 1 ≤ sc1 * num / den + 2 ^ S * num / den := + Nat.add_le_add_left hSnum _ + _ ≤ (sc1 * num + 2 ^ S * num) / den := hsuper + _ = 2 * sc2 * num / den := by rw [← hsplit] + omega + have hsmall : ∀ sc : Nat, sc * num < 2 ^ 256 → sc * num / den < 2 ^ 255 := by + intro sc hfit + have h1 : sc * num / den ≤ sc * num / 2 ^ 126 := + Nat.div_le_div_left hden126 (Nat.two_pow_pos _) + have h2 : sc * num / 2 ^ 126 < 2 ^ 130 := by + rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] + calc sc * num < 2 ^ 256 := hfit + _ = 2 ^ 130 * 2 ^ 126 := by norm_num + have h3 : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num + omega + rw [hq1, hq2, int256_of_lt (hsmall sc1 hfit1), int256_of_lt (hsmall sc2 hfit2)] + exact_mod_cast hkey + +/-! ## The odd-extended seam floor -/ + +/-- The seam floor comparison with one extra unit of slack: an odd excess over the doubled +argument cannot cross the even closing modulus, so `arg1 ≤ 2·arg2 + 1` still orders the shifted +floors across a one-bit shift drop. -/ +theorem seam_close_odd {arg1 arg2 s1 s2 : Nat} + (ha1 : arg1 < 2 ^ 256) (ha2 : arg2 < 2 ^ 256) + (hs1 : s1 < 256) (hs2 : s2 < 256) (hseq : s2 + 1 = s1) + (hnn1 : 0 ≤ int256 arg1) (hnn2 : 0 ≤ int256 arg2) + (hle : int256 arg1 ≤ 2 * int256 arg2 + 1) : + int256 (evmShr s1 arg1) ≤ int256 (evmShr s2 arg2) := by + obtain ⟨he1, hlt1⟩ := int256_eq_of_nonneg ha1 hnn1 + obtain ⟨he2, hlt2⟩ := int256_eq_of_nonneg ha2 hnn2 + have hleN : arg1 ≤ 2 * arg2 + 1 := by + have : ((arg1 : Nat) : Int) ≤ ((2 * arg2 + 1 : Nat) : Int) := by + rw [← he1] + push_cast + rw [← he2] + exact hle + exact_mod_cast this + rw [evmShr_eq_div hs1 ha1, evmShr_eq_div hs2 ha2] + -- ⌊(2·arg2 + 1)/2^s1⌋ = ⌊2·arg2/2^s1⌋: the odd numerator cannot complete the even modulus + have hodd : (2 * arg2 + 1) / 2 ^ s1 = 2 * arg2 / 2 ^ s1 := by + apply Nat.succ_div_of_not_dvd + intro hdvd + have h2 : (2:Nat) ∣ 2 ^ s1 := dvd_pow_self 2 (by omega : s1 ≠ 0) + have h3 : (2:Nat) ∣ 2 * arg2 + 1 := dvd_trans h2 hdvd + omega + have hkey : 2 * arg2 / 2 ^ s1 = arg2 / 2 ^ s2 := by + rw [← hseq, pow_succ, Nat.mul_comm (2 ^ s2) 2, Nat.mul_div_mul_left arg2 (2 ^ s2) (by norm_num)] + have hqle : arg1 / 2 ^ s1 ≤ arg2 / 2 ^ s2 := by + rw [← hkey, ← hodd] + exact Nat.div_le_div_right hleN + have hq1lt : arg1 / 2 ^ s1 < 2 ^ 255 := by + have h := Nat.div_le_self arg1 (2 ^ s1) + exact lt_of_le_of_lt h hlt1 + have hq2lt : arg2 / 2 ^ s2 < 2 ^ 255 := by + have h := Nat.div_le_self arg2 (2 ^ s2) + exact lt_of_le_of_lt h hlt2 + rw [int256_of_lt hq1lt, int256_of_lt hq2lt] + exact_mod_cast hqle + +/-! ## The adjacent magnitude step -/ + +/-- The signed closing shift is antitone in the magnitude word. -/ +theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) : + int256 (mulShiftTree b x) ≤ int256 (mulShiftTree a x) := by + have haQ : a ≤ scaleQ67 := le_trans hab hb + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) + have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleQ67; norm_num) + have haa : absTree a = a := absTree_of_small haQ + have hba : absTree b = b := absTree_of_small hb + have hta := mulShiftTree_transport (y := a) haw hx (by rw [haa]; exact haQ) hW + have htb := mulShiftTree_transport (y := b) hbw hx (by rw [hba]; exact hb) hW + rw [haa] at hta + rw [hba] at htb + rw [hta, htb] + have hanti := scaleShift_antitone ha hab hb + have hantiI : (scaleShiftTree b : Int) ≤ (scaleShiftTree a : Int) := by exact_mod_cast hanti + linarith [hantiI] + +/-- **The adjacent magnitude step**: at a fixed live exponent, one unit of magnitude never +decreases the kernel magnitude. -/ +theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleQ67) + (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) + (hlive2 : 2 ≤ int256 (mulShiftTree (a + 1) x)) : + int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + 1) x) := by + have haQ : a ≤ scaleQ67 := le_trans (Nat.le_succ a) ha1 + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) + have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleQ67; norm_num) + have haa : absTree a = a := absTree_of_small haQ + have ha1a : absTree (a + 1) = a + 1 := absTree_of_small ha1 + have hlive1 : 2 ≤ int256 (mulShiftTree a x) := + le_trans hlive2 (mulShiftY_antitone ha (Nat.le_succ a) ha1 hx hW) + -- headroom facts + obtain ⟨hs256a, hspec_a, hcap_a⟩ := mulScaleTree_spec (y := a) haw (by rw [haa]; exact haQ) + obtain ⟨hs256a1, hspec_a1, hcap_a1⟩ := mulScaleTree_spec (y := a + 1) ha1w + (by rw [ha1a]; exact ha1) + have hanti := scaleShift_antitone ha (Nat.le_succ a) ha1 + have hstep := scaleShift_step ha ha1 + -- word-level plumbing + have hm1 := mulMagnitudeTree_live (y := a) hx hx0 hW.1 + have hm2 := mulMagnitudeTree_live (y := a + 1) hx hx0 hW.1 + obtain ⟨harg1eq, harg1nn, harg1hi⟩ := mulShiftArg_facts (y := a) haw (by omega) hx + (by rw [haa]; exact haQ) hW + obtain ⟨harg2eq, harg2nn, harg2hi⟩ := mulShiftArg_facts (y := a + 1) ha1w (by omega) hx + (by rw [ha1a]; exact ha1) hW + obtain ⟨hsh1lo, hsh1lt, hsh1eq⟩ := mulShift_word_facts (y := a) haw hx + (by rw [haa]; exact haQ) hW hlive1 + obtain ⟨hsh2lo, hsh2lt, hsh2eq⟩ := mulShift_word_facts (y := a + 1) ha1w hx + (by rw [ha1a]; exact ha1) hW hlive2 + have hta := mulShiftTree_transport (y := a) haw hx (by rw [haa]; exact haQ) hW + have htb := mulShiftTree_transport (y := a + 1) ha1w hx (by rw [ha1a]; exact ha1) hW + rw [haa] at hta hspec_a + rw [ha1a] at htb hspec_a1 + have hr0a : r0MulTree a x = r0ScaledTree (a * 2 ^ scaleShiftTree a) x := by + rw [r0MulTree_eq_scaled, hspec_a] + have hr0a1 : r0MulTree (a + 1) x = r0ScaledTree ((a + 1) * 2 ^ scaleShiftTree (a + 1)) x := by + rw [r0MulTree_eq_scaled, hspec_a1] + rw [hspec_a] at hcap_a + rw [hspec_a1] at hcap_a1 + rw [hm1, hm2] + rcases Nat.eq_or_lt_of_le hanti with hSeq | hSlt + · -- same headroom shift: the scale grows, the closing shift is unchanged + have hr0mono : int256 (r0MulTree a x) ≤ int256 (r0MulTree (a + 1) x) := by + rw [hr0a, hr0a1, ← hSeq] + exact r0Scaled_mono_scale + (Nat.mul_le_mul_right _ (Nat.le_succ a)) (by rw [hSeq] at hcap_a1 ⊢; exact hcap_a1) + hx hW + have hsheq' : mulShiftTree a x = mulShiftTree (a + 1) x := by + have h1 : (mulShiftTree a x : Int) = (mulShiftTree (a + 1) x : Int) := by + rw [hsh1eq, hsh2eq, hta, htb, hSeq] + exact_mod_cast h1 + rw [← hsheq'] + set arg1 := evmSub (r0MulTree a x) marginWord with harg1def + set arg2 := evmSub (r0MulTree (a + 1) x) marginWord with harg2def + have ha1lt : arg1 < 2 ^ 256 := by rw [harg1def]; exact evmSub_lt _ _ + have ha2lt : arg2 < 2 ^ 256 := by rw [harg2def]; exact evmSub_lt _ _ + clear_value arg1 arg2 + have hargle : int256 arg1 ≤ int256 arg2 := by + rw [harg1eq, harg2eq] + exact sub_le_sub_right hr0mono 1 + obtain ⟨he1, hlt1⟩ := int256_eq_of_nonneg ha1lt (by rw [harg1eq]; exact harg1nn) + obtain ⟨he2, hlt2⟩ := int256_eq_of_nonneg ha2lt (by rw [harg2eq]; exact harg2nn) + have hargleN : arg1 ≤ arg2 := by + have : ((arg1 : Nat) : Int) ≤ ((arg2 : Nat) : Int) := by rw [← he1, ← he2]; exact hargle + exact_mod_cast this + rw [evmShr_eq_div hsh1lt ha1lt, evmShr_eq_div hsh1lt ha2lt] + have hqle : arg1 / 2 ^ mulShiftTree a x ≤ arg2 / 2 ^ mulShiftTree a x := + Nat.div_le_div_right hargleN + have hq1lt : arg1 / 2 ^ mulShiftTree a x < 2 ^ 255 := by + have h1 : arg1 / 2 ^ mulShiftTree a x ≤ arg1 := Nat.div_le_self _ _ + exact lt_of_le_of_lt h1 hlt1 + have hq2lt : arg2 / 2 ^ mulShiftTree a x < 2 ^ 255 := by + have h1 : arg2 / 2 ^ mulShiftTree a x ≤ arg2 := Nat.div_le_self _ _ + exact lt_of_le_of_lt h1 hlt2 + rw [int256_of_lt hq1lt, int256_of_lt hq2lt] + exact_mod_cast hqle + · -- the headroom shift drops one bit: the doubled scale gains one headroom unit + have hSid : scaleShiftTree a = scaleShiftTree (a + 1) + 1 := Nat.le_antisymm hstep hSlt + have hid : 2 * ((a + 1) * 2 ^ scaleShiftTree (a + 1)) = + a * 2 ^ scaleShiftTree a + 2 ^ scaleShiftTree a := by + rw [hSid, pow_succ] + ring + have hS1 : 1 ≤ scaleShiftTree a := by + rw [hSid] + exact Nat.succ_le_succ (Nat.zero_le _) + have hdouble : int256 (r0MulTree a x) ≤ 2 * int256 (r0MulTree (a + 1) x) := by + rw [hr0a, hr0a1] + exact r0Scaled_double_scale hS1 hid hcap_a hcap_a1 hx hW + have hseq : mulShiftTree (a + 1) x + 1 = mulShiftTree a x := by + have h1 : (mulShiftTree (a + 1) x : Int) + 1 = (mulShiftTree a x : Int) := by + rw [hsh1eq, hsh2eq, hta, htb] + have : (scaleShiftTree a : Int) = (scaleShiftTree (a + 1) : Int) + 1 := by + exact_mod_cast hSid + rw [this] + ring + exact_mod_cast h1 + set arg1 := evmSub (r0MulTree a x) marginWord with harg1def + set arg2 := evmSub (r0MulTree (a + 1) x) marginWord with harg2def + have ha1lt : arg1 < 2 ^ 256 := by rw [harg1def]; exact evmSub_lt _ _ + have ha2lt : arg2 < 2 ^ 256 := by rw [harg2def]; exact evmSub_lt _ _ + clear_value arg1 arg2 + have hargle : int256 arg1 ≤ 2 * int256 arg2 + 1 := by + rw [harg1eq, harg2eq] + linarith [hdouble] + exact seam_close_odd ha1lt ha2lt hsh1lt hsh2lt hseq + (by rw [harg1eq]; exact harg1nn) (by rw [harg2eq]; exact harg2nn) hargle + +/-! ## The magnitude induction -/ + +/-- Unit-step induction over the magnitude: the endpoint's live shift bounds every +intermediate through the headroom antitonicity. -/ +theorem mulMagnitudeY_mono_steps {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) + (hx0 : int256 x ≠ 0) (n : Nat) : + ∀ a : Nat, 1 ≤ a → a + n ≤ scaleQ67 → + 2 ≤ int256 (mulShiftTree (a + n) x) → + int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + n) x) := by + induction n with + | zero => + intro a _ _ _ + exact le_refl _ + | succ m ih => + intro a ha hbnd hlive + have hstep : int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + 1) x) := by + have hlive1 : 2 ≤ int256 (mulShiftTree (a + 1) x) := by + have h := mulShiftY_antitone (a := a + 1) (b := a + m + 1) (by omega) + (by omega) (by omega) hx hW + have h2 : a + (m + 1) = a + m + 1 := by omega + rw [h2] at hlive + linarith [h, hlive] + exact mulMagnitudeY_step ha (by omega) hx hW hx0 hlive1 + have hrec := ih (a + 1) (by omega) (by omega) (by + have h2 : a + 1 + m = a + (m + 1) := by omega + rw [h2] + exact hlive) + have h3 : a + 1 + m = a + (m + 1) := by omega + rw [h3] at hrec + exact le_trans hstep hrec + +/-- **Magnitude monotonicity in the multiplier at a fixed live exponent.** -/ +theorem mulMagnitudeY_region_mono {a1 a2 x : Nat} (ha1 : 1 ≤ a1) (h12 : a1 ≤ a2) + (ha2 : a2 ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) + (hlive2 : 2 ≤ int256 (mulShiftTree a2 x)) : + int256 (mulMagnitudeTree a1 x) ≤ int256 (mulMagnitudeTree a2 x) := by + have h := mulMagnitudeY_mono_steps hx hW hx0 (a2 - a1) a1 ha1 + (by omega) (by rw [show a1 + (a2 - a1) = a2 from by omega]; exact hlive2) + rw [show a1 + (a2 - a1) = a2 from by omega] at h + exact h + +/-! ## The public runtime statement -/ + +/-- **Monotonicity in the multiplier on the value domain.** For a fixed exponent and accepted +multipliers `y1 ≤ y2`, the signed results are ordered. -/ +theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} + (h1 : MulExpRayValueDomain y1 x) (h2 : MulExpRayValueDomain y2 x) + (hle : int256 y1 ≤ int256 y2) : + MulExpRayRunYMonotone y1 y2 x := by + obtain ⟨⟨hy1, hxw⟩, habs1, hxhi, hcase1⟩ := h1 + obtain ⟨⟨hy2, _⟩, habs2, _, hcase2⟩ := h2 + have hrun1 : run_mul_exp_ray_evm y1 x = .ok (mulExpTree y1 x) := + run_mul_exp_ray_evm_eq_tree ⟨⟨hy1, hxw⟩, habs1, hxhi, hcase1⟩ + have hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x) := + run_mul_exp_ray_evm_eq_tree ⟨⟨hy2, hxw⟩, habs2, hxhi, hcase2⟩ + refine ⟨mulExpTree y1 x, mulExpTree y2 x, hrun1, hrun2, hle, ?_⟩ + -- the exponent's class decides the result shape + by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax + · rw [mulExpTree_clamped hxw hcl, mulExpTree_clamped hxw hcl] + by_cases hx0 : int256 x = 0 + · have hxz : x = 0 := (int256_zero_iff_of_canonical hxw).1 hx0 + subst hxz + rw [mulExpTree_scale_point hy1 habs1, mulExpTree_scale_point hy2 habs2] + exact hle + -- the live region + have hW : WideRegion x := ⟨by omega, hxhi⟩ + have hlive : ∀ y : Nat, y < 2 ^ 256 → absTree y ≤ scaleQ67 → + (int256 x = 0 ∨ int256 x ≤ int256 mulExpRayZeroMax ∨ + 2 ≤ int256 (mulShiftTree y x)) → 2 ≤ int256 (mulShiftTree y x) := by + intro y _ _ hcase + rcases hcase with h | h | h + · exact absurd h hx0 + · exact absurd h hcl + · exact h + have hlv1 := hlive y1 hy1 habs1 hcase1 + have hlv2 := hlive y2 hy2 habs2 hcase2 + -- the live magnitudes, at the magnitude words + rcases Nat.eq_zero_or_pos y1 with hz1 | hp1 + · subst hz1 + rw [mulExpTree_zero, int256_zero_word'] + -- the other result is nonnegative: `int256 y2 ≥ int256 0 = 0` keeps `y2` on the + -- nonnegative-word side + rcases Nat.eq_zero_or_pos y2 with hz2 | hp2 + · subst hz2 + rw [mulExpTree_zero, int256_zero_word'] + · have h0 : int256 (0 : Nat) = 0 := int256_zero_word' + rw [h0] at hle + have hy2small : y2 < 2 ^ 255 := by + by_contra hbig + have := int256_y_neg (by omega) hy2 + omega + obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy2 hxw (by omega) habs2 hx0 hW hlv2 + rw [int256_tree_pos hp2 hy2small] + exact hm0 + rcases Nat.eq_zero_or_pos y2 with hz2 | hp2 + · subst hz2 + rw [mulExpTree_zero, int256_zero_word'] + have h0 : int256 (0 : Nat) = 0 := int256_zero_word' + rw [h0] at hle + have hy1big : 2 ^ 255 ≤ y1 := by + by_contra hsmall + have h1 : int256 y1 = (y1 : Int) := int256_of_lt (by omega) + rw [h1] at hle + have : y1 = 0 := by exact_mod_cast le_antisymm (by exact_mod_cast hle) (Nat.zero_le y1) + omega + have hm255 := mag_word_small hy1 (by omega) hxw habs1 hx0 hW hlv1 + obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy1 hxw (by omega) habs1 hx0 hW hlv1 + rw [int256_tree_neg hy1big hy1 hm255] + linarith [hm0] + -- both multipliers nonzero + by_cases hneg1 : y1 < 2 ^ 255 + · -- y1 on the nonnegative-word side, hence so is y2 + have hy2small : y2 < 2 ^ 255 := by + by_contra hbig + have hn := int256_y_neg (by omega) hy2 + have hp := int256_of_lt hneg1 + rw [hp] at hle + have : (0:Int) ≤ (y1 : Int) := Int.natCast_nonneg y1 + omega + have h12 : y1 ≤ y2 := by + have ha := int256_of_lt hneg1 + have hb := int256_of_lt hy2small + rw [ha, hb] at hle + exact_mod_cast hle + have haa2 : absTree y2 = y2 := absTree_nonneg hy2small + rw [int256_tree_pos hp1 hneg1, int256_tree_pos hp2 hy2small] + refine mulMagnitudeY_region_mono (by omega) h12 ?_ hxw hW hx0 hlv2 + rw [← haa2] + exact habs2 + · -- y1 on the negative-word side + have hy1big : 2 ^ 255 ≤ y1 := by omega + by_cases hneg2 : y2 < 2 ^ 255 + · -- signs differ: a nonpositive result against a nonnegative one + have hm255a := mag_word_small hy1 (by omega) hxw habs1 hx0 hW hlv1 + obtain ⟨hm0a, _, _, _⟩ := mulMagnitude_bracket_live hy1 hxw (by omega) habs1 hx0 hW hlv1 + obtain ⟨hm0b, _, _, _⟩ := mulMagnitude_bracket_live hy2 hxw (by omega) habs2 hx0 hW hlv2 + rw [int256_tree_neg hy1big hy1 hm255a, int256_tree_pos hp2 hneg2] + linarith [hm0a, hm0b] + · -- both negative: magnitudes reverse + have hy2big : 2 ^ 255 ≤ y2 := by omega + have haa1 : absTree y1 = 2 ^ 256 - y1 := absTree_neg hy1big hy1 + have haa2 : absTree y2 = 2 ^ 256 - y2 := absTree_neg hy2big hy2 + have h21 : absTree y2 ≤ absTree y1 := by + rw [haa1, haa2] + have ha := int256_neg_eq_abs hy1big hy1 + have hb := int256_neg_eq_abs hy2big hy2 + rw [ha, hb, haa1, haa2] at hle + have h1 : ((2 ^ 256 - y2 : Nat) : Int) ≤ ((2 ^ 256 - y1 : Nat) : Int) := by omega + exact_mod_cast h1 + have hmag : int256 (mulMagnitudeTree (absTree y2) x) ≤ + int256 (mulMagnitudeTree (absTree y1) x) := by + refine mulMagnitudeY_region_mono ?_ h21 habs1 hxw hW hx0 ?_ + · have : 1 ≤ absTree y2 := absTree_pos hy2 (by omega) + omega + · rw [← mulShift_abs_norm habs1] + exact hlv1 + have hm255a := mag_word_small hy1 (by omega) hxw habs1 hx0 hW hlv1 + have hm255b := mag_word_small hy2 (by omega) hxw habs2 hx0 hW hlv2 + rw [int256_tree_neg hy1big hy1 hm255a, int256_tree_neg hy2big hy2 hm255b, + mulMagnitude_abs_norm habs1, mulMagnitude_abs_norm habs2] + linarith [hmag] + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index ef137801b..a743d05ec 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -9,6 +9,7 @@ import ExpProof.Floor.RoundTrip import ExpProof.Mul.Shell import ExpProof.Mul.Accum import ExpProof.Mul.XMono +import ExpProof.Mul.YMono /-! # `expRayToWad` and `mulExpRay` — compiled-runtime proof signpost @@ -108,6 +109,7 @@ arguments. Discharged today, axiom-clean: | Rejected inputs revert | `run_mul_exp_ray_evm_revert` | | Signed bracket `0 ≤ m ≤ A < m + 2` on the domain | `mulExpRay_run_bracket` | | Sign-directed monotonicity in the exponent | `run_mul_exp_ray_evm_mono_x` | +| Monotonicity in the multiplier | `run_mul_exp_ray_evm_mono_y` | | Result magnitude is `⌊A⌋` or `⌊A⌋ − 1` | `mulExpRay_run_floor_membership` | | `A < 1` pins the result to zero | `mulExpRay_run_pins_zero` | | Zero multiplier returns zero (and its bracket) | `run_mul_exp_ray_evm_zero_of_guard` | @@ -117,10 +119,10 @@ arguments. Discharged today, axiom-clean: The bracket and the monotonicity in the exponent are proven on the whole value domain: the scale-symbolic per-point certificates (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) instantiate at the dynamic scale `abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`, the accumulator fold -(`Mul.Accum`) closes the live-region bracket, and the unit-step induction with the scaled seam -doubling (`Mul.XMono`) closes the sign-directed exponent monotonicity. Still open, visible below -as explicit hypotheses of the facade lemmas: the runtime monotonicity statements in the -multiplier and the joint form. +(`Mul.Accum`) closes the live-region bracket, the unit-step induction with the scaled seam +doubling (`Mul.XMono`) closes the sign-directed exponent monotonicity, and the headroom-step +induction (`Mul.YMono`) closes the multiplier monotonicity. Still open, visible below as an +explicit hypothesis of the facade lemma: the joint runtime monotonicity statement. -/ /-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ @@ -139,6 +141,12 @@ example {y x1 x2 : Nat} (h1 : MulExpRayValueDomain y x1) (h2 : MulExpRayValueDom MulExpRayRunMonotone y x1 x2 := run_mul_exp_ray_evm_mono_x h1 h2 hle +/-- **Monotonicity in the multiplier on the value domain.** -/ +example {y1 y2 x : Nat} (h1 : MulExpRayValueDomain y1 x) (h2 : MulExpRayValueDomain y2 x) + (hle : FormalYul.Preservation.int256 y1 ≤ FormalYul.Preservation.int256 y2) : + MulExpRayRunYMonotone y1 y2 x := + run_mul_exp_ray_evm_mono_y h1 h2 hle + /-- **Floor membership.** Every accepted input's result magnitude is `⌊A⌋` or `⌊A⌋ − 1`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ @@ -314,6 +322,10 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms run_mul_exp_ray_evm_mono_x +/-- info: 'ExpYul.run_mul_exp_ray_evm_mono_y' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms run_mul_exp_ray_evm_mono_y + /-- info: 'ExpYul.mulExpRay_run_floor_membership' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms mulExpRay_run_floor_membership From 04a8331f2766899048621129f7a81e939305d0f3 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 15:08:45 +0200 Subject: [PATCH 072/107] Prove mulExpRay joint monotonicity and complete the natspec signpost Mul/Joint.lean composes the two single-argument monotonicity theorems through a corner of the rectangle, which stays accepted because the headroom shift is antitone in the magnitude (shrinking the magnitude only grows the accepted exponent set); the mixed-sign case follows from the result-sign facts the signed bracket forces. The guard gains its octave vocabulary: on canonical inputs, rejection is exactly a too-large magnitude, an exponent at or beyond the unconditional fence, or a live exponent whose octave count exceeds the headroom shift less two - and type(int256).min always reverts, its magnitude word being 2^255. The signpost now states every documented mulExpRay property as a gated runtime theorem, cites the Panic(0x11) instantiation of the revert path, and the discharged tree-obligation facades are retired. Co-Authored-By: Claude Fable 5 --- formal/README.md | 2 +- formal/exp/ExpProof/ExpProof/Mul.lean | 51 +--- formal/exp/ExpProof/ExpProof/Mul/Accum.lean | 4 +- formal/exp/ExpProof/ExpProof/Mul/Joint.lean | 281 ++++++++++++++++++ .../exp/ExpProof/ExpProof/Mul/Transport.lean | 4 + formal/exp/ExpProof/ExpProof/Theorems.lean | 148 +++++---- 6 files changed, 362 insertions(+), 128 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Mul/Joint.lean diff --git a/formal/README.md b/formal/README.md index 58d3a4f4f..494280af5 100644 --- a/formal/README.md +++ b/formal/README.md @@ -11,7 +11,7 @@ Machine-checked Lean 4 correctness proofs for root math libraries in 0x Settler. | `cbrt/CbrtProof` | `src/vendor/Cbrt.sol` | `_cbrt`, `cbrt`, `cbrtUp` correct on uint256 | | `cbrt/Cbrt512Proof` | `src/utils/512Math.sol` | `_cbrt` (512-bit) correct: `cbrt(x_hi * 2^256 + x_lo) = icbrt(x)` | | `ln/LnProof` | `src/vendor/Ln.sol` | `lnWadToRay`, `lnWad` correct vs. `Real.log`, monotone, with a 1.6986-ulp error bound | -| `exp/ExpProof` | `src/vendor/Exp.sol` | `expRayToWad` correct vs. `Real.exp`: never over, floor-or-one-less, monotone, and the central `lnWadToRay` round trip. `mulExpRay`: exact accept/revert domains, value path to the compiled tree, and the bracket at the scale point and the zero clamp; the live-region bracket and monotonicity still need the certificates generalized to the dynamic scale | +| `exp/ExpProof` | `src/vendor/Exp.sol` | `expRayToWad` correct vs. `Real.exp`: never over, floor-or-one-less, monotone, and the central `lnWadToRay` round trip. `mulExpRay` correct vs. `abs(y)·Real.exp(x/10²⁷)`: exact accept/revert domains (also stated in octave vocabulary), value path to the compiled tree, the signed two-unit bracket with floor membership over the whole accepted domain, and monotonicity in each argument and jointly | ## Method diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index f91004853..8b2e8a889 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -7,12 +7,12 @@ import ExpProof.Mul.Domain import ExpProof.Mul.Bridge /-! -# `mulExpRay` proof facade +# `mulExpRay` public runtime specifications -This module states the public runtime specifications for `mulExpRay` and exposes the proof -obligations that connect the compiled run to the arithmetic tree. The tree is defined in -`Mono.MulTree`; consumers supply proofs that the tree satisfies the real bracket and x/y -monotonicity predicates below. +This module states the public runtime specifications for `mulExpRay` — the signed bracket and +the three monotonicity forms over successful runs — together with the shell results that need no +polynomial certificate. The tree is defined in `Mono.MulTree`; the bracket and monotonicity +statements are discharged in `Mul.Accum`, `Mul.XMono`, `Mul.YMono`, and `Mul.Joint`. -/ namespace ExpYul @@ -44,44 +44,6 @@ def MulExpRayRunJointMonotone (y1 y2 x1 x2 : Nat) : Prop := MulExpRayJointMonotone (int256 y1) (int256 y2) (int256 x1) (int256 x2) (int256 r1) (int256 r2) -/-- Runtime bracket proof obligation for the named arithmetic tree. -/ -theorem mulExpRay_run_bracket_of_tree - {y x : Nat} - (hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x)) - (hbracket : MulExpRayBracket (int256 y) (int256 x) (int256 (mulExpTree y x))) : - MulExpRayRunBracket y x := - ⟨mulExpTree y x, hrun, hbracket⟩ - -/-- Runtime monotonicity-in-`x` proof obligation for the named arithmetic tree. -/ -theorem mulExpRay_run_monotone_of_tree - {y x1 x2 : Nat} - (hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1)) - (hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2)) - (hmono : MulExpRaySignedMonotone (int256 y) (int256 x1) (int256 x2) - (int256 (mulExpTree y x1)) (int256 (mulExpTree y x2))) : - MulExpRayRunMonotone y x1 x2 := - ⟨mulExpTree y x1, mulExpTree y x2, hrun1, hrun2, hmono⟩ - -/-- Runtime monotonicity-in-`y` proof obligation for the named arithmetic tree. -/ -theorem mulExpRay_run_y_monotone_of_tree - {y1 y2 x : Nat} - (hrun1 : run_mul_exp_ray_evm y1 x = .ok (mulExpTree y1 x)) - (hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x)) - (hmono : MulExpRayYMonotone (int256 y1) (int256 y2) (int256 x) - (int256 (mulExpTree y1 x)) (int256 (mulExpTree y2 x))) : - MulExpRayRunYMonotone y1 y2 x := - ⟨mulExpTree y1 x, mulExpTree y2 x, hrun1, hrun2, hmono⟩ - -/-- Runtime sign-aware joint monotonicity proof obligation for the named arithmetic tree. -/ -theorem mulExpRay_run_joint_monotone_of_tree - {y1 y2 x1 x2 : Nat} - (hrun1 : run_mul_exp_ray_evm y1 x1 = .ok (mulExpTree y1 x1)) - (hrun2 : run_mul_exp_ray_evm y2 x2 = .ok (mulExpTree y2 x2)) - (hmono : MulExpRayJointMonotone (int256 y1) (int256 y2) (int256 x1) (int256 x2) - (int256 (mulExpTree y1 x1)) (int256 (mulExpTree y2 x2))) : - MulExpRayRunJointMonotone y1 y2 x1 x2 := - ⟨mulExpTree y1 x1, mulExpTree y2 x2, hrun1, hrun2, hmono⟩ - /-- The zero-magnitude result satisfies the signed `mulExpRay` bracket for every exponent. -/ theorem mulExpRayBracket_zero_result (x : Int) : MulExpRayBracket 0 x 0 := by @@ -131,7 +93,8 @@ theorem floorOrOneLess_to_mulExpRayBracket_wad {x r : Int} norm_num at hw exact ⟨hr, by simpa [hw] using h.1, by simpa [hw] using h.2⟩ -/-- Runtime specialization proof obligation for the existing `expRayToWad` theorem stack. -/ +/-- Runtime specialization: an `expRayToWad` floor bracket instantiates the `mulExpRay` +bracket at `y = 10¹⁸`. -/ theorem mulExpRay_run_bracket_wad_of_exp {x r : Nat} (hrun : run_mul_exp_ray_evm (10 ^ 18) x = .ok r) diff --git a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean index 9d127ad22..0e062d4fb 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean @@ -293,8 +293,8 @@ theorem mulExpRay_run_bracket {y x : Nat} (h : MulExpRayValueDomain y x) : have hWx : WideRegion x := ⟨by omega, hxhi⟩ have hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ - exact mulExpRay_run_bracket_of_tree hrun - (mulExpTree_bracket_live hy hx (by omega) habs hx0 hWx hlive) + exact ⟨mulExpTree y x, hrun, + mulExpTree_bracket_live hy hx (by omega) habs hx0 hWx hlive⟩ /-! ## Floor membership and the small-target pin -/ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean new file mode 100644 index 000000000..95bd91a77 --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean @@ -0,0 +1,281 @@ +import ExpProof.Mul.YMono + +/-! +# `mulExpRay` joint monotonicity and the octave view of the guard + +The joint sign-aware monotonicity composes the two single-argument statements through an +intermediate corner of the rectangle, which is accepted because the headroom shift is antitone +in the magnitude: shrinking the magnitude only grows the accepted exponent set. The mixed-sign +case needs no intermediate — a nonpositive multiplier's result is nonpositive and a nonnegative +multiplier's is nonnegative, directly from the signed bracket's shape. + +The guard also admits the octave vocabulary of the natspec: on canonical inputs, rejection is +exactly a too-large magnitude, an exponent at or beyond the unconditional fence, or a live +exponent whose octave count exceeds the headroom shift less two. +-/ + +namespace ExpYul + +open FormalYul +open FormalYul.Preservation +open ExpRealSpec + +set_option maxRecDepth 100000 +set_option maxHeartbeats 1600000 + +/-! ## Acceptance transfers along the antitone headroom -/ + +/-- The headroom shift is antitone in the magnitude, including the zero magnitude. -/ +theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleQ67) : + scaleShiftTree b ≤ scaleShiftTree a := by + rcases Nat.eq_zero_or_pos a with h0 | hpos + · subst h0 + rw [scaleShiftTree_zero] + have hb' : absTree b = b := + absTree_nonneg (lt_of_le_of_lt hb (by unfold scaleQ67; norm_num)) + have h := scaleShiftTree_le_127 (y := b) (by rw [hb']; exact hb) + rw [hb'] at h + exact h + · exact scaleShift_antitone hpos hab hb + +/-- Shrinking the magnitude keeps an accepted input accepted: the headroom shift only grows. -/ +theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : y1 < 2 ^ 256) + (h2 : MulExpRayValueDomain y2 x) (hab : absTree y1 ≤ absTree y2) : + MulExpRayValueDomain y1 x := by + obtain ⟨⟨hy2, hx⟩, habs2, hxhi, hcase⟩ := h2 + have habs1 : absTree y1 ≤ scaleQ67 := le_trans hab habs2 + refine ⟨⟨hy1, hx⟩, habs1, hxhi, ?_⟩ + by_cases hx0 : int256 x = 0 + · exact Or.inl hx0 + by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax + · exact Or.inr (Or.inl hcl) + have hlv2 : 2 ≤ int256 (mulShiftTree y2 x) := by + rcases hcase with h | h | h + · exact absurd h hx0 + · exact absurd h hcl + · exact h + have hW : WideRegion x := ⟨by omega, hxhi⟩ + refine Or.inr (Or.inr ?_) + have ht1 := mulShiftTree_transport hy1 hx habs1 hW + have ht2 := mulShiftTree_transport hy2 hx habs2 hW + have hanti : scaleShiftTree (absTree y2) ≤ scaleShiftTree (absTree y1) := + scaleShift_antitone' hab habs2 + have hantiI : (scaleShiftTree (absTree y2) : Int) ≤ (scaleShiftTree (absTree y1) : Int) := by + exact_mod_cast hanti + rw [ht1] + rw [ht2] at hlv2 + linarith [hantiI, hlv2] + +/-! ## Result signs from the bracket shape -/ + +/-- A nonnegative multiplier's accepted result is nonnegative. -/ +theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) + (hyw : y < 2 ^ 255) : 0 ≤ int256 (mulExpTree y x) := by + obtain ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ := h + rcases Nat.eq_zero_or_pos y with h0 | hpos + · subst h0 + rw [mulExpTree_zero, int256_zero_word'] + by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax + · rw [mulExpTree_clamped hx hcl, int256_zero_word'] + by_cases hx0 : int256 x = 0 + · have hxz : x = 0 := (int256_zero_iff_of_canonical hx).1 hx0 + subst hxz + rw [mulExpTree_scale_point hy habs, int256_of_lt hyw] + exact Int.natCast_nonneg y + · have hlv : 2 ≤ int256 (mulShiftTree y x) := by + rcases hcase with h | h | h + · exact absurd h hx0 + · exact absurd h hcl + · exact h + have hW : WideRegion x := ⟨by omega, hxhi⟩ + obtain ⟨hm0, _, _, _⟩ := + mulMagnitude_bracket_live hy hx (by omega) habs hx0 hW hlv + rw [int256_tree_pos hpos hyw] + exact hm0 + +/-- A nonpositive multiplier's accepted result is nonpositive. -/ +theorem mulExpTree_result_nonpos {y x : Nat} (h : MulExpRayValueDomain y x) + (hyneg : int256 y ≤ 0) : int256 (mulExpTree y x) ≤ 0 := by + obtain ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ := h + rcases Nat.eq_zero_or_pos y with h0 | hpos + · subst h0 + rw [mulExpTree_zero, int256_zero_word'] + have hybig : 2 ^ 255 ≤ y := by + by_contra hsmall + rw [int256_of_lt (by omega)] at hyneg + have h1 : y = 0 := by exact_mod_cast le_antisymm (by exact_mod_cast hyneg) (Nat.zero_le y) + omega + by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax + · rw [mulExpTree_clamped hx hcl, int256_zero_word'] + by_cases hx0 : int256 x = 0 + · have hxz : x = 0 := (int256_zero_iff_of_canonical hx).1 hx0 + subst hxz + rw [mulExpTree_scale_point hy habs] + exact hyneg + · have hlv : 2 ≤ int256 (mulShiftTree y x) := by + rcases hcase with h | h | h + · exact absurd h hx0 + · exact absurd h hcl + · exact h + have hW : WideRegion x := ⟨by omega, hxhi⟩ + obtain ⟨hm0, _, _, _⟩ := + mulMagnitude_bracket_live hy hx (by omega) habs hx0 hW hlv + have hm255 := mag_word_small hy (by omega) hx habs hx0 hW hlv + rw [int256_tree_neg hybig hy hm255] + linarith [hm0] + +/-! ## The joint statement -/ + +private theorem tree_of_run {y x r : Nat} + (hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x)) + (hr : run_mul_exp_ray_evm y x = .ok r) : r = mulExpTree y x := by + rw [hrun] at hr + injection hr with h + exact h.symm + +/-- **Sign-aware joint monotonicity on the value domain.** For accepted pairs, the results are +ordered when a nonnegative multiplier grows with the exponent, a nonpositive one grows against +it, or the multipliers straddle zero. -/ +theorem run_mul_exp_ray_evm_mono_joint {y1 y2 x1 x2 : Nat} + (h1 : MulExpRayValueDomain y1 x1) (h2 : MulExpRayValueDomain y2 x2) + (hcond : (0 ≤ int256 y1 ∧ int256 y1 ≤ int256 y2 ∧ int256 x1 ≤ int256 x2) ∨ + (int256 y1 ≤ int256 y2 ∧ int256 y2 ≤ 0 ∧ int256 x2 ≤ int256 x1) ∨ + (int256 y1 ≤ 0 ∧ 0 ≤ int256 y2)) : + MulExpRayRunJointMonotone y1 y2 x1 x2 := by + have hrun1 : run_mul_exp_ray_evm y1 x1 = .ok (mulExpTree y1 x1) := + run_mul_exp_ray_evm_eq_tree h1 + have hrun2 : run_mul_exp_ray_evm y2 x2 = .ok (mulExpTree y2 x2) := + run_mul_exp_ray_evm_eq_tree h2 + refine ⟨mulExpTree y1 x1, mulExpTree y2 x2, hrun1, hrun2, hcond, ?_⟩ + have hy1w : y1 < 2 ^ 256 := h1.1.1 + have hy2w : y2 < 2 ^ 256 := h2.1.1 + rcases hcond with ⟨hy1nn, hy12, hx12⟩ | ⟨hy12, hy2np, hx21⟩ | ⟨hy1np, hy2nn⟩ + · -- both nonnegative, exponents rising: route through (y1, x2) + have hy1small : y1 < 2 ^ 255 := by + by_contra hbig + have := int256_y_neg (by omega) hy1w + omega + have hy2small : y2 < 2 ^ 255 := by + by_contra hbig + have := int256_y_neg (by omega) hy2w + omega + have hab : absTree y1 ≤ absTree y2 := by + rw [absTree_nonneg hy1small, absTree_nonneg hy2small] + rw [int256_of_lt hy1small, int256_of_lt hy2small] at hy12 + exact_mod_cast hy12 + have h12 : MulExpRayValueDomain y1 x2 := valueDomain_of_abs_le hy1w h2 hab + obtain ⟨r1, r2, hr1, hr2, _, hordx⟩ := run_mul_exp_ray_evm_mono_x h1 h12 hx12 + obtain ⟨r3, r4, hr3, hr4, _, hordy⟩ := run_mul_exp_ray_evm_mono_y h12 h2 hy12 + have e1 := tree_of_run hrun1 hr1 + have e2 := tree_of_run (run_mul_exp_ray_evm_eq_tree h12) hr2 + have e3 := tree_of_run (run_mul_exp_ray_evm_eq_tree h12) hr3 + have e4 := tree_of_run hrun2 hr4 + rw [if_neg (int256_y_nonneg hy1small), e1, e2] at hordx + rw [e3, e4] at hordy + exact le_trans hordx hordy + · -- both nonpositive, exponents falling: route through (y2, x1) + have hab : absTree y2 ≤ absTree y1 := by + rcases Nat.eq_zero_or_pos y2 with h0 | hpos2 + · subst h0 + rw [show absTree 0 = 0 from absTree_nonneg (by norm_num)] + exact Nat.zero_le _ + have hy2big : 2 ^ 255 ≤ y2 := by + by_contra hsmall + rw [int256_of_lt (by omega)] at hy2np + have h1 : y2 = 0 := by + exact_mod_cast le_antisymm (by exact_mod_cast hy2np) (Nat.zero_le y2) + omega + have hy1big : 2 ^ 255 ≤ y1 := by + by_contra hsmall + have hnn : 0 ≤ int256 y1 := by + rw [int256_of_lt (by omega)] + exact Int.natCast_nonneg y1 + have hlt := int256_y_neg hy2big hy2w + omega + have ha := int256_neg_eq_abs hy1big hy1w + have hb := int256_neg_eq_abs hy2big hy2w + rw [ha, hb] at hy12 + have h1 : (absTree y2 : Int) ≤ (absTree y1 : Int) := by linarith [hy12] + exact_mod_cast h1 + have h21 : MulExpRayValueDomain y2 x1 := valueDomain_of_abs_le hy2w h1 hab + obtain ⟨r1, r2, hr1, hr2, _, hordy⟩ := run_mul_exp_ray_evm_mono_y h1 h21 hy12 + obtain ⟨r3, r4, hr3, hr4, _, hordx⟩ := run_mul_exp_ray_evm_mono_x h2 h21 hx21 + have e1 := tree_of_run hrun1 hr1 + have e2 := tree_of_run (run_mul_exp_ray_evm_eq_tree h21) hr2 + have e3 := tree_of_run hrun2 hr3 + have e4 := tree_of_run (run_mul_exp_ray_evm_eq_tree h21) hr4 + rw [e1, e2] at hordy + rw [e3, e4] at hordx + -- x-monotonicity at the nonpositive multiplier runs against the exponent + rcases Nat.eq_zero_or_pos y2 with h0 | hpos2 + · subst h0 + have hz1 : mulExpTree 0 x1 = 0 := mulExpTree_zero x1 + have hz2 : mulExpTree 0 x2 = 0 := mulExpTree_zero x2 + rw [hz1] at hordy + rw [hz2] + exact hordy + · have hy2big : 2 ^ 255 ≤ y2 := by + by_contra hsmall + rw [int256_of_lt (by omega)] at hy2np + have h1 : y2 = 0 := by + exact_mod_cast le_antisymm (by exact_mod_cast hy2np) (Nat.zero_le y2) + omega + rw [if_pos (int256_y_neg hy2big hy2w)] at hordx + exact le_trans hordy hordx + · -- straddling zero: nonpositive against nonnegative + have hy2small : y2 < 2 ^ 255 := by + by_contra hbig + have := int256_y_neg (by omega) hy2w + omega + have h1np := mulExpTree_result_nonpos h1 hy1np + have h2nn := mulExpTree_result_nonneg h2 hy2small + linarith [h1np, h2nn] + +/-! ## The octave vocabulary of the guard -/ + +/-- **The panic domain in octave language.** On canonical inputs, `mulExpRay` rejects exactly a +magnitude above the maximal scale, an exponent at or beyond the unconditional fence, or a live +exponent whose octave count exceeds the headroom shift less two. -/ +theorem panicDomain_iff_octave {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayPanicDomain y x ↔ + scaleQ67 < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ + (int256 x ≠ 0 ∧ int256 mulExpRayZeroMax < int256 x ∧ + (scaleShiftTree (absTree y) : Int) - 2 < int256 (kTree x)) := by + obtain ⟨hy, hx⟩ := hcanon + constructor + · rintro ⟨_, hbad⟩ + rcases hbad with h | h | ⟨hx0, hzm, hsh⟩ + · exact Or.inl h + · exact Or.inr (Or.inl h) + · by_cases habs : absTree y ≤ scaleQ67 + · by_cases hxhi : int256 x < int256 mulExpRayHi + · have hW : WideRegion x := ⟨hzm, hxhi⟩ + have ht := mulShiftTree_transport hy hx habs hW + rw [ht] at hsh + exact Or.inr (Or.inr ⟨hx0, hzm, by linarith [hsh]⟩) + · exact Or.inr (Or.inl (by omega)) + · exact Or.inl (by omega) + · rintro (h | h | ⟨hx0, hzm, hk⟩) + · exact ⟨⟨hy, hx⟩, Or.inl h⟩ + · exact ⟨⟨hy, hx⟩, Or.inr (Or.inl h)⟩ + · by_cases habs : absTree y ≤ scaleQ67 + · by_cases hxhi : int256 x < int256 mulExpRayHi + · have hW : WideRegion x := ⟨hzm, hxhi⟩ + have ht := mulShiftTree_transport hy hx habs hW + refine ⟨⟨hy, hx⟩, Or.inr (Or.inr ⟨hx0, hzm, ?_⟩)⟩ + rw [ht] + linarith [hk] + · exact ⟨⟨hy, hx⟩, Or.inr (Or.inl (by omega))⟩ + · exact ⟨⟨hy, hx⟩, Or.inl (by omega)⟩ + +/-- **The `type(int256).min` multiplier always reverts**: its magnitude word is `2^255`, above +the maximal scale. -/ +theorem run_mul_exp_ray_evm_revert_int_min {x : Nat} (hx : x < 2 ^ 256) : + run_mul_exp_ray_evm (2 ^ 255) x = .error "revert" := by + apply run_mul_exp_ray_evm_revert + refine ⟨⟨by norm_num, hx⟩, Or.inl ?_⟩ + rw [absTree_neg (le_refl _) (by norm_num)] + unfold scaleQ67 + norm_num + +end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean index c2c4f2f68..1d7d2a4e9 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -143,6 +143,10 @@ private theorem scaleShiftTree_cases (ay : Nat) (hy : ay < 2 ^ 256) (habs : ay _ ≤ ay * 2 ^ (126 - Nat.log2 ay) * 2 := Nat.mul_le_mul_right _ hbig _ = ay * 2 ^ (126 - Nat.log2 ay + 1) := by rw [pow_succ]; ring +/-- The zero magnitude takes the maximal headroom shift. -/ +theorem scaleShiftTree_zero : scaleShiftTree 0 = 127 := + (scaleShiftTree_cases 0 (by norm_num) (by unfold scaleQ67; norm_num)).1 rfl + /-- The headroom shift never exceeds `127` on supported magnitudes. -/ theorem scaleShiftTree_le_127 {y : Nat} (habs : absTree y ≤ scaleQ67) : scaleShiftTree (absTree y) ≤ 127 := by diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index a743d05ec..b4c36c3af 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -10,6 +10,7 @@ import ExpProof.Mul.Shell import ExpProof.Mul.Accum import ExpProof.Mul.XMono import ExpProof.Mul.YMono +import ExpProof.Mul.Joint /-! # `expRayToWad` and `mulExpRay` — compiled-runtime proof signpost @@ -17,9 +18,8 @@ import ExpProof.Mul.YMono This file is the at-a-glance demonstration that the documented properties hold for *the interpretation of the implementation*: the EVMYulLean execution of the compiled `ExpWrapper` Yul, `run_exp_ray_to_wad_evm` and `run_mul_exp_ray_evm` (defined in the generated `ExpYulRuntime`). -Each listed theorem is a runtime-level theorem or a runtime proof obligation; the axiom gate at the -bottom pins it to Lean's three standard axioms, so a stray `sorry` (or any new axiom) breaks the -build. +Each listed theorem is a runtime-level theorem; the axiom gate at the bottom pins it to Lean's +three standard axioms, so a stray `sorry` (or any new axiom) breaks the build. ## Documented `expRayToWad` properties (about the runtime) @@ -98,31 +98,33 @@ example (x1 x2 : Nat) /-! ## `mulExpRay` -The public spec for `mulExpRay` is a signed magnitude bracket plus monotonicity predicates in both -arguments. Discharged today, axiom-clean: - -| Property | Theorem | -|-----------------------------------------------------|-----------------------------------------| -| Exact value/panic partition of canonical calldata | `mulExpRay_value_iff_not_panic` | -| Guard word ↔ domain bridge | `valueDomain_iff_guard_eq_zero` | -| Value path returns the compiled tree | `run_mul_exp_ray_evm_eq_tree` | -| Rejected inputs revert | `run_mul_exp_ray_evm_revert` | -| Signed bracket `0 ≤ m ≤ A < m + 2` on the domain | `mulExpRay_run_bracket` | -| Sign-directed monotonicity in the exponent | `run_mul_exp_ray_evm_mono_x` | -| Monotonicity in the multiplier | `run_mul_exp_ray_evm_mono_y` | -| Result magnitude is `⌊A⌋` or `⌊A⌋ − 1` | `mulExpRay_run_floor_membership` | -| `A < 1` pins the result to zero | `mulExpRay_run_pins_zero` | -| Zero multiplier returns zero (and its bracket) | `run_mul_exp_ray_evm_zero_of_guard` | -| Scale point `mulExpRay(y, 0) = y` (and its bracket) | `run_mul_exp_ray_evm_scale_point` | -| Zero clamp at deep-negative `x` (and its bracket) | `run_mul_exp_ray_evm_clamped` | - -The bracket and the monotonicity in the exponent are proven on the whole value domain: the -scale-symbolic per-point certificates (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) -instantiate at the dynamic scale `abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`, the accumulator fold -(`Mul.Accum`) closes the live-region bracket, the unit-step induction with the scaled seam -doubling (`Mul.XMono`) closes the sign-directed exponent monotonicity, and the headroom-step -induction (`Mul.YMono`) closes the multiplier monotonicity. Still open, visible below as an -explicit hypothesis of the facade lemma: the joint runtime monotonicity statement. +Every documented `mulExpRay` property holds for the compiled runtime, axiom-clean: + +| Documented property | Theorem | +|--------------------------------------------------------|--------------------------------------| +| Signed bracket `0 ≤ m ≤ A ∧ A < m + 2` on the domain | `mulExpRay_run_bracket` | +| `m` is `⌊A⌋` or `⌊A⌋ − 1`; `A < 1` pins `m = 0` | `mulExpRay_run_floor_membership`, `mulExpRay_run_pins_zero` | +| `mulExpRay(0, x) = 0` for accepted `x` (and bracket) | `run_mul_exp_ray_evm_zero_of_guard` | +| `mulExpRay(y, 0) = y` for supported `y` (and bracket) | `run_mul_exp_ray_evm_scale_point` | +| Monotone in `x`, direction following `sign(y)` | `run_mul_exp_ray_evm_mono_x` | +| Nondecreasing in `y` at a fixed `x` | `run_mul_exp_ray_evm_mono_y` | +| Joint sign-aware monotonicity (three cases) | `run_mul_exp_ray_evm_mono_joint` | +| Reverts in exactly three cases, with the exemptions | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_octave`, `run_mul_exp_ray_evm_revert_int_min` | +| The accepted exponents need not form an interval | `MulExpRayValueDomain` (the exact accept set; its third disjunct is headroom-dependent) | + +Supporting rows: the exact value/panic partition of canonical calldata +(`mulExpRay_value_or_panic_of_canonical`), the guard word ↔ domain bridge +(`valueDomain_iff_guard_eq_zero`), the value path to the compiled tree +(`run_mul_exp_ray_evm_eq_tree`), and the zero clamp (`run_mul_exp_ray_evm_clamped`). + +The proof chain: the scale-symbolic per-point certificates +(`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) instantiate at the dynamic scale +`abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`; the accumulator fold (`Mul.Accum`) closes the live-region +bracket; the unit-step induction with the scaled seam doubling (`Mul.XMono`) closes the +sign-directed exponent monotonicity; the headroom-step induction (`Mul.YMono`) closes the +multiplier monotonicity; and the corner composition with the antitone headroom (`Mul.Joint`) +closes the joint form. Rejected inputs revert through the compiled `fun_panic` path, +instantiated at code `0x11` — `Panic(ARITHMETIC_OVERFLOW)` — in `Seam/MulRevert.lean`. -/ /-- Canonical `mulExpRay` inputs are partitioned by the implementation value and panic guards. -/ @@ -147,6 +149,37 @@ example {y1 y2 x : Nat} (h1 : MulExpRayValueDomain y1 x) (h2 : MulExpRayValueDom MulExpRayRunYMonotone y1 y2 x := run_mul_exp_ray_evm_mono_y h1 h2 hle +/-- **Sign-aware joint monotonicity on the value domain.** -/ +example {y1 y2 x1 x2 : Nat} + (h1 : MulExpRayValueDomain y1 x1) (h2 : MulExpRayValueDomain y2 x2) + (hcond : (0 ≤ FormalYul.Preservation.int256 y1 ∧ + FormalYul.Preservation.int256 y1 ≤ FormalYul.Preservation.int256 y2 ∧ + FormalYul.Preservation.int256 x1 ≤ FormalYul.Preservation.int256 x2) ∨ + (FormalYul.Preservation.int256 y1 ≤ FormalYul.Preservation.int256 y2 ∧ + FormalYul.Preservation.int256 y2 ≤ 0 ∧ + FormalYul.Preservation.int256 x2 ≤ FormalYul.Preservation.int256 x1) ∨ + (FormalYul.Preservation.int256 y1 ≤ 0 ∧ 0 ≤ FormalYul.Preservation.int256 y2)) : + MulExpRayRunJointMonotone y1 y2 x1 x2 := + run_mul_exp_ray_evm_mono_joint h1 h2 hcond + +/-- **The panic domain in the natspec's octave vocabulary**: too-large magnitude, exponent at or +beyond the unconditional fence, or a live exponent whose octave count exceeds the headroom shift +less two. -/ +example {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayPanicDomain y x ↔ + scaleQ67 < absTree y ∨ + FormalYul.Preservation.int256 mulExpRayHi ≤ FormalYul.Preservation.int256 x ∨ + (FormalYul.Preservation.int256 x ≠ 0 ∧ + FormalYul.Preservation.int256 mulExpRayZeroMax < FormalYul.Preservation.int256 x ∧ + (scaleShiftTree (absTree y) : Int) - 2 < FormalYul.Preservation.int256 (kTree x)) := + panicDomain_iff_octave hcanon + +/-- **`type(int256).min` always reverts**: its magnitude word `2^255` exceeds the maximal +scale. -/ +example {x : Nat} (hx : x < 2 ^ 256) : + run_mul_exp_ray_evm (2 ^ 255) x = .error "revert" := + run_mul_exp_ray_evm_revert_int_min hx + /-- **Floor membership.** Every accepted input's result magnitude is `⌊A⌋` or `⌊A⌋ − 1`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ @@ -165,49 +198,6 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ↔ ¬ MulExpRayPanicDomain y x := mulExpRay_value_iff_not_panic hcanon -/-- A tree equality plus a tree bracket gives the public runtime bracket spec. -/ -example {y x : Nat} - (hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x)) - (hbracket : ExpRealSpec.MulExpRayBracket - (FormalYul.Preservation.int256 y) (FormalYul.Preservation.int256 x) - (FormalYul.Preservation.int256 (mulExpTree y x))) : - MulExpRayRunBracket y x := - mulExpRay_run_bracket_of_tree hrun hbracket - -/-- A tree equality plus ordered tree results gives the public runtime monotonicity-in-`x` spec. -/ -example {y x1 x2 : Nat} - (hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1)) - (hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2)) - (hmono : ExpRealSpec.MulExpRaySignedMonotone - (FormalYul.Preservation.int256 y) (FormalYul.Preservation.int256 x1) - (FormalYul.Preservation.int256 x2) (FormalYul.Preservation.int256 (mulExpTree y x1)) - (FormalYul.Preservation.int256 (mulExpTree y x2))) : - MulExpRayRunMonotone y x1 x2 := - mulExpRay_run_monotone_of_tree hrun1 hrun2 hmono - -/-- A tree equality plus ordered tree results gives the public runtime monotonicity-in-`y` spec. -/ -example {y1 y2 x : Nat} - (hrun1 : run_mul_exp_ray_evm y1 x = .ok (mulExpTree y1 x)) - (hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x)) - (hmono : ExpRealSpec.MulExpRayYMonotone - (FormalYul.Preservation.int256 y1) (FormalYul.Preservation.int256 y2) - (FormalYul.Preservation.int256 x) (FormalYul.Preservation.int256 (mulExpTree y1 x)) - (FormalYul.Preservation.int256 (mulExpTree y2 x))) : - MulExpRayRunYMonotone y1 y2 x := - mulExpRay_run_y_monotone_of_tree hrun1 hrun2 hmono - -/-- A tree equality plus sign-aware ordered tree results gives the joint runtime spec. -/ -example {y1 y2 x1 x2 : Nat} - (hrun1 : run_mul_exp_ray_evm y1 x1 = .ok (mulExpTree y1 x1)) - (hrun2 : run_mul_exp_ray_evm y2 x2 = .ok (mulExpTree y2 x2)) - (hmono : ExpRealSpec.MulExpRayJointMonotone - (FormalYul.Preservation.int256 y1) (FormalYul.Preservation.int256 y2) - (FormalYul.Preservation.int256 x1) (FormalYul.Preservation.int256 x2) - (FormalYul.Preservation.int256 (mulExpTree y1 x1)) - (FormalYul.Preservation.int256 (mulExpTree y2 x2))) : - MulExpRayRunJointMonotone y1 y2 x1 x2 := - mulExpRay_run_joint_monotone_of_tree hrun1 hrun2 hmono - /-- Zero magnitude satisfies the signed bracket for every exponent. -/ example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := mulExpRayBracket_zero_result x @@ -334,21 +324,17 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_pins_zero -/-- info: 'ExpYul.mulExpRay_run_bracket_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ -#guard_msgs in -#print axioms mulExpRay_run_bracket_of_tree - -/-- info: 'ExpYul.mulExpRay_run_monotone_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.run_mul_exp_ray_evm_mono_joint' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms mulExpRay_run_monotone_of_tree +#print axioms run_mul_exp_ray_evm_mono_joint -/-- info: 'ExpYul.mulExpRay_run_y_monotone_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.panicDomain_iff_octave' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms mulExpRay_run_y_monotone_of_tree +#print axioms panicDomain_iff_octave -/-- info: 'ExpYul.mulExpRay_run_joint_monotone_of_tree' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.run_mul_exp_ray_evm_revert_int_min' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms mulExpRay_run_joint_monotone_of_tree +#print axioms run_mul_exp_ray_evm_revert_int_min /-- info: 'ExpYul.mulExpRay_value_or_panic_of_canonical' depends on axioms: [propext, Quot.sound] -/ #guard_msgs in From eeef5a591e80747575cfb93bbf1c0c7b869b0522 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 15:28:12 +0200 Subject: [PATCH 073/107] Document the tactic discipline over the runtime trees The generated runtime normal forms are shared DAGs whose syntactic expansion is exponential in nesting depth, so tactics whose preprocessing sends atoms through whnf (omega's atom collection, positivity, nlinarith's ring normalization) crash on tree-valued terms in scope. Record the working rule: opacify every tree-valued word with set + clear_value (or close goals with term-level lemmas) before doing arithmetic near it, establishing definition-dependent facts first. Co-Authored-By: Claude Fable 5 --- formal/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/formal/README.md b/formal/README.md index 494280af5..9c76dcf44 100644 --- a/formal/README.md +++ b/formal/README.md @@ -20,6 +20,27 @@ Machine-checked Lean 4 correctness proofs for root math libraries in 0x Settler. 3. **The `formal/yul` Lake importer** consumes `forge inspect ... ir` output and emits ignored EVMYulLean runtime/proof modules. 4. **Runtime bridge modules** execute ABI calls through EVMYulLean against the Yul emitted by solc. The implementation is Solidity; Lean proof machinery consumes the generated Yul artifacts rather than a second hand-maintained model. +## Tactic discipline over the runtime trees + +The runtime normal forms (`evTree`, `r0MulTree`, `mulShiftTree`, …) are deeply nested `evm*` +application terms whose subterms repeat: each Horner stage mentions its argument several times, +the squared argument mentions the reduced argument twice, and so on. In memory these are shared +DAGs, but any procedure that reduces or re-traverses them without sharing sees a syntactic +expansion exponential in nesting depth. Tactic preprocessing that sends atoms through `whnf` or +rebuilds them — `omega`'s atom collection, `positivity`, `nlinarith`'s ring normalization — +crashes the elaborator or kernel with a stack overflow or "deep recursion detected" when a +tree-valued term is in scope, even on goals that are trivially linear in the tree atoms. A +tree-valued `Nat` in the exponent of a `pow` fed to such a tactic fails the same way. + +The mitigation is opacification: name every tree-valued word before doing arithmetic near it — +`set w := … with hw` followed by `clear_value w` — so the atom is an opaque local with no value +to unfold, or close the goal with term-level lemmas (`lt_of_le_of_lt`, `Nat.add_le_add`, +`mul_le_mul_of_nonneg_left`, `linarith` with an explicit hypothesis list) instead of the +whnf-hungry tactics. Facts that need a tree's definition (an `rfl` unfolding, an `evmDiv`/`evmMul` +transport) must be established *before* the `clear_value`; everything downstream works on the +opaque name. The `Mul/*` modules and the scale-symbolic `Floor` lemmas follow this discipline +throughout; `omega` on opaque locals and on literals remains safe and is used freely. + ## Deriving the fixed-point rational coefficients The polynomial/rational coefficients in `Ln.sol` and `Exp.sol` (and their error margins) From ee55235509477d6300788f92c00b759f52c787e0 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 17:09:42 +0200 Subject: [PATCH 074/107] Raise the mulExpRay scale cap to the certified ceiling and pare the guard _SCALE_MAX becomes floor(2^126*10^19 / 5737291786393199862), the greatest scale at which the kernel margin dominates the over-side error image scale*delta/2^126; expRayToWad keeps its own basis through _WAD_SCALE = 10^18*2^67. At the cap the under-side envelope at two bits of closing shift stays below one output unit (deficit <= 2972/1000 with the div floor scale-independent and the proportional terms growing by at most 1005/1000). The guard reduces to three word comparisons: the magnitude cap, the positive wraparound fence phrased as one signed comparison (x > HI - 1), and the closing-shift test. Acceptance of x = 0 now requires 4*abs(y) within the cap, and exponents below the octave-wrap boundary (x < -(2^255 + 2^191)/CINV) revert or clamp to zero as the wrapped octave word falls; within the wrap-free range the accepted exponents form one interval per magnitude. Measured per call through ExpWrapper: accepting paths 850 -> 814 gas, reverting paths 507 -> 468 gas. Tests cover the new boundaries: the pin boundary on both sides, the bracket at the deepest live corner of the cap (s = 0, shift = 2), the scale-cap provenance pairing, and deterministic wrapped-octave witnesses on both sides of the wrap boundary including int256.min. Co-Authored-By: Claude Fable 5 --- src/vendor/Exp.sol | 118 +++++++++++++++++++++++------------------- test/0.8.34/Exp.t.sol | 52 ++++++++++++++++--- 2 files changed, 111 insertions(+), 59 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index c666aac07..2cfb94f70 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -8,12 +8,16 @@ import {Clz} from "./Clz.sol"; library Exp { using FastLogic for bool; - // 10¹⁸ ⋅ 2⁶⁷: the largest scale `_expRayKernel` accepts. The kernel's margin and deficit - // budgets are certified at exactly this scale (smaller scales only shrink the error terms), - // and it keeps the kernel's dividend inside 256 bits. - uint256 private constant _SCALE_MAX = 0x6f05b59d3b2000000000000000000000; + // ⌊2¹²⁶⋅10¹⁹ / 5737291786393199862⌋ ≈ 1.0048⋅10¹⁸⋅2⁶⁷: the largest scale `_expRayKernel` + // accepts. The kernel's over-side error envelope Δ (see the budget below) casts an image of + // scale⋅Δ/2¹²⁶ on the output grid; this is the greatest scale at which the margin still + // dominates that image. It also keeps the kernel's dividend inside 256 bits. + uint256 private constant _SCALE_MAX = 0x6f8d071203399a4f3617495dba31eeb1; // clz(_SCALE_MAX); must track _SCALE_MAX (paired by `testScaleMaxClzPairing`). uint256 private constant _SCALE_MAX_CLZ = 129; + // 10¹⁸ ⋅ 2⁶⁷ ≤ _SCALE_MAX: `expRayToWad`'s scale — the wad output basis carrying 67 bits of + // closing headroom. + uint256 private constant _WAD_SCALE = 0x6f05b59d3b2000000000000000000000; // The least x whose octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, i.e. // ⌈(66⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ 65.5⋅ln(2)⋅10²⁷ ≈ 45.40⋅10²⁷ (CINV is `_octave`'s // reciprocal): at `expRayToWad`'s fixed headroom s = 67 the deficit envelope reaches one @@ -25,17 +29,18 @@ library Exp { int256 private constant _WAD_ZERO_MAX = -41446531673892822312323846185; // The least x whose octave count reaches 126, i.e. ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ // 125.5⋅ln(2)⋅10²⁷ ≈ 87.00⋅10²⁷: the first octave past the deficit envelope at even the - // maximal scale headroom (s = 127, at y = 0). This comparison doubles as the fence that - // keeps accepted x clear of the region (x ≳ 2¹⁵¹) where `_octave`'s product wraps and k is - // garbage; without it, a garbage k could pass the accuracy guard and the kernel would - // return an unflagged wrong value. + // maximal scale headroom (s = 127, at y = 0). Within the wrap-free octave range the + // closing-shift guard already rejects these inputs; this comparison's irreducible role is + // the fence that keeps accepted x clear of the region (x ≳ 2¹⁵¹) where `_octave`'s product + // wraps and the octave word is garbage; without it, a wrapped word could pass the accuracy + // guard and the kernel would return an unflagged wrong value. int256 private constant _MUL_EXP_RAY_HI = 86989971160273136331862631244; // The least x whose octave count reaches -127, i.e. ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ - // -127.5⋅ln(2)⋅10²⁷ ≈ -88.38⋅10²⁷. At or below it `mulExpRay` clamps to zero, which is - // within the bracket at every supported scale (10¹⁸⋅2⁶⁷⋅exp(x/10²⁷) < 0.62); the clamp - // consults only x, so it also discards the reduction garbage for x ≲ -2¹⁵¹ where - // `_octave`'s product wraps. Above it, k ≥ -127 keeps the closing shift below 256 and the - // reduced argument on the certified domain. + // -127.5⋅ln(2)⋅10²⁷ ≈ -88.38⋅10²⁷. At or below it the kernel clamps `mulExpRay` to zero, + // which is within the bracket at every supported scale (_SCALE_MAX⋅exp(x/10²⁷) < 0.63); the + // clamp consults only x, so it also zeroes every accepted x inside `_octave`'s negative + // wraparound region (x ≲ -2¹⁵²). Above it, k ≥ -127 keeps the closing shift below 256 and + // the reduced argument on the certified domain. int256 private constant _MUL_EXP_RAY_ZERO_MAX = -88376265521393026950697095485; /// @notice Compute the natural exponential of a fixnum with 10**27 (ray) basis, returning the @@ -56,30 +61,33 @@ library Exp { int256 k = _octave(x); unchecked { - return int256(_expRayKernel(x, k, _SCALE_MAX, uint256(int256(67) - k), _WAD_ZERO_MAX)); + return int256(_expRayKernel(x, k, _WAD_SCALE, uint256(int256(67) - k), _WAD_ZERO_MAX)); } } /// @notice Compute y * exp(x / 10**27), with y's sign reapplied after magnitude evaluation. /// @dev Let A = abs(y) ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, except that when - /// A < 1 the lower bound pins m = 0. `mulExpRay(0, x) == 0` for every accepted x and - /// `mulExpRay(y, 0) == y` for every supported y. Among accepted inputs, the result is + /// A < 1 the lower bound pins m = 0. `mulExpRay(0, x) == 0` for every accepted x, and + /// `mulExpRay(y, 0) == y` exactly whenever 4⋅abs(y) ≤ + /// 148276564793151315913207305475055546033 (larger magnitudes leave fewer than two bits + /// of closing shift, so x = 0 reverts there). Among accepted inputs, the result is /// monotone in x: nondecreasing if y ≥ 0 and nonincreasing if y < 0. For a fixed x, /// among accepted inputs, the result is nondecreasing in y. Jointly, for accepted pairs /// (y₁, x₁) and (y₂, x₂), the first result is no greater than the second when 0 ≤ y₁ ≤ y₂ /// and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. /// - /// Reverts with `Panic(17)` in exactly three cases: abs(y) > 10¹⁸⋅2⁶⁷ (including + /// Reverts with `Panic(17)` in exactly three cases: + /// abs(y) > 148276564793151315913207305475055546033 ≈ 1.48⋅10³⁸ (including /// y = type(int256).min); x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ (regardless of - /// y); or x and abs(y) jointly exhaust the accuracy envelope: with 2ˢ the scale headroom - /// above abs(y) (the largest power of two with abs(y)⋅2ˢ ≤ 10¹⁸⋅2⁶⁷; s = 127 at y = 0), - /// any x whose octave count k = round(x / (10²⁷⋅ln(2))) exceeds s - 2 reverts, except - /// x = 0 (returned exactly at any headroom) and x ≤ -88376265521393026950697095485 ≈ - /// -88.38⋅10²⁷ (clamped to zero at any headroom). Because the headroom shrinks as abs(y) - /// grows, the accepted exponents need not form an interval: at the largest magnitudes, - /// x = 0 is accepted while every other x > -1.5⋅ln(2)⋅10²⁷ reverts, and sufficiently - /// negative x are accepted again. + /// y); or the octave word — `_octave`'s output, which is round(x / (10²⁷⋅ln(2))) wherever + /// its product does not wrap (|x| ≲ 2¹⁵²) — exceeding s - 2, with 2ˢ the scale headroom + /// above abs(y) (the largest power of two with abs(y)⋅2ˢ within the magnitude bound; + /// s = 127 at y = 0). Within the wrap-free range the accepted exponents form one + /// interval that narrows as abs(y) grows, and every accepted + /// x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap + /// boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to + /// zero, either of which is sound (A < 1 there at every supported magnitude). function mulExpRay(int256 y, int256 x) internal pure returns (int256) { uint256 ay; uint256 sign; @@ -111,14 +119,16 @@ library Exp { // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: // - abs(y) above the maximal scale; // - x at or above the octave (k = 126) that exhausts the deficit envelope at even - // the maximal headroom; this comparison also fences accepted x away from - // `_octave`'s wraparound region (see `_MUL_EXP_RAY_HI`); - // - a live x — neither pinned (x = 0, exact at any headroom) nor clamped (at or - // below the zero cutoff, where the result is zero without consulting k, keeping - // deep-negative x with a wrapped octave product accepted) — leaving fewer than two - // bits of closing shift: the deficit envelope (2993/1000 + margin)⋅2ᵏ⁻ˢ reaches - // one output unit at k > s - 2 (see the kernel). - if ((ay > _SCALE_MAX).or(x >= _MUL_EXP_RAY_HI).or((x != 0).and(x > _MUL_EXP_RAY_ZERO_MAX).and(shift < 2))) { + // the maximal headroom, phrased as one signed comparison against the constant + // less one; its irreducible role is fencing accepted x away from `_octave`'s + // positive wraparound (see `_MUL_EXP_RAY_HI`); + // - fewer than two bits of closing shift: the deficit envelope + // (2972/1000 + margin)⋅2ᵏ⁻ˢ reaches one output unit at k > s - 2 (see the + // kernel). This also rejects x = 0 when abs(y) leaves s ≤ 1, although the pinned + // result would be exact. When `_octave`'s product wraps (x ≲ -2¹⁵²) its output + // stands in for k, so those exponents revert or pass as the wrapped word falls; + // the kernel's clamp zeroes every accepted one. + if ((ay > _SCALE_MAX).or(x > _MUL_EXP_RAY_HI - 1).or(shift < 2)) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } @@ -161,8 +171,8 @@ library Exp { /// @dev The rational polynomial approximation kernel, shared by `expRayToWad` /// (scale = 10¹⁸⋅2⁶⁷, shift = 67 - k) and `mulExpRay` (scale = abs(y)⋅2ˢ, shift = s - k). /// The caller must maintain: - /// - `k == _octave(x)` and `scale ≤ 10¹⁸⋅2⁶⁷`: the margin and deficit budgets below are - /// certified at exactly the maximal scale, and smaller scales only shrink them; + /// - `k == _octave(x)` and `scale ≤ _SCALE_MAX`: the margin and deficit budgets below + /// are certified at exactly that cap, and smaller scales only shrink them; /// - `scale == base << s` for the caller's magnitude base, with `shift == s - k`; /// - for every accepted x with `zeroCutoff` < x and x ≠ 0: `shift ≥ 2` (the deficit /// envelope reaches one output unit below that), `_octave`'s product must not wrap @@ -208,7 +218,7 @@ library Exp { // product stays inside 256 bits // dividend: Q156 the widest basis that fits in 256 bits before the single truncating // `DIV` by Q89 divisor. < 2¹²⁹ - // r: the pre-scale is at most 10¹⁸⋅2⁶⁷ < 2¹²⁷ to avoid overflowing the dividend. + // r: the pre-scale is at most _SCALE_MAX < 2¹²⁷ to avoid overflowing the dividend. // output: the closing `shr(shift, …)` is the output-rounding floor, with the 2ᵏ octave // scaling folded into the caller's scale/shift pair. // @@ -235,21 +245,23 @@ library Exp { // grid term below 2⁻²²⁸), lifting ê by ≤ 0.0055242717280199026 (≈ √2/256). // // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid unit - // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale ≤ 10¹⁸⋅2⁶⁷, Δ's - // image is below one grid unit: the Q89 closing bases confine the over-side jitter so that - // 5¹⁸⋅Δ/2⁴¹ ≤ 0.99527 < 1. The margin is the least integer that dominates the image: 0x01, - // worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so the - // pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is certified - // directly on the output grid, piecewise over the 32 domain pieces (per-piece denominator - // floors confine the truncation amplification): q ≥ scale⋅exp(t) - 2993/1000, where - // 2993/1000 bounds, on each sign half, the sum of the integer-rational deficit together - // with the `DIV` floor (≤ 2378/1000, certified piecewise), the `Mp` factor (≤ 2/25, via ê ≤ - // 1.45), the under-direction reduced-argument gap (≤ 307/1000 on the t > 0 half via exp(t) - // ≤ √2; ≤ 218/1000 on the other, where exp(t) ≤ 1 + ε), and the under-direction argument - // granularity (≤ 143/500: the one-grain envelope with the negative-half denominator floor; - // free on the t > 0 half). + // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). The scale cap is exactly + // ⌊2¹²⁶/Δ⌋ in Q126 units (its defining property), so Δ's image on the grid, scale⋅Δ/2¹²⁶, + // never exceeds one grid unit. The margin is the least integer that dominates the image: + // 0x01, worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so + // the pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is + // certified directly on the output grid, piecewise over the 32 domain pieces (per-piece + // denominator floors confine the truncation amplification): q ≥ scale⋅exp(t) - 2972/1000. + // The `DIV` floor costs one unit at any scale; the remaining, scale-proportional deficits + // are certified at 10¹⁸⋅2⁶⁷ — integer-rational ≤ 1378/1000, the `Mp` factor ≤ 2/25 (via + // ê ≤ 1.45), the under-direction reduced-argument gap ≤ 307/1000 on the t > 0 half (via + // exp(t) ≤ √2; ≤ 218/1000 on the other, where exp(t) ≤ 1 + ε), and the under-direction + // argument granularity ≤ 143/500 (the one-grain envelope with the negative-half + // denominator floor; free on the t > 0 half) — and grow by at most + // scale/(10¹⁸⋅2⁶⁷) ≤ 1005/1000 at the cap, keeping each half's proportional total within + // 1972/1000. // - // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2993/1000 + margin)⋅2ᵏ⁻ˢ. The caller + // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2972/1000 + margin)⋅2ᵏ⁻ˢ. The caller // keeps k ≤ s - 2, where this is < 1, so the floor returns ⌊E⌋ or ⌊E⌋ - 1. For the wad // specialization s = 67, the deficit envelope exceeds 1ulp at k ≥ 66. On the central octave // k = 0, the margin is 2⁻⁶⁷ ≈ 6.8⋅10⁻²¹ ulp, far below the ≈10⁻⁹ ulp gap `lnWadToRay` @@ -258,8 +270,8 @@ library Exp { // // Monotonicity: one unit step in x multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves the // pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live - // scale exceeds 10¹⁸⋅2⁶⁶: the maximal headroom leaves scale > 10¹⁸⋅2⁶⁷/2). The error - // terms above confine the accumulator to a band of width 5¹⁸⋅Δ/2⁴¹ + 2993/1000 ≈ 4.0 grid + // scale exceeds _SCALE_MAX/2 > 10¹⁸⋅2⁶⁶). The error + // terms above confine the accumulator to a band of width scale⋅Δ/2¹²⁶ + 2972/1000 ≈ 4.0 grid // units just below E's grid image at every octave (in grid units the band is k-independent; // an octave seam rescales E and the band together), so the per-step gain exceeds any // adverse swing within the band by more than 9 orders of magnitude, and the pre-floor @@ -306,7 +318,7 @@ library Exp { // both positive. let tod := sar(0x81, mul(t, od)) - // The scaled rational: the caller keeps scale ≤ 10¹⁸⋅2⁶⁷, so one `DIV` scales, widens, + // The scaled rational: the caller keeps scale ≤ _SCALE_MAX, so one `DIV` scales, widens, // and floors at once. The numerator stays below 2¹²⁹ and scale < 2¹²⁷, so the // dividend stays inside 256 bits; the denominator > 0. r := div(mul(scale, add(ev, tod)), sub(ev, tod)) diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index 29866172c..b3f3772ef 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -7,7 +7,9 @@ import {Clz} from "src/vendor/Clz.sol"; import {Test, stdError} from "@forge-std/Test.sol"; contract ExpTest is Test { - uint256 private constant _SCALE_MAX = 0x6f05b59d3b2000000000000000000000; + // Mirrors Exp._SCALE_MAX: floor(2**126 * 1e19 / 5737291786393199862), the over-side + // certification ceiling of the kernel. + uint256 private constant _SCALE_MAX = 0x6f8d071203399a4f3617495dba31eeb1; // First input whose octave count exceeds the supported range; `expRayToWad` reverts here. int256 private constant _TOO_BIG = 0x92b2f16cc66c5a4ae96e80d4; // First input whose octave count reaches 125: the accuracy-guard boundary at the deepest @@ -208,11 +210,46 @@ contract ExpTest is Test { } } - function testMulExpRayScalePoint() external pure { + /// x = 0 is pinned exactly wherever it is accepted: acceptance needs two bits of closing + /// shift, i.e. 4*abs(y) <= _SCALE_MAX. One unit of magnitude past that boundary reverts. + function testMulExpRayScalePoint() external { assertEq(Exp.mulExpRay(1, 0), 1, "one"); assertEq(Exp.mulExpRay(-1, 0), -1, "minus one"); - assertEq(Exp.mulExpRay(int256(_SCALE_MAX), 0), int256(_SCALE_MAX), "scale max"); - assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), 0), -int256(_SCALE_MAX), "negative scale max"); + int256 pinMax = int256(_SCALE_MAX >> 2); + assertEq(Exp.mulExpRay(pinMax, 0), pinMax, "deepest pinned magnitude"); + assertEq(Exp.mulExpRay(-pinMax, 0), -pinMax, "negative mirror"); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(pinMax + 1, 0); + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(-(pinMax + 1), 0); + } + + /// The deepest live corner at the scale cap: abs(y) = _SCALE_MAX (s = 0) at the first x of + /// octave k = -2, where the closing shift is exactly 2. The two-unit bracket must hold here. + function testMulExpRayScaleCapLive() external pure { + int256 x = -1732867951399863273543080303; // _octaveStart(-2) + int256 floorA = 26211841114070945982531467099595678267; + int256 r = Exp.mulExpRay(int256(_SCALE_MAX), x); + assertLe(r, floorA, "overestimates"); + assertGe(r, floorA - 1, "below floor minus one"); + } + + /// Below the octave-wrap boundary (x < -(2**255 + 2**191)/CINV ~ -5.7e45) the wrapped octave + /// word decides between revert and the zero clamp; either is within the bracket (A < 1 at + /// every supported magnitude). One deterministic witness each way, plus the boundary pair. + function testMulExpRayWrappedOctave() external { + // 2**191 + CINV*x wraps to exactly zero: octave word 0, closing shift 67, clamps. + assertEq( + Exp.mulExpRay(1e18, -57402104550644550183762763389232637323199440519166886170539266728770553249792), + 0, + "wrapped word 0 clamps" + ); + assertEq(Exp.mulExpRay(1e18, type(int256).min), 0, "int256.min clamps"); + // The deepest wrap-free x: octave word -2**63, closing shift far above 2, clamps. + assertEq(Exp.mulExpRay(1e18, -6393154322601327830240888940151524429370348050), 0, "deepest wrap-free x clamps"); + // One below it the product wraps positive (octave word 2**63 - 1) and the guard fires. + vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(1e18, -6393154322601327830240888940151524429370348051); } /// A zero multiplier takes the same guard as every other y: any x below the k = 126 fence is @@ -230,10 +267,13 @@ contract ExpTest is Test { this.mulExpRayExternal(0, type(int256).max); } - /// `_SCALE_MAX_CLZ` inside the library must track `_SCALE_MAX`. + /// `_SCALE_MAX_CLZ` inside the library must track `_SCALE_MAX`, and `_SCALE_MAX` must be the + /// over-side certification ceiling floor(2**126 / Delta) with Delta = 5737291786393199862/1e19, + /// the kernel's Q126 error envelope. The wad scale must sit within the cap. function testScaleMaxClzPairing() external pure { - assertEq(_SCALE_MAX, uint256(1e18) << 67, "scale is the wad unit at 67 bits of headroom"); + assertEq(_SCALE_MAX, ((uint256(1) << 126) * 1e19) / 5737291786393199862, "scale cap is floor(2^126 / Delta)"); assertEq(Clz.clz(_SCALE_MAX), 129, "_SCALE_MAX_CLZ"); + assertLe(uint256(1e18) << 67, _SCALE_MAX, "wad scale within the cap"); } function testMulExpRayLowerZero() external pure { From ea11fdd5ac8f1f216455af8b7e9df6b7d59fb952 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 22:04:50 +0200 Subject: [PATCH 075/107] Strengthen agent decision discipline Co-Authored-By: OpenAI Codex --- AGENTS.md | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 74b092fcd..af378eb81 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -439,21 +439,52 @@ normative source merely because it is present in the repository. ### Decision-Making Discipline -Agents must not make judgment calls or architectural decisions. Whenever a -juncture calls for professional judgment, taste, external context, or -real-world experience — or whenever no option is clearly superior on technical -merits alone — stop and present every viable option to the user, with the pros -and cons of each clearly spelled out, and ask the user to decide the correct -way forward. An agent may choose on its own only when the correct choice is -obvious and unambiguous from the information available to it. +Agents are FORBIDDEN from making decisions. This prohibition is absolute. It +is not limited to "judgment calls" or "architectural decisions"; each of the +following IS a decision and is therefore forbidden: + +- selecting which of several viable approaches to pursue, implement, or + present first; +- declaring any approach "the route", "the right way", "the fix", "not + viable", "not worth it", "impractical", or any equivalent phrasing, however + hedged; +- ruling an option out, ranking options, or presenting one option as primary + and the others as asides; +- narrowing the option space before presenting it — an option omitted is an + option decided against; +- choosing a constant, bound, tolerance, naming, or specification change from + among several defensible values; +- concluding that a goal is infeasible, or that a line of inquiry has been + explored enough to stop. + +Whenever work arrives at a fork — anywhere professional judgment, taste, +external context, or real-world experience would inform the choice, or +wherever no option is clearly superior on technical merits alone — the agent +MUST stop and present every viable option to the user, with the pros, cons, +costs, and quantified evidence for each spelled out, and MUST ask the user to +decide the way forward. Options the agent believes difficult, expensive, or +unpromising MUST appear alongside the rest with the evidence for that belief +stated quantitatively; difficulty is a fact to report, never a license to +omit or pre-select. A recommendation never substitutes for the full option +set. If a sentence being drafted asserts which option will be taken, stop: +that sentence is the user's to write. + +An agent may proceed without asking only when the correct choice is obvious +and unambiguous from the information available to it — meaning a reasonable +expert could not disagree. "Probably best", "clearly preferable", and +"standard practice" do not meet this bar. When in doubt, it is a decision: +stop and present. Do not spend effort cataloging the reasons a task is too daunting, too difficult, or too lengthy to complete. Spend that effort instead on determining concretely why the task *can* be completed: identify the specific techniques, tools, or enhancements that can be brought to bear to make it more tractable. -When faced with a choice among options where one or more appears substantially -more difficult for only marginal benefit, do not silently take the easier path; -present the trade-off to the user and let the user choose. +Declaring a goal infeasible is itself a decision reserved to the user: the +agent's role is to report what was tried, what was measured, and which +concrete avenues remain open, and then let the user direct. When faced with a +choice among options where one or more appears substantially more difficult +for only marginal benefit, do not silently take the easier path; present the +trade-off to the user and let the user choose. When reasoning about how difficult or feasible a line of inquiry is, do not rely on assumptions drawn from past experience or general priors. Root every From 2b35f9aa3585737e48ac5448467bbe21d9fdfb80 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 22:38:10 +0200 Subject: [PATCH 076/107] Add extensible polynomial certificate backends Co-Authored-By: OpenAI Codex --- formal/common/Common.lean | 12 +- formal/common/Common/CertificateExamples.lean | 51 +++++ .../common/Common/Foundation/Bernstein.lean | 204 ++++++++++++++++++ .../Common/Foundation/KroneckerShift.lean | 11 +- formal/common/Common/Foundation/Poly.lean | 42 ++++ formal/common/Common/GenBernstein.lean | 123 +++++++++++ formal/common/Common/GenCover.lean | 110 ++++++++++ 7 files changed, 546 insertions(+), 7 deletions(-) create mode 100644 formal/common/Common/CertificateExamples.lean create mode 100644 formal/common/Common/Foundation/Bernstein.lean create mode 100644 formal/common/Common/GenBernstein.lean diff --git a/formal/common/Common.lean b/formal/common/Common.lean index 3ec55faab..0f81f2dbb 100644 --- a/formal/common/Common.lean +++ b/formal/common/Common.lean @@ -1,17 +1,21 @@ -- This module serves as the root of the `Common` library: the shared, -- function-agnostic Lean machinery used by the per-function Yul correctness -- proofs (`LnProof`, `ExpProof`). Nothing here models any specific --- implementation. It is generic interval-Horner nonnegativity certificates and --- Kronecker identity-testing / packed-shift cell walks (`Common.Poly`), the +-- implementation. It is generic interval-Horner and Bernstein nonnegativity +-- certificates and Kronecker identity-testing / packed-shift cell walks +-- (`Common.Poly`), the -- `e^(p/q)` Taylor-cut framework (`Common.Exp`), the `Real.exp` bridge for the -- partial-sum caps (`Common.RealExpBridge`), the EVM-word op-preservation --- bridges (`Common.Word`), and the cover-certificate generator string/IO helpers the --- `lake env lean Gen*.lean` scripts share (`Common.GenCover`). +-- bridges (`Common.Word`), and the certificate generator string/IO helpers the +-- `lake env lean Gen*.lean` scripts share. import Common.Word import Common.Foundation.Poly import Common.Foundation.ExpSum import Common.Foundation.ShiftCert import Common.Foundation.Kronecker import Common.Foundation.KroneckerShift +import Common.Foundation.Bernstein import Common.Seam.RealExpBridge import Common.GenCover +import Common.GenBernstein +import Common.CertificateExamples diff --git a/formal/common/Common/CertificateExamples.lean b/formal/common/Common/CertificateExamples.lean new file mode 100644 index 000000000..81dd13aec --- /dev/null +++ b/formal/common/Common/CertificateExamples.lean @@ -0,0 +1,51 @@ +import Common.GenBernstein + +namespace Common.CertificateExamples + +open Common.Poly Common.GenCover Common.GenBernstein + +set_option maxRecDepth 100000 + +def nonnegativeQuadratic : List Int := [1, 0, 1] +def nonnegativeQuadraticWeights : List Int := [1, 2, 101] + +theorem quadraticCoverKCheck : + checkCoverK kB nonnegativeQuadratic 0 10 [10] = true := by + decide +kernel + +theorem quadraticBernsteinCheck : + checkBernsteinKWithWitness 9 nonnegativeQuadratic 0 10 + nonnegativeQuadraticWeights = true := by + decide +kernel + +theorem quadraticComputedBernsteinCheck : + checkBernsteinK 9 nonnegativeQuadratic 0 10 = true := by + decide +kernel + +theorem quadraticCoverKNonneg : NonnegOn nonnegativeQuadratic 0 10 := + checkCoverK_nonnegOn kB nonnegativeQuadratic [10] 0 10 quadraticCoverKCheck + +theorem quadraticBernsteinNonneg : NonnegOn nonnegativeQuadratic 0 10 := + checkBernsteinKWithWitness_nonnegOn 9 nonnegativeQuadratic 0 10 + nonnegativeQuadraticWeights quadraticBernsteinCheck + +theorem quadraticMixedPartitionNonneg : NonnegOn nonnegativeQuadratic 0 10 := by + exact NonnegOn.union + (NonnegOn.restrict quadraticCoverKNonneg (by omega) (by omega : (4 : Int) ≤ 10)) + (NonnegOn.restrict quadraticBernsteinNonneg (by omega : (0 : Int) ≤ 5) (by omega)) + +theorem malformedBernsteinWitness : + checkBernsteinKWithWitness 9 nonnegativeQuadratic 0 10 [] = false := by + decide +kernel + +theorem malformedBernsteinInterval : + checkBernsteinKWithWitness 9 nonnegativeQuadratic 10 0 + nonnegativeQuadraticWeights = false := by + decide +kernel + +theorem insufficientBernsteinIdentityWidth : + checkBernsteinKWithWitness 8 nonnegativeQuadratic 0 10 + nonnegativeQuadraticWeights = false := by + decide +kernel + +end Common.CertificateExamples diff --git a/formal/common/Common/Foundation/Bernstein.lean b/formal/common/Common/Foundation/Bernstein.lean new file mode 100644 index 000000000..7b071ed7b --- /dev/null +++ b/formal/common/Common/Foundation/Bernstein.lean @@ -0,0 +1,204 @@ +import Mathlib.Tactic.Linarith +import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Ring +import Common.Foundation.KroneckerShift + +/-! +# Bernstein polynomial nonnegativity certificates + +The checker computes integer Bernstein weights for a polynomial on a closed +interval. Nonnegative weights give a nonnegative weighted-power expansion. +The expansion identity is checked at a Kronecker point under explicit +coefficient bounds, so the computed weights are not trusted. +-/ + +namespace Common.Poly + +def bernsteinTermPoly (a b : Int) (n i : Nat) : List Int := + polyMul (polyPow [-a, 1] i) (polyPow [b, -1] (n - i)) + +def bernsteinCertPoly (a b : Int) (n i : Nat) : List Int → List Int + | [] => [] + | d :: ds => + polyAdd (polyScale d (bernsteinTermPoly a b n i)) + (bernsteinCertPoly a b n (i + 1) ds) + +theorem eval_bernsteinTermPoly (a b t : Int) (n i : Nat) : + evalPoly (bernsteinTermPoly a b n i) t = + (t - a) ^ i * (b - t) ^ (n - i) := by + unfold bernsteinTermPoly + rw [evalPoly_polyMul, evalPoly_polyPow, evalPoly_polyPow] + simp only [evalPoly] + ring + +theorem eval_bernsteinCertPoly_nonneg (a b t : Int) (n i : Nat) : + ∀ ds : List Int, (∀ d ∈ ds, 0 ≤ d) → a ≤ t → t ≤ b → + 0 ≤ evalPoly (bernsteinCertPoly a b n i ds) t := by + intro ds + induction ds generalizing i with + | nil => + intro _ _ _ + simp [bernsteinCertPoly, evalPoly] + | cons d ds ih => + intro hds hat htb + have hd : 0 ≤ d := hds d (by simp) + have htail : ∀ z ∈ ds, 0 ≤ z := by + intro z hz + exact hds z (by simp [hz]) + have hx : 0 ≤ t - a := by omega + have hy : 0 ≤ b - t := by omega + have hterm : 0 ≤ evalPoly (bernsteinTermPoly a b n i) t := by + rw [eval_bernsteinTermPoly] + positivity + have hrest := ih (i := i + 1) htail hat htb + simp only [bernsteinCertPoly, evalPoly_polyAdd, evalPoly_polyScale] + positivity + +theorem nonnegOn_of_bernsteinCertificate (C ds : List Int) (a b : Int) (n : Nat) + (hab : a < b) + (hidentity : polyScale ((b - a) ^ n) C = bernsteinCertPoly a b n 0 ds) + (hweights : ∀ d ∈ ds, 0 ≤ d) : NonnegOn C a b := by + intro t hat htb + have hcert := eval_bernsteinCertPoly_nonneg a b t n 0 ds hweights hat htb + have heval := congrArg (fun P => evalPoly P t) hidentity + change evalPoly (polyScale ((b - a) ^ n) C) t = + evalPoly (bernsteinCertPoly a b n 0 ds) t at heval + rw [evalPoly_polyScale] at heval + have hw : 0 < (b - a) ^ n := by + have : 0 < b - a := by omega + positivity + nlinarith + +def scaleVariableAux (w : Int) : Nat → List Int → List Int + | _, [] => [] + | i, c :: cs => c * w ^ i :: scaleVariableAux w (i + 1) cs + +def scaleVariable (w : Int) (C : List Int) : List Int := + scaleVariableAux w 0 C + +def bernsteinWeight (q : List Int) (n i : Nat) : Int := + (List.range (i + 1)).foldl + (fun z j => z + q.getD j 0 * (Nat.choose (n - j) (i - j) : Int)) 0 + +/-- Candidate integer weights computed from the packed Taylor shift. -/ +def bernsteinWitness (C : List Int) (a b : Int) : List Int := + let n := C.length - 1 + let q := scaleVariable (b - a) (kShiftWitness kB C a) + (List.range C.length).map (bernsteinWeight q n) + +def bernsteinCertEval (a b x : Int) (n i : Nat) : List Int → Int + | [] => 0 + | d :: ds => + d * (x - a) ^ i * (b - x) ^ (n - i) + + bernsteinCertEval a b x n (i + 1) ds + +theorem eval_bernsteinCertPoly (a b x : Int) (n i : Nat) : ∀ ds : List Int, + evalPoly (bernsteinCertPoly a b n i ds) x = + bernsteinCertEval a b x n i ds := by + intro ds + induction ds generalizing i with + | nil => simp [bernsteinCertPoly, bernsteinCertEval, evalPoly] + | cons d ds ih => + simp only [bernsteinCertPoly, bernsteinCertEval, evalPoly_polyAdd, + evalPoly_polyScale, eval_bernsteinTermPoly, ih] + ring + +def bernsteinCertL1 (a b : Int) (n i : Nat) : List Int → Nat + | [] => 0 + | d :: ds => + d.natAbs * (a.natAbs + 1) ^ i * (b.natAbs + 1) ^ (n - i) + + bernsteinCertL1 a b n (i + 1) ds + +theorem polyL1_bernsteinTermPoly_le (a b : Int) (n i : Nat) : + polyL1 (bernsteinTermPoly a b n i) ≤ + (a.natAbs + 1) ^ i * (b.natAbs + 1) ^ (n - i) := by + unfold bernsteinTermPoly + have hm := polyL1_polyMul (polyPow [-a, 1] i) (polyPow [b, -1] (n - i)) + have hp := polyL1_polyPow [-a, 1] i + have hq := polyL1_polyPow [b, -1] (n - i) + have ha : polyL1 ([-a, 1] : List Int) = a.natAbs + 1 := by + simp [polyL1] + have hb : polyL1 ([b, -1] : List Int) = b.natAbs + 1 := by + simp [polyL1] + rw [ha] at hp + rw [hb] at hq + exact le_trans hm (Nat.mul_le_mul hp hq) + +theorem polyL1_bernsteinCertPoly_le (a b : Int) (n i : Nat) : ∀ ds : List Int, + polyL1 (bernsteinCertPoly a b n i ds) ≤ bernsteinCertL1 a b n i ds := by + intro ds + induction ds generalizing i with + | nil => simp [bernsteinCertPoly, bernsteinCertL1, polyL1] + | cons d ds ih => + simp only [bernsteinCertPoly, bernsteinCertL1] + have hadd := polyL1_polyAdd (polyScale d (bernsteinTermPoly a b n i)) + (bernsteinCertPoly a b n (i + 1) ds) + have hscale := polyL1_polyScale d (bernsteinTermPoly a b n i) + have hterm := polyL1_bernsteinTermPoly_le a b n i + have hrest := ih (i := i + 1) + have hscaled : polyL1 (polyScale d (bernsteinTermPoly a b n i)) ≤ + d.natAbs * ((a.natAbs + 1) ^ i * (b.natAbs + 1) ^ (n - i)) := + le_trans hscale (Nat.mul_le_mul_left _ hterm) + calc + polyL1 (polyAdd (polyScale d (bernsteinTermPoly a b n i)) + (bernsteinCertPoly a b n (i + 1) ds)) + ≤ polyL1 (polyScale d (bernsteinTermPoly a b n i)) + + polyL1 (bernsteinCertPoly a b n (i + 1) ds) := hadd + _ ≤ d.natAbs * ((a.natAbs + 1) ^ i * (b.natAbs + 1) ^ (n - i)) + + bernsteinCertL1 a b n (i + 1) ds := Nat.add_le_add hscaled hrest + _ = d.natAbs * (a.natAbs + 1) ^ i * (b.natAbs + 1) ^ (n - i) + + bernsteinCertL1 a b n (i + 1) ds := by rw [Nat.mul_assoc] + +/-- Exact checker with an explicit witness, used to validate generated weights. -/ +def checkBernsteinKWithWitness + (B : Nat) (C : List Int) (a b : Int) (ds : List Int) : Bool := + let n := C.length - 1 + decide (a < b) && + decide (∀ d ∈ ds, 0 ≤ d) && + decide (polyL1 (polyScale ((b - a) ^ n) C) * 2 < 2 ^ B) && + decide (bernsteinCertL1 a b n 0 ds * 2 < 2 ^ B) && + decide (evalPoly (polyScale ((b - a) ^ n) C) (((2 ^ B : Nat) : Int)) = + bernsteinCertEval a b (((2 ^ B : Nat) : Int)) n 0 ds) + +def checkBernsteinK (B : Nat) (C : List Int) (a b : Int) : Bool := + checkBernsteinKWithWitness B C a b (bernsteinWitness C a b) + +theorem checkBernsteinKWithWitness_nonnegOn + (B : Nat) (C : List Int) (a b : Int) (ds : List Int) + (hcheck : checkBernsteinKWithWitness B C a b ds = true) : NonnegOn C a b := by + simp only [checkBernsteinKWithWitness, Bool.and_eq_true, decide_eq_true_eq] at hcheck + rcases hcheck with ⟨⟨⟨⟨hab, hweights⟩, hpL1⟩, hcertL1⟩, hevalPoint⟩ + intro t hat htb + let n := C.length - 1 + have hcert := eval_bernsteinCertPoly_nonneg a b t n 0 ds hweights hat htb + have hqL1 : polyL1 (bernsteinCertPoly a b n 0 ds) * 2 < 2 ^ B := by + have hbound := polyL1_bernsteinCertPoly_le a b n 0 ds + exact lt_of_le_of_lt (Nat.mul_le_mul_right 2 hbound) hcertL1 + have heval : evalPoly (polyScale ((b - a) ^ n) C) ((2 : Int) ^ B) = + evalPoly (bernsteinCertPoly a b n 0 ds) ((2 : Int) ^ B) := by + rw [pow2_cast, eval_bernsteinCertPoly] + exact hevalPoint + have hevery := evalPoly_ext (B := B) (polyScale ((b - a) ^ n) C) + (bernsteinCertPoly a b n 0 ds) hpL1 hqL1 heval t + rw [evalPoly_polyScale] at hevery + have hw : 0 < (b - a) ^ n := by + have : 0 < b - a := by omega + positivity + nlinarith + +theorem checkBernsteinK_nonnegOn (B : Nat) (C : List Int) (a b : Int) + (hcheck : checkBernsteinK B C a b = true) : NonnegOn C a b := by + exact checkBernsteinKWithWitness_nonnegOn B C a b (bernsteinWitness C a b) hcheck + +theorem checkBernsteinKWithWitness_sound + (B : Nat) (C : List Int) (a b : Int) (ds : List Int) + (hcheck : checkBernsteinKWithWitness B C a b ds = true) : + ∀ t : Int, a ≤ t → t ≤ b → 0 ≤ evalPoly C t := by + exact checkBernsteinKWithWitness_nonnegOn B C a b ds hcheck + +theorem checkBernsteinK_sound (B : Nat) (C : List Int) (a b : Int) + (_hab : a < b) (hcheck : checkBernsteinK B C a b = true) : + ∀ t : Int, a ≤ t → t ≤ b → 0 ≤ evalPoly C t := by + exact checkBernsteinK_nonnegOn B C a b hcheck + +end Common.Poly diff --git a/formal/common/Common/Foundation/KroneckerShift.lean b/formal/common/Common/Foundation/KroneckerShift.lean index c17d23410..5d6d68cc4 100644 --- a/formal/common/Common/Foundation/KroneckerShift.lean +++ b/formal/common/Common/Foundation/KroneckerShift.lean @@ -256,9 +256,8 @@ def checkCoverK (B : Nat) (C : List Int) (lo hi : Int) : List Int → Bool decide (0 ≤ (hornerIv S 0 w).1) && checkCoverK B C (lo + w + 1) hi ws -theorem checkCoverK_sound (B : Nat) (C : List Int) (ws : List Int) : - ∀ lo hi : Int, checkCoverK B C lo hi ws = true → - ∀ x : Int, lo ≤ x → x ≤ hi → 0 ≤ evalPoly C x := by +theorem checkCoverK_nonnegOn (B : Nat) (C : List Int) (ws : List Int) : + ∀ lo hi : Int, checkCoverK B C lo hi ws = true → NonnegOn C lo hi := by induction ws with | nil => intro lo hi h x h1 h2 @@ -285,4 +284,10 @@ theorem checkCoverK_sound (B : Nat) (C : List Int) (ws : List Int) : rw [show lo + (x - lo) = x by omega] at hx omega +theorem checkCoverK_sound (B : Nat) (C : List Int) (ws : List Int) : + ∀ lo hi : Int, checkCoverK B C lo hi ws = true → + ∀ x : Int, lo ≤ x → x ≤ hi → 0 ≤ evalPoly C x := by + intro lo hi h + exact checkCoverK_nonnegOn B C ws lo hi h + end Common.Poly diff --git a/formal/common/Common/Foundation/Poly.lean b/formal/common/Common/Foundation/Poly.lean index 721f2ab5c..73b61e694 100644 --- a/formal/common/Common/Foundation/Poly.lean +++ b/formal/common/Common/Foundation/Poly.lean @@ -35,6 +35,48 @@ def evalPoly : List Int → Int → Int | [], _ => 0 | c :: cs, x => c + x * evalPoly cs x +/-- The proposition shared by polynomial nonnegativity certificate backends. -/ +def NonnegOn (cs : List Int) (lo hi : Int) : Prop := + ∀ x : Int, lo ≤ x → x ≤ hi → 0 ≤ evalPoly cs x + +namespace NonnegOn + +theorem eval {cs : List Int} {lo hi x : Int} (h : NonnegOn cs lo hi) + (hlo : lo ≤ x) (hhi : x ≤ hi) : 0 ≤ evalPoly cs x := + h x hlo hhi + +theorem restrict {cs : List Int} {lo hi lo' hi' : Int} (h : NonnegOn cs lo hi) + (hlo : lo ≤ lo') (hhi : hi' ≤ hi) : NonnegOn cs lo' hi' := by + intro x hxlo hxhi + exact h x (by omega) (by omega) + +theorem empty (cs : List Int) {lo hi : Int} (h : hi < lo) : NonnegOn cs lo hi := by + intro x hxlo hxhi + omega + +theorem singleton (cs : List Int) (x : Int) (h : 0 ≤ evalPoly cs x) : + NonnegOn cs x x := by + intro y hylo hyhi + have : y = x := by omega + simpa [this] using h + +theorem union {cs : List Int} {lo mid hi : Int} + (hl : NonnegOn cs lo mid) (hr : NonnegOn cs (mid + 1) hi) : + NonnegOn cs lo hi := by + intro x hxlo hxhi + by_cases hx : x ≤ mid + · exact hl x hxlo hx + · exact hr x (by omega) hxhi + +theorem congr {cs ds : List Int} {lo hi : Int} (h : NonnegOn cs lo hi) + (heval : ∀ x : Int, lo ≤ x → x ≤ hi → evalPoly cs x = evalPoly ds x) : + NonnegOn ds lo hi := by + intro x hxlo hxhi + rw [← heval x hxlo hxhi] + exact h x hxlo hxhi + +end NonnegOn + /-- Interval Horner over a nonnegative domain `[lo, hi]`, `0 ≤ lo`. Returns `(vlo, vhi)` with `vlo ≤ P(x) ≤ vhi` for all `x ∈ [lo, hi]`. -/ def hornerIv : List Int → Int → Int → Int × Int diff --git a/formal/common/Common/GenBernstein.lean b/formal/common/Common/GenBernstein.lean new file mode 100644 index 000000000..8c46d4ff9 --- /dev/null +++ b/formal/common/Common/GenBernstein.lean @@ -0,0 +1,123 @@ +import Common.Foundation.Bernstein +import Common.GenCover + +/-! +# Bernstein certificate generation + +The generator searches exact checker results and emits cell endpoints, bit +widths, and explicit weights. Generated modules remain independently checked +by Lean's kernel. +-/ + +namespace Common.GenBernstein + +open Common.Poly Common.GenCover + +structure BernsteinCell where + spec : CellSpec + weights : List Int + +def weightsText (name : String) (weights : List Int) : String := + "def " ++ name ++ " : List Int := [\n " ++ + String.intercalate ",\n " (weights.map toString) ++ "]\n\n" + +def bernsteinEmitter (weights : List Int) : CellEmitter where + checkerImport := "Common.Foundation.Bernstein" + preamble := fun cellName => weightsText s!"{cellName}Weights" weights + checkType := fun litName cellName spec => + s!"checkBernsteinKWithWitness {spec.bits} {litName} {spec.lo} {spec.hi} {cellName}Weights = true" + soundTerm := fun litName cellName spec => + s!"checkBernsteinKWithWitness_nonnegOn {spec.bits} {litName} {spec.lo} {spec.hi} {cellName}Weights {cellName}" + +def generatedWeights (C : List Int) (a b : Int) : List Int := + let n := C.length - 1 + let q := scaleVariable (b - a) (polyShiftM C a) + (List.range C.length).map (bernsteinWeight q n) + +def bernsteinIdentityStart (C : List Int) (a b : Int) (weights : List Int) : Nat := + let n := C.length - 1 + max + (strictPow2Bits (polyL1 (polyScale ((b - a) ^ n) C) * 2)) + (strictPow2Bits (bernsteinCertL1 a b n 0 weights * 2)) + +def weightsNonnegative (weights : List Int) : Bool := + decide (∀ d ∈ weights, 0 ≤ d) + +/-- Find the first identity width that makes the exact checker accept a cell. -/ +def firstBernsteinBWithWeights (C : List Int) (a b : Int) (weights : List Int) + (fuel : Nat) : Option Nat := + if a < b && weightsNonnegative weights then + let start := bernsteinIdentityStart C a b weights + firstAcceptedB (fun B => checkBernsteinKWithWitness B C a b weights) start fuel + else none + +def firstBernsteinB (C : List Int) (a b : Int) (fuel : Nat) : Option Nat := + firstBernsteinBWithWeights C a b (generatedWeights C a b) fuel + +def acceptedCell (C : List Int) (bitFuel : Nat) (lo hi : Int) : Option BernsteinCell := + let weights := generatedWeights C lo hi + match firstBernsteinBWithWeights C lo hi weights bitFuel with + | none => none + | some B => some ⟨⟨lo, hi, B⟩, weights⟩ + +partial def bisectWidest (C : List Int) (bitFuel : Nat) + (accepted : BernsteinCell) (rejected : Int) : BernsteinCell := + if rejected ≤ accepted.spec.hi + 1 then accepted + else + let mid := accepted.spec.hi + (rejected - accepted.spec.hi) / 2 + match acceptedCell C bitFuel accepted.spec.lo mid with + | some cell => bisectWidest C bitFuel cell rejected + | none => bisectWidest C bitFuel accepted mid + +/-- The checker-accepted cell with the largest endpoint at the given anchor. -/ +def widestCell (C : List Int) (bitFuel : Nat) (lo hi : Int) : Option BernsteinCell := + if hi ≤ lo then none + else + match acceptedCell C bitFuel lo (lo + 1) with + | none => none + | some first => + if hi = lo + 1 then some first + else + match acceptedCell C bitFuel lo hi with + | some full => some full + | none => some (bisectWidest C bitFuel first hi) + +/-- Greedy left-to-right partition into the widest checker-accepted cells. -/ +def search (C : List Int) (bitFuel : Nat) : + Nat → Int → Int → Option (List BernsteinCell) + | 0, lo, hi => if hi < lo then some [] else none + | cellFuel + 1, lo, hi => + if hi < lo then some [] + else + match widestCell C bitFuel lo hi with + | none => none + | some cell => + if cell.spec.hi = hi then some [cell] + else + match search C bitFuel cellFuel (cell.spec.hi + 1) hi with + | none => none + | some rest => some (cell :: rest) + +def cellText (importMod ns cellName litName : String) (cell : BernsteinCell) : String := + cellTextWith (bernsteinEmitter cell.weights) importMod ns cellName litName cell.spec + +def emitCells (outDir importMod ns modPrefix cellPrefix litName : String) + (cells : List BernsteinCell) : IO Unit := do + for (cell, i) in cells.zipIdx do + let suffix := pad2 i + IO.FS.writeFile s!"{outDir}/{modPrefix}{suffix}.lean" + (cellText importMod ns s!"{cellPrefix}{suffix}" litName cell) + +def searchAndEmit (outDir importMod ns modPrefix cellPrefix litName : String) + (C : List Int) (lo hi : Int) (cellFuel bitFuel : Nat) : + IO (Option (List BernsteinCell)) := do + let result := search C bitFuel cellFuel lo hi + match result with + | none => pure none + | some cells => + let expected := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" + reconcileOutputs outDir [modPrefix] expected + emitCells outDir importMod ns modPrefix cellPrefix litName cells + pure (some cells) + +end Common.GenBernstein diff --git a/formal/common/Common/GenCover.lean b/formal/common/Common/GenCover.lean index 251a634d9..80b8aa742 100644 --- a/formal/common/Common/GenCover.lean +++ b/formal/common/Common/GenCover.lean @@ -14,6 +14,94 @@ namespace Common.GenCover open Common.Poly +structure CellSpec where + lo : Int + hi : Int + bits : Nat + +structure CellEmitter where + checkerImport : String + preamble : String → String + checkType : String → String → CellSpec → String + soundTerm : String → String → CellSpec → String + +/-- Search a finite consecutive range for its first checker-accepted bit width. -/ +def firstAcceptedB (check : Nat → Bool) : Nat → Nat → Option Nat + | _, 0 => none + | start, fuel + 1 => + if check start then some start else firstAcceptedB check (start + 1) fuel + +def strictPow2Bits (n : Nat) : Nat := + if n = 0 then 0 else Nat.log2 n + 1 + +def firstCoverKB (C : List Int) (lo hi : Int) (fuel : Nat) : Option Nat := + let start := strictPow2Bits (aeval C (1 + lo.natAbs) * 2) + firstAcceptedB (fun B => checkCoverK B C lo hi [hi - lo]) start fuel + +def acceptedKCell (C : List Int) (bitFuel : Nat) (lo hi : Int) : Option CellSpec := + match firstCoverKB C lo hi bitFuel with + | none => none + | some B => some ⟨lo, hi, B⟩ + +partial def bisectWidestK (C : List Int) (bitFuel : Nat) + (accepted : CellSpec) (rejected : Int) : CellSpec := + if rejected ≤ accepted.hi + 1 then accepted + else + let mid := accepted.hi + (rejected - accepted.hi) / 2 + match acceptedKCell C bitFuel accepted.lo mid with + | some cell => bisectWidestK C bitFuel cell rejected + | none => bisectWidestK C bitFuel accepted mid + +def widestKCell (C : List Int) (bitFuel : Nat) (lo hi : Int) : Option CellSpec := + if hi < lo then none + else + match acceptedKCell C bitFuel lo hi with + | some full => some full + | none => + match acceptedKCell C bitFuel lo lo with + | none => none + | some point => some (bisectWidestK C bitFuel point hi) + +/-- Greedy left-to-right partition with a checker-accepted bit width per cell. -/ +def walkK (C : List Int) (bitFuel : Nat) : + Nat → Int → Int → Option (List CellSpec) + | 0, lo, hi => if hi < lo then some [] else none + | cellFuel + 1, lo, hi => + if hi < lo then some [] + else + match widestKCell C bitFuel lo hi with + | none => none + | some cell => + if cell.hi = hi then some [cell] + else + match walkK C bitFuel cellFuel (cell.hi + 1) hi with + | none => none + | some rest => some (cell :: rest) + +/-- Remove stale generated Lean files only from the caller's owned prefixes. -/ +def reconcileOutputs (outDir : System.FilePath) (ownedPrefixes expected : List String) : + IO Unit := do + for entry in (← outDir.readDir) do + let name := entry.fileName + let owned := ownedPrefixes.any (fun pfx => name.startsWith pfx) + let keep := expected.any (fun expectedName => name = expectedName) + if name.endsWith ".lean" && owned && !keep then + let metadata ← entry.path.symlinkMetadata + if metadata.type == .file then + IO.FS.removeFile entry.path + +def cellTextWith (emitter : CellEmitter) (importMod ns cellName litName : String) + (spec : CellSpec) : String := + s!"import {importMod}\nimport {emitter.checkerImport}\n\nnamespace {ns}\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\n{emitter.preamble cellName}theorem {cellName} : {emitter.checkType litName cellName spec} := by\n decide +kernel\n\ntheorem {cellName}_nonnegOn : NonnegOn {litName} {spec.lo} {spec.hi} := by\n exact {emitter.soundTerm litName cellName spec}\n\nend {ns}\n" + +def coverKEmitter : CellEmitter where + checkerImport := "Common.Foundation.KroneckerShift" + preamble := fun _ => "" + checkType := fun litName _ spec => + s!"checkCoverK {spec.bits} {litName} {spec.lo} {spec.hi}\n [{spec.hi - spec.lo}] = true" + soundTerm := fun litName cellName spec => + s!"checkCoverK_nonnegOn {spec.bits} {litName} [{spec.hi - spec.lo}] {spec.lo} {spec.hi} {cellName}" + /-- Drop trailing zero coefficients. -/ def ptrim (a : List Int) : List Int := let r := (a.reverse.dropWhile (· == 0)).reverse @@ -54,6 +142,28 @@ def litText (name : String) (c : List Int) : String := def cellText (importMod ns cellName litName : String) (a w : Int) : String := s!"import {importMod}\nimport Common.Foundation.KroneckerShift\n\nnamespace {ns}\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\ntheorem {cellName} : checkCoverK kB {litName} {a} {a + w}\n [{w}] = true := by\n decide +kernel\n\nend {ns}\n" +def cellTextK (importMod ns cellName litName : String) (spec : CellSpec) : String := + cellTextWith coverKEmitter importMod ns cellName litName spec + +def emitKCells (outDir importMod ns modPrefix cellPrefix litName : String) + (cells : List CellSpec) : IO Unit := do + for (spec, i) in cells.zipIdx do + let suffix := pad2 i + IO.FS.writeFile s!"{outDir}/{modPrefix}{suffix}.lean" + (cellTextK importMod ns s!"{cellPrefix}{suffix}" litName spec) + +def walkAndEmitK (outDir importMod ns modPrefix cellPrefix litName : String) + (C : List Int) (lo hi : Int) (cellFuel bitFuel : Nat) : + IO (Option (List CellSpec)) := do + let result := walkK C bitFuel cellFuel lo hi + match result with + | none => pure none + | some cells => + let expected := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" + reconcileOutputs outDir [modPrefix] expected + emitKCells outDir importMod ns modPrefix cellPrefix litName cells + pure (some cells) + /-- One `_nonneg`-ladder step dispatching variable `x` into cell `cellName`; the final cell consumes the ladder's upper hypothesis `h2` directly. -/ def ladderStep (cellName x : String) (a w : Int) (last : Bool) : String := From 20bae78802393dff534763e873ba34c1efa89502 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 23:20:05 +0200 Subject: [PATCH 077/107] Add Exp polynomial certificate portfolio Co-Authored-By: OpenAI Codex --- .../ExpProof/Floor/UnderCarryDefs.lean | 67 +++++ formal/exp/ExpProof/GenExpUnderCarry.lean | 81 ++++++ formal/exp/ExpProof/GenExpVLit.lean | 242 +++++++++++------- 3 files changed, 297 insertions(+), 93 deletions(-) create mode 100644 formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean create mode 100644 formal/exp/ExpProof/GenExpUnderCarry.lean diff --git a/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean b/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean new file mode 100644 index 000000000..d15b7d56b --- /dev/null +++ b/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean @@ -0,0 +1,67 @@ +import ExpProof.Floor.CertDefsV +import ExpProof.Floor.GranPieces + +/-! +# Positive-under carry certificates at the signed 128-bit magnitude bound + +The carry budget is reduced to one degree-ten integer polynomial on each +granularity interval. Every row records the interval, its argument cap, and +the checked integer bound used by the corresponding certificate. +-/ + +namespace ExpCertV + +open Common.Poly + +def S2 : Int := 2 ^ 127 - 1 + +def denAtCap (T : Int) : List Int := + polySub (polyScale (2 ^ 111) evVPoly) (polyScale T odVPoly) + +def carryLhs (T : Int) : List Int := + let D := denAtCap T + let inner := polyAdd + (polyAdd (polyScale (200 * S2) D) (polyScale (200 * S2 * T) odVPoly)) + (polyScale (800 * S2 * 2 ^ 637) [1]) + polyAdd + (polyScale (1000 * (2 ^ 637 + 269746241 * 2 ^ 480 * T)) inner) + (polyScale (200000 * 2 ^ 637) D) + +def carryCert (T R : Int) : List Int := + let D := denAtCap T + polySub (polyScale R (polyMul D D)) (carryLhs T) + +def underCarryBounds : List Int := [ + 92600, 97310, 101060, 104316, 107259, 109980, 112535, 114960, + 117278, 119508, 121663, 123754, 125790, 127776, 129719, 131623, + 133492, 135329, 137138, 138920, 140678, 142414, 144130, 145826, + 147505, 149168, 150816, 152449, 154069, 155677, 157272, 158857] + +def withCarryBound : + (Int × Int × Int × Int × Int) → Int → (Int × Int × Int × Int) + | (vlo, vhi, T, _, _), R => (vlo, vhi, T, R) + +def underCarryPieces : List (Int × Int × Int × Int) := + List.zipWith withCarryBound granPieces underCarryBounds + +theorem eval_denAtCap (T v : Int) : + evalPoly (denAtCap T) v = + 2 ^ 111 * evalPoly evVPoly v - T * evalPoly odVPoly v := by + simp only [denAtCap, evalPoly_polySub, evalPoly_polyScale] + +theorem eval_carryLhs (T v : Int) : + evalPoly (carryLhs T) v = + 1000 * (2 ^ 637 + 269746241 * 2 ^ 480 * T) * + (200 * S2 * evalPoly (denAtCap T) v + + 200 * S2 * T * evalPoly odVPoly v + 800 * S2 * 2 ^ 637) + + 200000 * 2 ^ 637 * evalPoly (denAtCap T) v := by + simp only [carryLhs, evalPoly_polyAdd, evalPoly_polyScale, evalPoly_singleton] + rw [Int.mul_one] + +theorem eval_carryCert (T R v : Int) : + evalPoly (carryCert T R) v = + R * (evalPoly (denAtCap T) v * evalPoly (denAtCap T) v) - + evalPoly (carryLhs T) v := by + simp only [carryCert, evalPoly_polySub, evalPoly_polyScale, evalPoly_polyMul] + +end ExpCertV diff --git a/formal/exp/ExpProof/GenExpUnderCarry.lean b/formal/exp/ExpProof/GenExpUnderCarry.lean new file mode 100644 index 000000000..a03e7ce5a --- /dev/null +++ b/formal/exp/ExpProof/GenExpUnderCarry.lean @@ -0,0 +1,81 @@ +import ExpProof.Floor.UnderCarryDefs +import Common.GenCover + +/-! +# Positive-under carry certificate generator + +Each granularity row emits one literal polynomial and one independently +checked interval-Horner/Kronecker cell. The façade transports those literal +certificates back to the symbolic carry polynomials. +-/ + +open Common.Poly Common.GenCover ExpCertV + +namespace GenExpUnderCarry + +def outDir : String := "ExpProof/Cert" + +def literalModule (pieces : List (Int × Int × Int × Int)) : String := + let body := pieces.zipIdx.foldl (fun text row => + let ((_, _, T, R), i) := row + text ++ litText s!"carryP{pad2 i}Lit" (carryCert T R)) + "namespace ExpCertV\n\n" + body ++ "end ExpCertV\n" + +def facadeModule (pieces : List (Int × Int × Int × Int)) : String := + let imports := pieces.zipIdx.foldl (fun text row => + let (_, i) := row + text ++ s!"import ExpProof.Cert.ExpUnderCarryP{pad2 i}C00\n") + "import ExpProof.Floor.UnderCarryDefs\nimport ExpProof.Cert.ExpUnderCarryLit\n" + let theorems := pieces.zipIdx.foldl (fun text row => + let ((lo, hi, T, R), i) := row + let suffix := pad2 i + text ++ s!"theorem carryP{suffix}_eq : carryCert {T} {R} = carryP{suffix}Lit := by\n" ++ + " unfold carryCert carryLhs denAtCap S2\n decide +kernel\n\n" ++ + s!"theorem carryP{suffix}_nonnegOn :\n" ++ + s!" NonnegOn (carryCert {T} {R}) {lo} {hi} := by\n" ++ + s!" rw [carryP{suffix}_eq]\n" ++ + s!" exact underCarryP{suffix}_cell00_nonnegOn\n\n" ++ + s!"theorem carryP{suffix}_nonneg {lb}v : Int{rb} (hlo : {lo} ≤ v) (hhi : v ≤ {hi}) :\n" ++ + s!" 0 ≤ evalPoly (carryCert {T} {R}) v :=\n" ++ + s!" carryP{suffix}_nonnegOn v hlo hhi\n\n") "" + imports ++ + "\nnamespace ExpCertV\n\nopen Common.Poly\n\n" ++ + "set_option maxRecDepth 100000\n\n" ++ theorems ++ "end ExpCertV\n" +where + lb := "{" + rb := "}" + +def expectedOutputs (pieces : List (Int × Int × Int × Int)) : List String := + ["ExpUnderCarryLit.lean", "ExpUnderCarry.lean"] ++ + pieces.zipIdx.map fun (_, i) => s!"ExpUnderCarryP{pad2 i}C00.lean" + +def generate : IO Unit := do + if granPieces.length != underCarryBounds.length then + throw <| IO.userError + s!"carry table length mismatch: {granPieces.length} pieces, {underCarryBounds.length} bounds" + if underCarryPieces.length != 32 then + throw <| IO.userError s!"expected 32 carry pieces, got {underCarryPieces.length}" + let mut accepted : List (Nat × Nat) := [] + for (piece, i) in underCarryPieces.zipIdx do + let (lo, hi, T, R) := piece + let C := carryCert T R + let modPrefix := s!"ExpUnderCarryP{pad2 i}C" + match walkK C 1024 1 lo hi with + | some [cell] => + emitKCells outDir "ExpProof.Cert.ExpUnderCarryLit" "ExpCertV" + modPrefix s!"underCarryP{pad2 i}_cell" s!"carryP{pad2 i}Lit" [cell] + accepted := accepted ++ [(i, cell.bits)] + | some cells => + throw <| IO.userError s!"piece {i} requires {cells.length} cells" + | none => + throw <| IO.userError s!"piece {i} has no accepted one-cell certificate" + reconcileOutputs outDir ["ExpUnderCarry"] (expectedOutputs underCarryPieces) + IO.FS.writeFile s!"{outDir}/ExpUnderCarryLit.lean" (literalModule underCarryPieces) + IO.FS.writeFile s!"{outDir}/ExpUnderCarry.lean" (facadeModule underCarryPieces) + for (i, B) in accepted do + IO.println s!"carry piece {pad2 i}: cells=1 B={B}" + +end GenExpUnderCarry + +#eval GenExpUnderCarry.generate diff --git a/formal/exp/ExpProof/GenExpVLit.lean b/formal/exp/ExpProof/GenExpVLit.lean index c67faa9a1..4ec898351 100644 --- a/formal/exp/ExpProof/GenExpVLit.lean +++ b/formal/exp/ExpProof/GenExpVLit.lean @@ -1,131 +1,187 @@ import ExpProof.Floor.CertDefsV import ExpProof.Floor.GranPieces -import Common.Foundation.KroneckerShift -import Common.GenCover +import Common.GenBernstein /-! -# Cert literal + cover generator for the **v-form** reduced-argument Taylor caps - -Computes the never-over (`certExpUp`) and not-two-below (`certExpLo`) v-form certificate polynomials -from the symbolic `ExpCertV` definitions, emits the building-block + cert literal coefficient lists -(`Cert/ExpVCertLit.lean`), then greedily walks `[0, H128]` for each — exactly the predicate the -in-kernel `checkCoverK` decides — and writes one `Cert/ExpV{Up,Lo,…}C.lean` cell file per sub-cell -plus the cover module with the symbolic-cert↔literal equality and the `_nonneg` ladder. - -Run with `lake env lean GenExpVLit.lean` after -`lake build ExpProof.Floor.CertDefsV ExpProof.Floor.GranPieces Common.GenCover`. Output is -deterministic (byte-identical on re-run). Only the generated `Cert/ExpV*` files are machine -output; this -generator, the hand-written `Floor/CertDefsV.lean` symbolic definitions, and the -`Floor/GranPieces.lean` piece table are tracked. +# Reduced-argument certificate generator + +Taylor upper and lower bounds use exact Bernstein witnesses. Numerator, +denominator, and granularity families use interval-Horner/Kronecker cells. +Each family owns a distinct literal module so an approximation change does +not invalidate unrelated certificate leaves. -/ -open Common.Poly ExpCertV Common.GenCover +open Common.Poly ExpCertV Common.GenCover Common.GenBernstein namespace GenExpVLit -/-- Walk `[lo, hi]`, write one cell file per sub-cell, then write the cover module. -/ -def emit (litName coverMod modPrefix cellPrefix certEqName litNonneg symNonneg symName eqTac : String) - (C : List Int) (lo hi : Int) : IO Unit := do - let (ok, cells) := walk C lo hi - IO.println s!"-- {coverMod}: reached={ok} ncells={cells.length}" - if ! ok then IO.println s!"-- FAILED tail: {cells.drop (cells.length - 2)}"; return - for (aw, i) in cells.zipIdx do - let (a, w) := aw - IO.FS.writeFile s!"ExpProof/Cert/{modPrefix}{pad2 i}.lean" - (cellText "ExpProof.Cert.ExpVCertLit" "ExpCertV" s!"{cellPrefix}{pad2 i}" litName a w) - let lb := "{"; let rb := "}" - let mut s := "import ExpProof.Floor.CertDefsV\nimport ExpProof.Cert.ExpVCertLit\nimport Common.Foundation.KroneckerShift\n" - for (_, i) in cells.zipIdx do s := s ++ s!"import ExpProof.Cert.{modPrefix}{pad2 i}\n" - s := s ++ s!"\nnamespace ExpCertV\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\n" - s := s ++ s!"theorem {certEqName} : {symName} = {litName} := by\n{eqTac}\n\n" - s := s ++ s!"theorem {litNonneg} {lb}t : Int{rb} (h1 : {lo} ≤ t) (h2 : t ≤ {hi}) :\n" - s := s ++ s!" 0 ≤ evalPoly {litName} t := by\n" - let n := cells.length - for (aw, i) in cells.zipIdx do - let (a, w) := aw - s := s ++ ladderStep s!"{cellPrefix}{pad2 i}" "t" a w (i + 1 == n) - s := s ++ s!"\ntheorem {symNonneg} {lb}t : Int{rb} (h1 : {lo} ≤ t) (h2 : t ≤ {hi}) :\n" - s := s ++ s!" 0 ≤ evalPoly {symName} t := by\n rw [{certEqName}]; exact {litNonneg} h1 h2\n" - s := s ++ "\nend ExpCertV\n" - IO.FS.writeFile s!"ExpProof/Cert/{coverMod}.lean" s - -end GenExpVLit - -open GenExpVLit +def outDir : String := "ExpProof/Cert" + +def literalText (body : String) : String := + "namespace ExpCertV\n\n" ++ body ++ "end ExpCertV\n" + +def theoremLadder (cellPrefix x : String) (cells : List CellSpec) : String := + cells.zipIdx.foldl (fun text row => + let (cell, i) := row + let name := s!"{cellPrefix}{pad2 i}_nonnegOn" + if i + 1 = cells.length then + text ++ s!" exact {name} {x} (by omega) hhi\n" + else + text ++ s!" rcases Int.lt_or_le {x} ({cell.hi} + 1) with h | h\n" ++ + s!" · exact {name} {x} (by omega) (by omega)\n") "" + +def coverText (literalImport coverImport ns litName certEqName litNonnegOn + symNonnegOn pointwiseName symName eqTac cellPrefix : String) + (lo hi : Int) (cells : List CellSpec) : String := + let imports := cells.zipIdx.foldl (fun text row => + let (_, i) := row + text ++ s!"import ExpProof.Cert.{coverImport}{pad2 i}\n") + s!"import ExpProof.Floor.CertDefsV\nimport {literalImport}\n" + imports ++ s!"\nnamespace {ns}\n\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\n" ++ + s!"theorem {certEqName} : {symName} = {litName} := by\n{eqTac}\n\n" ++ + s!"theorem {litNonnegOn} : NonnegOn {litName} {lo} {hi} := by\n" ++ + " intro t hlo hhi\n" ++ theoremLadder cellPrefix "t" cells ++ "\n" ++ + s!"theorem {symNonnegOn} : NonnegOn {symName} {lo} {hi} := by\n" ++ + s!" rw [{certEqName}]\n exact {litNonnegOn}\n\n" ++ + s!"theorem {pointwiseName} {lb}t : Int{rb} (hlo : {lo} ≤ t) (hhi : t ≤ {hi}) :\n" ++ + s!" 0 ≤ evalPoly {symName} t :=\n {symNonnegOn} t hlo hhi\n\nend {ns}\n" +where + lb := "{" + rb := "}" + +def emitBernstein (literalModule coverModule cellModPrefix cellPrefix litName + certEqName litNonnegOn symNonnegOn pointwiseName symName eqTac : String) + (C : List Int) (lo hi : Int) : IO (List String × List Nat) := do + match search C 1024 16 lo hi with + | none => throw <| IO.userError s!"{coverModule} has no Bernstein cover" + | some cells => + let specs := cells.map (·.spec) + emitCells outDir s!"ExpProof.Cert.{literalModule}" "ExpCertV" + cellModPrefix cellPrefix litName cells + IO.FS.writeFile s!"{outDir}/{coverModule}.lean" + (coverText s!"ExpProof.Cert.{literalModule}" cellModPrefix "ExpCertV" + litName certEqName litNonnegOn symNonnegOn pointwiseName symName eqTac cellPrefix + lo hi specs) + let outputs := [s!"{coverModule}.lean"] ++ + cells.zipIdx.map fun (_, i) => s!"{cellModPrefix}{pad2 i}.lean" + pure (outputs, cells.map (·.spec.bits)) + +def emitKronecker (literalModule coverModule cellModPrefix cellPrefix litName + certEqName litNonnegOn symNonnegOn pointwiseName symName eqTac : String) + (C : List Int) (lo hi : Int) : IO (List String × List Nat) := do + match walkK C 1024 128 lo hi with + | none => throw <| IO.userError s!"{coverModule} has no Kronecker cover" + | some cells => + emitKCells outDir s!"ExpProof.Cert.{literalModule}" "ExpCertV" + cellModPrefix cellPrefix litName cells + IO.FS.writeFile s!"{outDir}/{coverModule}.lean" + (coverText s!"ExpProof.Cert.{literalModule}" cellModPrefix "ExpCertV" + litName certEqName litNonnegOn symNonnegOn pointwiseName symName eqTac cellPrefix + lo hi cells) + let outputs := [s!"{coverModule}.lean"] ++ + cells.zipIdx.map fun (_, i) => s!"{cellModPrefix}{pad2 i}.lean" + pure (outputs, cells.map (·.bits)) -/-- Tactic block proving `certExpUp = certExpUpLit`. -/ def upEqTac : String := " have hy : yUB = yUBLit := by unfold yUB numExpV evNumVPoly todNumV odNumVPoly mulT2; decide +kernel\n" ++ " have hw : wUB = wUBLit := by unfold wUB denExpV evNumVPoly todNumV odNumVPoly mulT2; decide +kernel\n" ++ " have ht : tailUp = tailUpLit := by unfold tailUp expN27; decide +kernel\n" ++ " unfold certExpUp\n rw [hy, hw, ht]\n decide +kernel" -/-- Tactic block proving `certExpLo = certExpLoLit`. -/ def loEqTac : String := " have he : expN27 = expN27Lit := by unfold expN27; decide +kernel\n" ++ " have hy : yLB = yLBLit := by unfold yLB numExpV evNumVPoly todNumV odNumVPoly mulT2; decide +kernel\n" ++ " have hw : wLB = wLBLit := by unfold wLB denExpV evNumVPoly todNumV odNumVPoly mulT2; decide +kernel\n" ++ " unfold certExpLo\n rw [he, hy, hw]\n decide +kernel" -/-- Tactic block proving `numExpV = numExpVLit`. -/ def numEqTac : String := " unfold numExpV evNumVPoly todNumV odNumVPoly mulT2\n decide +kernel" -/-- Tactic block proving `certDenM1 = certDenM1Lit`. -/ -def denM1EqTac : String := +def denEqTac : String := " unfold certDenM1 denExpV evNumVPoly todNumV odNumVPoly mulT2\n decide +kernel" -/-- Tactic block proving `certDOver = certDOverLit`. -/ def dOverEqTac : String := " unfold certDOver certDOverP evVPoly odVPoly\n decide +kernel" -/-- Tactic block proving `certDOverP T D = certDOvPLit`. -/ def dOverPEqTac : String := " unfold certDOverP evVPoly odVPoly\n decide +kernel" -/-- Tactic block proving `certDUnderP T D = certDUnPLit`. -/ def dUnderPEqTac : String := " unfold certDUnderP evVPoly odVPoly\n decide +kernel" -#eval do +def generate : IO Unit := do let cUp := ptrim certExpUp let cLo := ptrim certExpLo - let mut lits := - ("/-! Generated v-form cut-certificate literal coefficient lists. -/\n\nnamespace ExpCertV\n\n" ++ - litText "numExpVLit" (ptrim numExpV) ++ - litText "denExpVLit" (ptrim denExpV) ++ - litText "expN27Lit" (ptrim expN27) ++ - litText "tailUpLit" (ptrim tailUp) ++ - litText "yUBLit" (ptrim yUB) ++ - litText "wUBLit" (ptrim wUB) ++ - litText "yLBLit" (ptrim yLB) ++ - litText "wLBLit" (ptrim wLB) ++ - litText "certDenM1Lit" (ptrim certDenM1) ++ - litText "certExpUpLit" cUp ++ - litText "certExpLoLit" cLo ++ - litText "certDOverLit" (ptrim certDOver)) - for (p, i) in granPieces.zipIdx do - let (_, _, t, dO, dU) := p - lits := lits ++ litText s!"certDOvP{pad2 i}Lit" (ptrim (certDOverP t dO)) - lits := lits ++ litText s!"certDUnP{pad2 i}Lit" (ptrim (certDUnderP t dU)) - IO.FS.writeFile "ExpProof/Cert/ExpVCertLit.lean" (lits ++ "end ExpCertV\n") - IO.println "v-form literals written" - emit "certExpUpLit" "ExpVUp" "ExpVUpC" "expVUp_cell" "certExpUp_eq" "expVUpLit_nonneg" - "expVUp_nonneg" "certExpUp" upEqTac cUp 0 (H129 : Int) - emit "certExpLoLit" "ExpVLo" "ExpVLoC" "expVLo_cell" "certExpLo_eq" "expVLoLit_nonneg" - "expVLo_nonneg" "certExpLo" loEqTac cLo 0 (H129 : Int) - emit "numExpVLit" "ExpVNum" "ExpVNumC" "expVNum_cell" "numExpV_eq" "numExpVLit_nonneg" - "numExpV_nonneg" "numExpV" numEqTac (ptrim numExpV) 0 (H129 : Int) - emit "certDenM1Lit" "ExpVDenM1" "ExpVDenM1C" "expVDenM1_cell" "certDenM1_eq" "denM1VLit_nonneg" - "denM1V_nonneg" "certDenM1" denM1EqTac (ptrim certDenM1) 0 (H129 : Int) - emit "certDOverLit" "ExpVDOver" "ExpVDOverC" "expVDOver_cell" "certDOver_eq" "dOverVLit_nonneg" - "dOverV_nonneg" "certDOver" dOverEqTac (ptrim certDOver) 0 ((vmaxV : Int) + 1) - for (p, i) in granPieces.zipIdx do - let (vlo, vhi, t, dO, dU) := p - emit s!"certDOvP{pad2 i}Lit" s!"ExpVDOvP{pad2 i}" s!"ExpVDOvP{pad2 i}C" s!"dOvP{pad2 i}_cell" - s!"certDOvP{pad2 i}_eq" s!"dOvP{pad2 i}Lit_nonneg" s!"dOvP{pad2 i}_nonneg" - s!"(certDOverP {t} {dO})" dOverPEqTac (ptrim (certDOverP t dO)) vlo (vhi + 1) - emit s!"certDUnP{pad2 i}Lit" s!"ExpVDUnP{pad2 i}" s!"ExpVDUnP{pad2 i}C" s!"dUnP{pad2 i}_cell" - s!"certDUnP{pad2 i}_eq" s!"dUnP{pad2 i}Lit_nonneg" s!"dUnP{pad2 i}_nonneg" - s!"(certDUnderP {t} {dU})" dUnderPEqTac (ptrim (certDUnderP t dU)) vlo (vhi + 1) + IO.FS.writeFile s!"{outDir}/ExpVTaylorUpLit.lean" <| literalText <| + litText "yUBLit" (ptrim yUB) ++ litText "wUBLit" (ptrim wUB) ++ + litText "tailUpLit" (ptrim tailUp) ++ litText "certExpUpLit" cUp + IO.FS.writeFile s!"{outDir}/ExpVTaylorLoLit.lean" <| literalText <| + litText "expN27Lit" (ptrim expN27) ++ litText "yLBLit" (ptrim yLB) ++ + litText "wLBLit" (ptrim wLB) ++ litText "certExpLoLit" cLo + IO.FS.writeFile s!"{outDir}/ExpVNumLit.lean" <| literalText <| + litText "numExpVLit" (ptrim numExpV) + IO.FS.writeFile s!"{outDir}/ExpVDenLit.lean" <| literalText <| + litText "certDenM1Lit" (ptrim certDenM1) + IO.FS.writeFile s!"{outDir}/ExpVDOverLit.lean" <| literalText <| + litText "certDOverLit" (ptrim certDOver) + let mut overLits := "" + let mut underLits := "" + for (piece, i) in granPieces.zipIdx do + let (_, _, T, dOver, dUnder) := piece + overLits := overLits ++ litText s!"certDOvP{pad2 i}Lit" (ptrim (certDOverP T dOver)) + underLits := underLits ++ litText s!"certDUnP{pad2 i}Lit" (ptrim (certDUnderP T dUnder)) + IO.FS.writeFile s!"{outDir}/ExpVGranOverLit.lean" (literalText overLits) + IO.FS.writeFile s!"{outDir}/ExpVGranUnderLit.lean" (literalText underLits) + + let mut expected := ["ExpVTaylorUpLit.lean", "ExpVTaylorLoLit.lean", + "ExpVNumLit.lean", "ExpVDenLit.lean", "ExpVDOverLit.lean", + "ExpVGranOverLit.lean", "ExpVGranUnderLit.lean"] + + let (upFiles, upBits) ← emitBernstein "ExpVTaylorUpLit" "ExpVUp" "ExpVUpC" + "expVUp_cell" "certExpUpLit" "certExpUp_eq" "expVUpLit_nonnegOn" + "expVUp_nonnegOn" "expVUp_nonneg" "certExpUp" upEqTac cUp 0 (H129 : Int) + expected := expected ++ upFiles + let (loFiles, loBits) ← emitBernstein "ExpVTaylorLoLit" "ExpVLo" "ExpVLoC" + "expVLo_cell" "certExpLoLit" "certExpLo_eq" "expVLoLit_nonnegOn" + "expVLo_nonnegOn" "expVLo_nonneg" "certExpLo" loEqTac cLo 0 (H129 : Int) + expected := expected ++ loFiles + let (numFiles, _) ← emitKronecker "ExpVNumLit" "ExpVNum" "ExpVNumC" + "expVNum_cell" "numExpVLit" "numExpV_eq" "numExpVLit_nonnegOn" + "numExpV_nonnegOn" "numExpV_nonneg" "numExpV" numEqTac (ptrim numExpV) 0 (H129 : Int) + expected := expected ++ numFiles + let (denFiles, _) ← emitKronecker "ExpVDenLit" "ExpVDenM1" "ExpVDenM1C" + "expVDenM1_cell" "certDenM1Lit" "certDenM1_eq" "denM1VLit_nonnegOn" + "denM1V_nonnegOn" "denM1V_nonneg" "certDenM1" denEqTac (ptrim certDenM1) 0 (H129 : Int) + expected := expected ++ denFiles + let (overFiles, _) ← emitKronecker "ExpVDOverLit" "ExpVDOver" "ExpVDOverC" + "expVDOver_cell" "certDOverLit" "certDOver_eq" "dOverVLit_nonnegOn" + "dOverV_nonnegOn" "dOverV_nonneg" "certDOver" dOverEqTac (ptrim certDOver) + 0 ((vmaxV : Int) + 1) + expected := expected ++ overFiles + + for (piece, i) in granPieces.zipIdx do + let (vlo, vhi, T, dOver, dUnder) := piece + let suffix := pad2 i + let (dOverFiles, _) ← emitKronecker "ExpVGranOverLit" s!"ExpVDOvP{suffix}" + s!"ExpVDOvP{suffix}C" s!"dOvP{suffix}_cell" s!"certDOvP{suffix}Lit" + s!"certDOvP{suffix}_eq" s!"dOvP{suffix}Lit_nonnegOn" s!"dOvP{suffix}_nonnegOn" + s!"dOvP{suffix}_nonneg" s!"(certDOverP {T} {dOver})" dOverPEqTac + (ptrim (certDOverP T dOver)) vlo (vhi + 1) + expected := expected ++ dOverFiles + let (dUnderFiles, _) ← emitKronecker "ExpVGranUnderLit" s!"ExpVDUnP{suffix}" + s!"ExpVDUnP{suffix}C" s!"dUnP{suffix}_cell" s!"certDUnP{suffix}Lit" + s!"certDUnP{suffix}_eq" s!"dUnP{suffix}Lit_nonnegOn" s!"dUnP{suffix}_nonnegOn" + s!"dUnP{suffix}_nonneg" s!"(certDUnderP {T} {dUnder})" dUnderPEqTac + (ptrim (certDUnderP T dUnder)) vlo (vhi + 1) + expected := expected ++ dUnderFiles + + IO.FS.writeFile s!"{outDir}/ExpVTaylor.lean" + "import ExpProof.Cert.ExpVUp\nimport ExpProof.Cert.ExpVLo\n" + expected := expected ++ ["ExpVTaylor.lean"] + reconcileOutputs outDir ["ExpV"] expected + IO.println s!"Taylor upper: cells={upFiles.length - 1} B={upBits}" + IO.println s!"Taylor lower: cells={loFiles.length - 1} B={loBits}" + +end GenExpVLit + +#eval GenExpVLit.generate From 87e063fb9015503be40f8982af1e5e1d9642596e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 10 Jul 2026 23:25:03 +0200 Subject: [PATCH 078/107] Use shared polynomial certificates in Ln proofs Co-Authored-By: OpenAI Codex --- formal/ln/LnProof/GenCover.lean | 38 ++++++++++++------- formal/ln/LnProof/GenErrLit.lean | 7 +++- formal/ln/LnProof/GenFloorCertLit.lean | 38 ++++++++++++++----- formal/ln/LnProof/LnProof/Error/GeBridge.lean | 11 ++++-- formal/ln/LnProof/LnProof/Error/LtBridge.lean | 11 ++++-- formal/ln/LnProof/LnProof/Floor/CertGeLo.lean | 11 ++++-- formal/ln/LnProof/LnProof/Floor/CertGeUp.lean | 11 ++++-- formal/ln/LnProof/LnProof/Floor/CertLtLo.lean | 11 ++++-- formal/ln/LnProof/LnProof/Floor/CertLtUp.lean | 11 ++++-- .../LnProof/LnProof/Floor/CertTightLit.lean | 2 - formal/ln/LnProof/LnProof/Floor/Window.lean | 8 ++-- 11 files changed, 109 insertions(+), 50 deletions(-) diff --git a/formal/ln/LnProof/GenCover.lean b/formal/ln/LnProof/GenCover.lean index aa63a13f1..994d2d921 100644 --- a/formal/ln/LnProof/GenCover.lean +++ b/formal/ln/LnProof/GenCover.lean @@ -1,4 +1,7 @@ -import LnProof.Cert.FloorCertLit +import LnProof.Cert.FloorCertGeUpLit +import LnProof.Cert.FloorCertGeLoLit +import LnProof.Cert.FloorCertLtUpLit +import LnProof.Cert.FloorCertLtLoLit import Common.Foundation.KroneckerShift import Common.GenCover @@ -8,11 +11,12 @@ import Common.GenCover Greedily walks `[lo, hi]` for a certificate polynomial, computing at each anchor `a` the largest cell width `w` with `0 ≤ (hornerIv (kShiftWitness kB C a) 0 w).1` — exactly the predicate the in-kernel `checkCoverK` decides, so the emitted -covers are guaranteed `decide`-acceptable. Writes one `…C.lean` cell file -per sub-cell and prints the `_nonneg` ladder and import block for the cover -module. +covers are guaranteed `decide`-acceptable. Writes one `…C.lean` cell file +per sub-cell and prints the `NonnegOn` ladder, its pointwise compatibility +theorem, and the import block for the cover module. -Run with `lake env lean GenCover.lean` (after `lake build LnProof.Cert.FloorCertLit Common.GenCover`). +Run with `lake env lean GenCover.lean` after building the four +`LnProof.Cert.FloorCert*Lit` modules and `Common.GenCover`. -/ open Common.Poly LnFloorCert Common.GenCover @@ -20,19 +24,21 @@ open Common.Poly LnFloorCert Common.GenCover namespace GenCover /-- Emit cell files `.lean` and return the ladder text. -/ -def emit (nm litName symName evalEqName modPrefix cellPrefix nonnegName : String) +def emit (nm litModule litName symName evalEqName modPrefix cellPrefix nonnegName : String) (C : List Int) (lo hi : Int) : IO Unit := do let (ok, cells) := walk C lo hi IO.println s!"-- {nm}: reached={ok} ncells={cells.length}" if ! ok then IO.println s!"-- FAILED tail: {cells.drop (cells.length - 2)}" return + let expected := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" + reconcileOutputs "LnProof/Cert" [modPrefix] expected -- write one cell file per sub-cell for (aw, i) in cells.zipIdx do let (a, w) := aw let nn := pad2 i IO.FS.writeFile s!"LnProof/Cert/{modPrefix}{nn}.lean" - (cellText "LnProof.Cert.FloorCertLit" "LnFloorCert" s!"{cellPrefix}{nn}" litName a w) + (cellText s!"LnProof.Cert.{litModule}" "LnFloorCert" s!"{cellPrefix}{nn}" litName a w) -- ladder + imports let mut imps := "" for (_, i) in cells.zipIdx do @@ -42,14 +48,18 @@ def emit (nm litName symName evalEqName modPrefix cellPrefix nonnegName : String IO.println "==== LADDER ====" let lb := "{" let rb := "}" - IO.println s!"theorem {nonnegName} {lb}m : Int{rb} (h1 : {lo} ≤ m) (h2 : m ≤ {hi}) :" - IO.println s!" 0 ≤ evalPoly {symName} m := by" + IO.println s!"theorem {nonnegName}On : NonnegOn {symName} {lo} {hi} := by" + IO.println " intro m h1 h2" IO.println s!" have hev := {evalEqName} m" IO.println " rw [hev]" let n := cells.length for (aw, i) in cells.zipIdx do let (a, w) := aw IO.print (ladderStep s!"{cellPrefix}{pad2 i}" "m" a w (i + 1 == n)) + IO.println "" + IO.println s!"theorem {nonnegName} {lb}m : Int{rb} (h1 : {lo} ≤ m) (h2 : m ≤ {hi}) :" + IO.println s!" 0 ≤ evalPoly {symName} m :=" + IO.println s!" {nonnegName}On m h1 h2" end GenCover @@ -62,8 +72,8 @@ def hiGE : Int := 79228162514264337593543950335 -- 2^96 - 1 -- Generate the floor cert covers: never-overshoot upper forms (GeUp/LtUp) and -- not-too-low lower forms (GeLo/LtLo). The cover modules keep their hand-written --- eval_eq; only the cell files and the _nonneg ladder are generated. -#eval emit "certGeUp" "certGeUpLit" "certGeUp" "geUp_eval_eq" "FloorCertGeUpC" "geUp_cell" "geUp_nonneg" certGeUpLit loGE hiGE -#eval emit "certLtUp" "certLtUpLit" "certLtUp" "ltUp_eval_eq" "FloorCertLtUpC" "ltUp_cell" "ltUp_nonneg" certLtUpLit loLT hiLT -#eval emit "certGeLo" "certGeLoLit" "certGeLo" "geLo_eval_eq" "FloorCertGeLoC" "geLo_cell" "geLo_nonneg" certGeLoLit loGE hiGE -#eval emit "certLtLo" "certLtLoLit" "certLtLo" "ltLo_eval_eq" "FloorCertLtLoC" "ltLo_cell" "ltLo_nonneg" certLtLoLit loLT hiLT +-- eval_eq; only the cell files and the `NonnegOn` ladder are generated. +#eval emit "certGeUp" "FloorCertGeUpLit" "certGeUpLit" "certGeUp" "geUp_eval_eq" "FloorCertGeUpC" "geUp_cell" "geUp_nonneg" certGeUpLit loGE hiGE +#eval emit "certLtUp" "FloorCertLtUpLit" "certLtUpLit" "certLtUp" "ltUp_eval_eq" "FloorCertLtUpC" "ltUp_cell" "ltUp_nonneg" certLtUpLit loLT hiLT +#eval emit "certGeLo" "FloorCertGeLoLit" "certGeLoLit" "certGeLo" "geLo_eval_eq" "FloorCertGeLoC" "geLo_cell" "geLo_nonneg" certGeLoLit loGE hiGE +#eval emit "certLtLo" "FloorCertLtLoLit" "certLtLoLit" "certLtLo" "ltLo_eval_eq" "FloorCertLtLoC" "ltLo_cell" "ltLo_nonneg" certLtLoLit loLT hiLT diff --git a/formal/ln/LnProof/GenErrLit.lean b/formal/ln/LnProof/GenErrLit.lean index b9250f62d..b3b7bffbd 100644 --- a/formal/ln/LnProof/GenErrLit.lean +++ b/formal/ln/LnProof/GenErrLit.lean @@ -7,7 +7,7 @@ their covers for the current BIASc and `lnErrorBoundNum`. Computes `certErrLt`/`certErrGe` inline (mirroring the ErrCert*Bridge constructions) so it does not depend on the bridges building, then walks the `checkCoverK` covers (literal signature, as the -checked `errLt_nonneg`/`errGe_nonneg` theorems use). -/ +checked `errLt_nonnegOn`/`errGe_nonnegOn` theorems use). -/ open Common.Poly LnFloorCert Common.Exp LnFloor LnYul open Common.GenCover hiding litText @@ -40,6 +40,8 @@ def emit (litFile litName coverMod modPrefix cellPrefix nonnegName : String) (C let (ok, cells) := walk C lo hi IO.println s!"-- {coverMod}: reached={ok} ncells={cells.length}" if ! ok then IO.println s!"-- FAILED tail: {cells.drop (cells.length-2)}"; return + let expected := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" + reconcileOutputs "LnProof/Cert" [modPrefix] expected for (aw, i) in cells.zipIdx do let (a, w) := aw IO.FS.writeFile s!"LnProof/Cert/{modPrefix}{pad2 i}.lean" @@ -48,11 +50,12 @@ def emit (litFile litName coverMod modPrefix cellPrefix nonnegName : String) (C let mut s := "" for (_, i) in cells.zipIdx do s := s ++ s!"import LnProof.Cert.{modPrefix}{pad2 i}\n" s := s ++ s!"\nnamespace LnFloorCert\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\n" - s := s ++ s!"theorem {nonnegName} {lb}m : Int{rb} (h1 : {lo} ≤ m) (h2 : m ≤ {hi}) :\n 0 ≤ evalPoly {litName} m := by\n" + s := s ++ s!"theorem {nonnegName}On : NonnegOn {litName} {lo} {hi} := by\n intro m h1 h2\n" let n := cells.length for (aw, i) in cells.zipIdx do let (a, w) := aw s := s ++ ladderStep s!"{cellPrefix}{pad2 i}" "m" a w (i + 1 == n) + s := s ++ s!"\ntheorem {nonnegName} {lb}m : Int{rb} (h1 : {lo} ≤ m) (h2 : m ≤ {hi}) :\n 0 ≤ evalPoly {litName} m :=\n {nonnegName}On m h1 h2\n" s := s ++ "\nend LnFloorCert\n" IO.FS.writeFile s!"LnProof/Cert/{coverMod}.lean" s diff --git a/formal/ln/LnProof/GenFloorCertLit.lean b/formal/ln/LnProof/GenFloorCertLit.lean index 3080d808c..b37f18184 100644 --- a/formal/ln/LnProof/GenFloorCertLit.lean +++ b/formal/ln/LnProof/GenFloorCertLit.lean @@ -5,23 +5,41 @@ open LnFloorCert Common.GenCover namespace GenFloorCertLit -def fileText : String := - "/-! Literal coefficient lists for the floor certificate polynomials. -/\n\n" ++ +def fileText (body : String) : String := + "/-! Literal coefficient lists for one floor-certificate family. -/\n\n" ++ "namespace LnFloorCert\n\n" ++ + body ++ + "end LnFloorCert\n" + +def geUpText : String := fileText <| litText "geTNLit" geTN ++ litText "geTDLit" geTD ++ + litText "certGeUpLit" (ptrim certGeUp) + +def geLoText : String := fileText <| litText "geTN2bLit" geTN2b ++ litText "geTD2bLit" geTD2b ++ - litText "ltTNLit" ltTN ++ - litText "ltTDLit" ltTD ++ + litText "certGeLoLit" (ptrim certGeLo) + +def ltUpText : String := fileText <| litText "ltTN2bLit" ltTN2b ++ litText "ltTD2bLit" ltTD2b ++ - litText "certGeUpLit" (ptrim certGeUp) ++ - litText "certGeLoLit" (ptrim certGeLo) ++ - litText "certLtUpLit" (ptrim certLtUp) ++ - litText "certLtLoLit" (ptrim certLtLo) ++ - "end LnFloorCert\n" + litText "certLtUpLit" (ptrim certLtUp) + +def ltLoText : String := fileText <| + litText "ltTNLit" ltTN ++ + litText "ltTDLit" ltTD ++ + litText "certLtLoLit" (ptrim certLtLo) end GenFloorCertLit -#eval IO.FS.writeFile "LnProof/Cert/FloorCertLit.lean" GenFloorCertLit.fileText +#eval do + reconcileOutputs "LnProof/Cert" + ["FloorCertLit", "FloorCertGeUpLit", "FloorCertGeLoLit", "FloorCertLtUpLit", + "FloorCertLtLoLit"] + ["FloorCertGeUpLit.lean", "FloorCertGeLoLit.lean", "FloorCertLtUpLit.lean", + "FloorCertLtLoLit.lean"] + IO.FS.writeFile "LnProof/Cert/FloorCertGeUpLit.lean" GenFloorCertLit.geUpText + IO.FS.writeFile "LnProof/Cert/FloorCertGeLoLit.lean" GenFloorCertLit.geLoText + IO.FS.writeFile "LnProof/Cert/FloorCertLtUpLit.lean" GenFloorCertLit.ltUpText + IO.FS.writeFile "LnProof/Cert/FloorCertLtLoLit.lean" GenFloorCertLit.ltLoText diff --git a/formal/ln/LnProof/LnProof/Error/GeBridge.lean b/formal/ln/LnProof/LnProof/Error/GeBridge.lean index 639d1be97..a51291044 100644 --- a/formal/ln/LnProof/LnProof/Error/GeBridge.lean +++ b/formal/ln/LnProof/LnProof/Error/GeBridge.lean @@ -5,7 +5,7 @@ import LnProof.Error.FactoredCap /-! # Bridge from the ge error cell cover to the `sumGE` inequality -`errGe_nonneg` proves `0 ≤ evalPoly certErrGeLit m` over the ge domain. Here we +`errGe_nonnegOn` proves `0 ≤ evalPoly certErrGeLit m` over the ge domain. Here we identify the literal cert with the symbolic margin `certErrGe = expMarginPoly 22 geTN2b geTD2b (errGeK·(m+1)) errGeW` (an `evalPoly_ext` identity, exactly as `geLo_eval_eq`), and feed the existing @@ -89,6 +89,12 @@ theorem errGe_eval_eq : ∀ x : Int, evalPoly certErrGe x = evalPoly certErrGeLi evalPoly_polyPow, evalPoly_expPolyNum, eval01] decide +kernel +theorem certErrGe_nonnegOn : + NonnegOn certErrGe 56022770974786139918731938273 79228162514264337593543950335 := by + intro x hlo hhi + rw [errGe_eval_eq] + exact errGe_nonnegOn x hlo hhi + /-- The ge cell cover proves the `sumGE`-shaped budget inequality. -/ theorem errGe_sumGE {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : sumGE 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat @@ -97,8 +103,7 @@ theorem errGe_sumGE {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : simp only [Sc] at h1; omega have hle : (m : Int) ≤ 79228162514264337593543950335 := by simp only [MHI] at h2; omega - have hnn : 0 ≤ evalPoly certErrGe (m : Int) := by - rw [errGe_eval_eq]; exact errGe_nonneg hge hle + have hnn : 0 ≤ evalPoly certErrGe (m : Int) := certErrGe_nonnegOn _ hge hle have hyp : 0 ≤ evalPoly (polyScale errGeK [1, 1]) (m : Int) := by rw [evalPoly_polyScale] refine Int.mul_nonneg (by unfold errGeK; decide) ?_ diff --git a/formal/ln/LnProof/LnProof/Error/LtBridge.lean b/formal/ln/LnProof/LnProof/Error/LtBridge.lean index 059c7e13b..926dc77ec 100644 --- a/formal/ln/LnProof/LnProof/Error/LtBridge.lean +++ b/formal/ln/LnProof/LnProof/Error/LtBridge.lean @@ -5,7 +5,7 @@ import LnProof.Error.LtFactoredCap /-! # Bridge from the lt error cell cover to the reduced error inequality -`errLt_nonneg` proves `0 ≤ evalPoly certErrLtLit m` over the lt domain +`errLt_nonnegOn` proves `0 ≤ evalPoly certErrLtLit m` over the lt domain `[2^95, Sc-46]`. Here we identify the literal cert with the symbolic margin `certErrLt = errLtW·23!·ltTD^23 − errLtK·(m+1)·G` (an `evalPoly_ext` identity, exactly as `ltLo_eval_eq`), and read off the reduced inequality that @@ -95,6 +95,12 @@ theorem errLt_eval_eq : ∀ x : Int, evalPoly certErrLt x = evalPoly certErrLtLi evalPoly_polyPow, evalPoly_expPolyNum] decide +kernel +theorem certErrLt_nonnegOn : + NonnegOn certErrLt 39614081257132168796771975168 56022770974786139918731938181 := by + intro x hlo hhi + rw [errLt_eval_eq] + exact errLt_nonnegOn x hlo hhi + /-- The lt cell cover proves the c-independent error-bound inequality, via the `evalPoly_ext` identity and the direct `polySub` margin (no `sumGE`). -/ theorem errLt_reduced_ineq {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : @@ -113,8 +119,7 @@ theorem errLt_reduced_ineq {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : have h := ltTD_nonneg hw1 hw2; rw [evalCertLtTD] at h; omega have hTN : 0 ≤ evalPoly ltTN (m : Int) := ltTN_nonneg hw1 hw2 have herrK : (0 : Int) ≤ errLtK := by unfold errLtK; decide - have hcert : 0 ≤ evalPoly certErrLt (m : Int) := by - rw [errLt_eval_eq]; exact errLt_nonneg hw1 hw2 + have hcert : 0 ≤ evalPoly certErrLt (m : Int) := certErrLt_nonnegOn _ hw1 hw2 -- expand the symbolic margin; cast the bracket evaluations to `Nat` unfold certErrLt at hcert simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, diff --git a/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean b/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean index 6b09f3bb3..2ec63568c 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean @@ -1,5 +1,5 @@ import LnProof.Floor.CertDefs -import LnProof.Cert.FloorCertLit +import LnProof.Cert.FloorCertGeLoLit import Common.Foundation.Kronecker import LnProof.Cert.FloorCertGeLoC00 import LnProof.Cert.FloorCertGeLoC01 @@ -77,8 +77,9 @@ theorem geLo_eval_eq : ∀ x : Int, evalPoly certGeLo x = evalPoly certGeLoLit x evalPoly_polyPow, evalPoly_expPolyNum, eval01] decide +kernel -theorem geLo_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m ≤ 79228162514264337593543950335) : - 0 ≤ evalPoly certGeLo m := by +theorem geLo_nonnegOn : + NonnegOn certGeLo 56022770974786139918731938273 79228162514264337593543950335 := by + intro m h1 h2 have hev := geLo_eval_eq m rw [hev] rcases Int.lt_or_le m (62244752178564837341413711044 + 1) with h | h @@ -113,4 +114,8 @@ theorem geLo_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m · exact checkCoverK_sound _ _ _ _ _ geLo_cell14 m (by omega) (by omega) exact checkCoverK_sound _ _ _ _ _ geLo_cell15 m (by omega) h2 +theorem geLo_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) + (h2 : m ≤ 79228162514264337593543950335) : 0 ≤ evalPoly certGeLo m := + geLo_nonnegOn m h1 h2 + end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean b/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean index 18e89c32d..0d1938d70 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean @@ -1,5 +1,5 @@ import LnProof.Floor.CertDefs -import LnProof.Cert.FloorCertLit +import LnProof.Cert.FloorCertGeUpLit import Common.Foundation.Kronecker import LnProof.Cert.FloorCertGeUpC00 import LnProof.Cert.FloorCertGeUpC01 @@ -87,8 +87,9 @@ theorem geUp_eval_eq : ∀ x : Int, evalPoly certGeUp x = evalPoly certGeUpLit x evalPoly_polyPow, evalPoly_expPolyNum, eval01] decide +kernel -theorem geUp_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m ≤ 79228162514264337593543950335) : - 0 ≤ evalPoly certGeUp m := by +theorem geUp_nonnegOn : + NonnegOn certGeUp 56022770974786139918731938273 79228162514264337593543950335 := by + intro m h1 h2 have hev := geUp_eval_eq m rw [hev] rcases Int.lt_or_le m (59266081817351235913474286845 + 1) with h | h @@ -121,4 +122,8 @@ theorem geUp_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m · exact checkCoverK_sound _ _ _ _ _ geUp_cell13 m (by omega) (by omega) exact checkCoverK_sound _ _ _ _ _ geUp_cell14 m (by omega) h2 +theorem geUp_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) + (h2 : m ≤ 79228162514264337593543950335) : 0 ≤ evalPoly certGeUp m := + geUp_nonnegOn m h1 h2 + end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean b/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean index b5c0528e5..4909c6ff2 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean @@ -1,5 +1,5 @@ import LnProof.Floor.CertDefs -import LnProof.Cert.FloorCertLit +import LnProof.Cert.FloorCertLtLoLit import Common.Foundation.Kronecker import LnProof.Cert.FloorCertLtLoC00 import LnProof.Cert.FloorCertLtLoC01 @@ -88,8 +88,9 @@ theorem ltLo_eval_eq : ∀ x : Int, evalPoly certLtLo x = evalPoly certLtLoLit x evalPoly_polyPow, evalPoly_expPolyNum, eval01] decide +kernel -theorem ltLo_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) (h2 : m ≤ 56022770974786139918731938181) : - 0 ≤ evalPoly certLtLo m := by +theorem ltLo_nonnegOn : + NonnegOn certLtLo 39614081257132168796771975168 56022770974786139918731938181 := by + intro m h1 h2 have hev := ltLo_eval_eq m rw [hev] rcases Int.lt_or_le m (39691340757316876069324712922 + 1) with h | h @@ -124,4 +125,8 @@ theorem ltLo_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) (h2 : m · exact checkCoverK_sound _ _ _ _ _ ltLo_cell14 m (by omega) (by omega) exact checkCoverK_sound _ _ _ _ _ ltLo_cell15 m (by omega) h2 +theorem ltLo_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) + (h2 : m ≤ 56022770974786139918731938181) : 0 ≤ evalPoly certLtLo m := + ltLo_nonnegOn m h1 h2 + end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean b/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean index 1408cc3b0..bf04e5e23 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean @@ -1,5 +1,5 @@ import LnProof.Floor.CertDefs -import LnProof.Cert.FloorCertLit +import LnProof.Cert.FloorCertLtUpLit import Common.Foundation.Kronecker import LnProof.Cert.FloorCertLtUpC00 import LnProof.Cert.FloorCertLtUpC01 @@ -73,8 +73,9 @@ theorem ltUp_eval_eq : ∀ x : Int, evalPoly certLtUp x = evalPoly certLtUpLit x evalPoly_polyPow, evalPoly_expPolyNum, eval01] decide +kernel -theorem ltUp_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) (h2 : m ≤ 56022770974786139918731938181) : - 0 ≤ evalPoly certLtUp m := by +theorem ltUp_nonnegOn : + NonnegOn certLtUp 39614081257132168796771975168 56022770974786139918731938181 := by + intro m h1 h2 have hev := ltUp_eval_eq m rw [hev] rcases Int.lt_or_le m (39982094489912265292386939330 + 1) with h | h @@ -111,4 +112,8 @@ theorem ltUp_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) (h2 : m · exact checkCoverK_sound _ _ _ _ _ ltUp_cell15 m (by omega) (by omega) exact checkCoverK_sound _ _ _ _ _ ltUp_cell16 m (by omega) h2 +theorem ltUp_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) + (h2 : m ≤ 56022770974786139918731938181) : 0 ≤ evalPoly certLtUp m := + ltUp_nonnegOn m h1 h2 + end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean b/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean index 3dfd35bed..03a7f65ef 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean @@ -1,5 +1,3 @@ -import LnProof.Cert.FloorCertLit - /-! Generated tightened floor-certificate literals used by the exact ln error-bound proof. The lists are materialized so Kronecker cell checks do not rebuild the source diff --git a/formal/ln/LnProof/LnProof/Floor/Window.lean b/formal/ln/LnProof/LnProof/Floor/Window.lean index 42fcda60e..d6513e9ce 100644 --- a/formal/ln/LnProof/LnProof/Floor/Window.lean +++ b/formal/ln/LnProof/LnProof/Floor/Window.lean @@ -115,7 +115,7 @@ theorem x1capGeUpF {m : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) : 560227709747861399187319382270000000000000000000000000000000 := by rcases Nat.lt_or_ge m (Sc + 46) with hw | ho · exact (wGe_facts h1 (by omega)).2.1 - · have hup := geUp_nonneg (m := (m : Int)) + · have hup := geUp_nonnegOn (m : Int) (by simp only [Sc] at ho; omega) (by simp only [MHI] at h2; omega) have h := x1capGeUp ho h2 hup rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS @@ -128,7 +128,7 @@ theorem x1capGeLoF {m : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) : 560227709747861399187319382270000000000000000000000000000000 := by rcases Nat.lt_or_ge m (Sc + 46) with hw | ho · exact (wGe_facts h1 (by omega)).2.2 - · have hlo := geLo_nonneg (m := (m : Int)) + · have hlo := geLo_nonnegOn (m : Int) (by simp only [Sc] at ho; omega) (by simp only [MHI] at h2; omega) have h := x1capGeLo ho h2 hlo rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS @@ -140,7 +140,7 @@ theorem x1capLtUpF {m : Nat} (h1 : MLO ≤ m) (h2 : m < Sc) : 560227709747861399187319382270000000000000000000000000000000 (m * 10000000000000000000000000003382) := by rcases Nat.lt_or_ge m (Sc - 45) with ho | hw - · have hup := ltUp_nonneg (m := (m : Int)) + · have hup := ltUp_nonnegOn (m : Int) (by simp only [MLO] at h1; omega) (by simp only [Sc] at ho ⊢; omega) have h := x1capLtUp h1 (by simp only [Sc] at ho ⊢; omega) hup rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS @@ -153,7 +153,7 @@ theorem x1capLtLoF {m : Nat} (h1 : MLO ≤ m) (h2 : m < Sc) : 560227709747861399187319382270000000000000000000000000000000 (m * 9999999999999999999999999996615) := by rcases Nat.lt_or_ge m (Sc - 45) with ho | hw - · have hlo := ltLo_nonneg (m := (m : Int)) + · have hlo := ltLo_nonnegOn (m : Int) (by simp only [MLO] at h1; omega) (by simp only [Sc] at ho ⊢; omega) have h := x1capLtLo h1 (by simp only [Sc] at ho ⊢; omega) hlo rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS From ca3562f0e133a94e3e2bb3d9071ad7298114d19e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Sat, 11 Jul 2026 00:03:48 +0200 Subject: [PATCH 079/107] Gate shared certificate soundness axioms Co-Authored-By: OpenAI Codex --- formal/common/Common.lean | 1 + formal/common/Common/AxiomCheck.lean | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 formal/common/Common/AxiomCheck.lean diff --git a/formal/common/Common.lean b/formal/common/Common.lean index 0f81f2dbb..b4079496a 100644 --- a/formal/common/Common.lean +++ b/formal/common/Common.lean @@ -19,3 +19,4 @@ import Common.Seam.RealExpBridge import Common.GenCover import Common.GenBernstein import Common.CertificateExamples +import Common.AxiomCheck diff --git a/formal/common/Common/AxiomCheck.lean b/formal/common/Common/AxiomCheck.lean new file mode 100644 index 000000000..a2249b54f --- /dev/null +++ b/formal/common/Common/AxiomCheck.lean @@ -0,0 +1,17 @@ +import Common.Foundation.KroneckerShift +import Common.Foundation.Bernstein + +/-! +# Axiom gate + +The public certificate soundness theorems must remain independent of +nonstandard axioms. +-/ + +/-- info: 'Common.Poly.checkCoverK_nonnegOn' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms Common.Poly.checkCoverK_nonnegOn + +/-- info: 'Common.Poly.checkBernsteinKWithWitness_nonnegOn' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms Common.Poly.checkBernsteinKWithWitness_nonnegOn From 731f34d87a7e82fc9c1819ab53708dd8a462010a Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Sun, 12 Jul 2026 19:19:58 +0200 Subject: [PATCH 080/107] Certify mulExpRay through 127-bit magnitudes Co-Authored-By: OpenAI Codex --- formal/exp/ExpProof/ExpProof/Floor/CapsV.lean | 7 +- .../ExpProof/ExpProof/Floor/R0BoundHolds.lean | 6 +- formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean | 188 ++++--- .../ExpProof/ExpProof/Floor/R0ExpUnder.lean | 515 ++++++++++-------- .../ExpProof/ExpProof/Floor/RoundTrip.lean | 13 +- formal/exp/ExpProof/ExpProof/Mono/Consts.lean | 15 +- formal/exp/ExpProof/ExpProof/Mono/Cross.lean | 22 +- .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 14 +- formal/exp/ExpProof/ExpProof/Mono/Quot.lean | 26 +- .../exp/ExpProof/ExpProof/Mono/StepMono.lean | 2 +- formal/exp/ExpProof/ExpProof/Mul/Accum.lean | 30 +- formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 137 ++--- formal/exp/ExpProof/ExpProof/Mul/Joint.lean | 116 ++-- formal/exp/ExpProof/ExpProof/Mul/Shell.lean | 146 ++--- .../exp/ExpProof/ExpProof/Mul/Transport.lean | 298 +++++----- formal/exp/ExpProof/ExpProof/Mul/XMono.lean | 54 +- formal/exp/ExpProof/ExpProof/Mul/YMono.lean | 96 ++-- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 183 ++++--- .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 167 ++---- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 186 +++---- formal/exp/ExpProof/ExpProof/Seam/Value.lean | 6 +- formal/exp/ExpProof/ExpProof/Theorems.lean | 131 ++++- formal/yul/YulImporter.lean | 26 +- src/vendor/Exp.sol | 102 ++-- test/0.8.34/Exp.t.sol | 41 +- 25 files changed, 1276 insertions(+), 1251 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean b/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean index 0abc59182..80bc83ec3 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/CapsV.lean @@ -3,8 +3,7 @@ import Mathlib.Tactic.Ring import Mathlib.Tactic.Positivity import Mathlib.Algebra.Order.Floor.Defs import Common.Foundation.ExpSum -import ExpProof.Cert.ExpVUp -import ExpProof.Cert.ExpVLo +import ExpProof.Cert.ExpVTaylor import ExpProof.Cert.ExpVNum import ExpProof.Cert.ExpVDenM1 @@ -144,7 +143,7 @@ theorem capExpUp {t : Int} (h1 : 0 ≤ t) (h2 : t ≤ (H129 : Int)) : have hHQ : 2 * H129 < 29 * Qexp := by unfold H129 Qexp; norm_num omega · rw [htn, hyn, hwn, Qexp_eq] - have h := expVUp_nonneg h1 h2 + have h := expVUp_nonnegOn t h1 h2 rw [evalCertExpUp] at h unfold fact28Q28 at h rw [Qexp_eq] at h @@ -173,7 +172,7 @@ theorem capExpLo {t : Int} (h1 : 0 ≤ t) (h2 : t ≤ (H129 : Int)) : have hwn : ((evalPoly wLB t).toNat : Int) = evalPoly wLB t := Int.toNat_of_nonneg hwlb refine capLB27_of_int ?_ rw [htn, hyn, hwn, Qexp_eq] - have h := expVLo_nonneg h1 h2 + have h := expVLo_nonnegOn t h1 h2 rw [evalCertExpLo] at h unfold fact27Q27 at h rw [Qexp_eq] at h diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean b/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean index 268b61ab2..7889737b8 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean @@ -12,7 +12,7 @@ about the real pre-floor accumulator unconditionally and axiom-clean, via the oc `E·2^s = WAD·2⁶⁷·exp(rt)` (`WAD·2⁶⁷ = scaleQ67`; `s = 67 − k`, the closing shift; `k ≤ 65` so `s ≥ 2`). -* `accumReal_over` ⟸ `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` and `(5¹⁸/2⁴¹)·B ≤ MARGIN = 1`; +* `accumReal_over` ⟸ `r0 ≤ scaleQ67·exp(rt) + B` and `B < MARGIN = 1`; * `accumReal_under` ⟸ `scaleQ67·exp(rt) ≤ r0 + U` (`U = 2993/1000`) and `U + MARGIN < 2² ≤ 2^s`. @@ -44,9 +44,7 @@ theorem accumReal_over (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 rw [hfold] have hwad : (WAD : Real) = (10 ^ 18 : Real) := by unfold WAD; norm_num rw [hwad] - -- (5¹⁸/2⁴¹)·B ≤ 1 = MARGIN - have hBM : (3814697265625 : Real) * 5737291786393199862 / - (10000000000000000000 * 2199023255552) ≤ 1 := by norm_num + have hBM := over_budget_image_lt_one linarith [hover, hBM] rw [hAeq, div_le_iff₀ hps] linarith [hbound] diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean index 584541e13..8f4792c79 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean @@ -9,16 +9,15 @@ import Mathlib.Analysis.SpecialFunctions.Pow.Real # The per-point `r0`-vs-`exp` bridge (never-over side) This module bounds the scaled quotient `r0ScaledTree scale x` above by `scale·exp(rt)` -plus the never-over budget image `(5¹⁸/2⁴¹)·B`, for any scale `2¹²⁵ ≤ scale ≤ scaleQ67 = -10¹⁸·2⁶⁷` (the budget is certified at the maximal scale; smaller scales only shrink the true -error) +plus twice the Q126 never-over budget, for any scale `2¹²⁵ ≤ scale ≤ scaleMax = 2¹²⁷ − 1` +(the budget is certified at the maximal scale; smaller scales only shrink the true error) (`rt = X/RAY − k·ln2` the reduced argument), the analytic content the floor brackets (`Floor.R0BoundHolds`) consume. The chain has four links: 1. **`r0` vs `ê(v)`** — Horner stage truncation and the closing `div` floor only: the runtime accumulators bracket the exact integer polynomials (`evTree_bracket`/`odTree_bracket`), and the shared even truncation cancels through the floor, leaving the jitter - `≤ 2170557036555806152/10¹⁹`; + `≤ 1102011232081646123/10¹⁹`; 2. **`ê(v)` vs `ê(t²)`** — the argument-granularity link (`Floor.GranV`): one `v`-grid grain, `≤ 3290521163436398582/10¹⁹` on this half (the 32-piece certified envelope); 3. **`ê(t²)` vs `exp(t/2¹²⁸)`** — the `2⁻¹³²`-nudged Taylor cut (`Floor.CapsV`), the `Mp` factor @@ -26,10 +25,10 @@ error) 4. **`exp(t/2¹²⁸)` vs `exp(rt)`** — the reduced-argument gap (`Floor.Reduce`), `≤ 55242717280199026/10¹⁹`. -The total is the budget `B = 5737291786393199862/10¹⁹`, whose image `(5¹⁸/2⁴¹)·B ≈ 0.9953` -sits below `MARGIN = 1`. On the `t ≤ 0` -half link 2 is free (the grain moves `ê` the other way) and links 3–4 shrink (`ê ≤ 1`), so the same -`B` covers both halves. +The nonnegative-half total is `4668745981919039833/10¹⁹ < 1/2`, so doubling it for every +`scale < 2¹²⁷` stays below `MARGIN = 1`. On the `t ≤ 0` half link 2 is free (the grain moves `ê` +the other way) and links 3–4 shrink (`ê ≤ 1`), giving the smaller total +`2446770622956801280/10¹⁹`. -/ namespace ExpYul @@ -45,8 +44,8 @@ set_option exponentiation.threshold 2000 /-! ## The `div` floor sandwich -/ /-- The scaled quotient is the integer floor: `r0·den_rt ≤ scale·num_rt < (r0+1)·den_rt` with -`num_rt = ev + tod`, `den_rt = ev − tod`, at any `scale ≤ scaleQ67`. -/ -theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) +`num_rt = ev + tod`, `den_rt = ev − tod`, at any `scale ≤ scaleMax`. -/ +theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (r0ScaledTree scale x) * ((evTree x : Int) - int256 (todTree x)) ≤ (scale : Int) * ((evTree x : Int) + int256 (todTree x)) ∧ @@ -75,10 +74,10 @@ theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < have hnumnat128 : num < 2 ^ 129 := by have hh : ((num : Nat) : Int) < 2 ^ 129 := by rw [hnumeq] at hnumlt128; exact hnumlt128 exact_mod_cast hh - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) have hfit : scale * num < 2 ^ 256 := by - have h1 : scale * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hnumnat128) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h1 : scale * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hnumnat128) + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hmulval : evmMul scale num = scale * num := evmMul_eq_nat hsw hnumw hfit have hdennat : 0 < den := by @@ -144,7 +143,7 @@ theorem den_ge_194 {x : Nat} (hx : x < 2 ^ 256) omega /-- On the nonpositive half `tod ≤ 0` and hence `r0 ≤ scale` (num ≤ den). -/ -theorem r0_le_scale_neg {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) +theorem r0_le_scale_neg {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (r0ScaledTree scale x) ≤ (scale : Int) := by @@ -246,9 +245,9 @@ theorem tOd_bracket_neg {x : Nat} (hx : x < 2 ^ 256) /-! ## Link 1 (over side): `r0` vs the grid rational, shared-`Ev` cancellation -/ -/-- **Joint link-1 over (nonneg half, `r0 ≥ scaleQ67`)**: the shared even truncation cancels through -the floor, `r0·DENv − scaleQ67·NUMv ≤ Wev·2⁵⁹⁰·(r0 − scaleQ67)`. -/ -theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- **Joint link-1 over (nonnegative half, `r0 ≥ scale`)**: the shared even truncation cancels +through the floor, `r0·DENv − scale·NUMv ≤ Wev·2⁵⁹⁰·(r0 − scale)`. -/ +theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) (hr0ge : (scale : Int) ≤ int256 (r0ScaledTree scale x)) : @@ -281,8 +280,8 @@ theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scal mul_nonpos_of_nonneg_of_nonpos (by positivity) hfloor nlinarith [hterm1, hterm2, hfloor638] -/-- **Link-1 over (nonneg half, `r0 ≤ scaleQ67`)**: the residue is nonpositive outright. -/ -theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- **Link-1 over (nonnegative half, `r0 ≤ scale`)**: the residue is nonpositive outright. -/ +theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) (hr0le : int256 (r0ScaledTree scale x) ≤ (scale : Int)) : @@ -317,9 +316,9 @@ theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scal mul_nonpos_of_nonneg_of_nonpos (by positivity) hfloor nlinarith [hterm1, hterm2, hfloor638] -/-- **Link-1 over (nonpositive half)**: the even truncation drops (`r0 ≤ scaleQ67`); the odd truncation -survives attenuated to the `t`-scale: `r0·DENv − scaleQ67·NUMv ≤ Wod·2⁴⁸⁰·(−t)·(r0 + scaleQ67)`. -/ -theorem link1_over_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- **Link-1 over (nonpositive half)**: the even truncation drops (`r0 ≤ scale`); the odd truncation +survives attenuated to the `t`-scale: `r0·DENv − scale·NUMv ≤ Wod·2⁴⁸⁰·(−t)·(r0 + scale)`. -/ +theorem link1_over_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) - @@ -752,7 +751,7 @@ theorem num_le_145_den {x : Nat} (hx : x < 2 ^ 256) nlinarith [hceil, hden] /-- The quotient cap: `10⁴·(r0 − scale) ≤ 4146·scale` on the nonneg half. -/ -theorem r0_cap {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) +theorem r0_cap {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 10000 * (int256 (r0ScaledTree scale x) - (scale : Int)) ≤ 4146 * (scale : Int) := by @@ -776,20 +775,19 @@ theorem r0_cap {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) /-! ## The per-point never-over (nonnegative half) -/ -/-- The link-1 jitter divided by `DENv` stays inside its budget (nonneg half): -`Wev·2⁵⁹⁰·(r0 − scaleQ67)/DENv ≤ (5¹⁸/2⁴⁰)·2170557036555806152/10¹⁹`. -/ -theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) +/-- The link-1 jitter divided by `DENv` stays inside its budget on the nonnegative half. -/ +theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (72572599271425 : Real) * 2 ^ 591 * ((int256 (r0ScaledTree scale x) : Real) - (scale : Real)) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ - 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by + 2 * 1102011232081646123 / 10000000000000000000 := by obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW - have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num + have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by + unfold scaleMax; norm_num rw [hs] at h exact h set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -803,11 +801,13 @@ theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < mul_nonpos_of_nonneg_of_nonpos (by positivity) hle0 have : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) / (DENv v t : Real) ≤ 0 := div_nonpos_of_nonpos_of_nonneg hnumneg (le_of_lt hDR) - have hpos : (0:Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by positivity + have hpos : (0 : Real) ≤ 2 * 1102011232081646123 / 10000000000000000000 := by + positivity linarith [this, hpos] · rw [div_le_iff₀ hDR] have hcap := r0_cap hshi hx hW htnn - have hcapR : (r0 : Real) - (scale : Real) ≤ 4146 * 0x6f05b59d3b2000000000000000000000 / 10000 := by + have hcapR : (r0 : Real) - (scale : Real) ≤ + 4146 * 0x7fffffffffffffffffffffffffffffff / 10000 := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hcap push_cast at h linarith [h, hshiR] @@ -824,33 +824,35 @@ theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < push_cast at h linarith [h] have hnum_le : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) ≤ - (72572599271425 : Real) * 2 ^ 591 * (4146 * 0x6f05b59d3b2000000000000000000000 / 10000) := + (72572599271425 : Real) * 2 ^ 591 * + (4146 * 0x7fffffffffffffffffffffffffffffff / 10000) := mul_le_mul_of_nonneg_left hcapR (by positivity) - have hbudget : (72572599271425 : Real) * 2 ^ 591 * (4146 * 0x6f05b59d3b2000000000000000000000 / 10000) ≤ - (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * + have hbudget : (72572599271425 : Real) * 2 ^ 591 * + (4146 * 0x7fffffffffffffffffffffffffffffff / 10000) ≤ + (2 * 1102011232081646123 / 10000000000000000000) * ((2:Real) ^ 637 * (330077261860684142693791478386293573392 - 2)) := by norm_num calc (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) - ≤ (72572599271425 : Real) * 2 ^ 591 * (4146 * 0x6f05b59d3b2000000000000000000000 / 10000) := hnum_le - _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * + ≤ (72572599271425 : Real) * 2 ^ 591 * + (4146 * 0x7fffffffffffffffffffffffffffffff / 10000) := hnum_le + _ ≤ (2 * 1102011232081646123 / 10000000000000000000) * ((2:Real) ^ 637 * (330077261860684142693791478386293573392 - 2)) := hbudget - _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * + _ ≤ (2 * 1102011232081646123 / 10000000000000000000) * (DENv v t : Real) := mul_le_mul_of_nonneg_left hDENlowR (by norm_num) -/-- **The per-point never-over (nonneg half).** `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` with the -four-link budget `B = 5737291786393199862/10¹⁹` itemized in the module header. -/ -theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- **The per-point never-over on the nonnegative half.** -/ +theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + 2 * 4668745981919039833 / 10000000000000000000 := by obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num + have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by + unfold scaleMax; norm_num rw [hs] at h exact h set t := int256 (tTree x) with htdef @@ -869,14 +871,15 @@ theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : sc exact_mod_cast this -- link 1: r0 ≤ scale·Qv + jitter have hlink1 : (r0 : Real) ≤ (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + - 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by + 2 * 1102011232081646123 / 10000000000000000000 := by rcases le_or_gt r0 (scale : Int) with hsm | hbg · have hi := link1_over_small hslo hshi hx hW htnn hsm have hiR : (r0 : Real) * (DENv v t : Real) ≤ (scale : Real) * (NUMv v t : Real) := by have := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hi; push_cast at this; linarith [this] have hr0le : (r0 : Real) ≤ (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) := by rw [mul_div_assoc', le_div_iff₀ hDR]; linarith [hiR] - have hBJnn : (0:Real) ≤ 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by positivity + have hBJnn : (0 : Real) ≤ 2 * 1102011232081646123 / 10000000000000000000 := by + positivity linarith [hr0le, hBJnn] · have hi := link1_over_tight hslo hshi hx hW htnn (le_of_lt hbg) have hjointR : (r0 : Real) * (DENv v t : Real) - (scale : Real) * (NUMv v t : Real) ≤ @@ -956,31 +959,31 @@ theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : sc linarith [hgran, hNEMp, hcMp, hEtErt] have h234S := mul_le_mul_of_nonneg_left h234 hsRnn have hCs : (scale : Real) * (3566734749837393710 / 10000000000000000000) ≤ - (0x6f05b59d3b2000000000000000000000 : Real) * (3566734749837393710 / 10000000000000000000) := + (0x7fffffffffffffffffffffffffffffff : Real) * + (3566734749837393710 / 10000000000000000000) := mul_le_mul_of_nonneg_right hshiR (by positivity) rw [hErtdef] at * nlinarith [hlink1, h234S, hCs] /-! ## The per-point never-over (nonpositive half) -/ -/-- The link-1 jitter budget on the nonpositive half: -`Wod·2⁴⁸⁰·(−t)·(r0 + scaleQ67)/DENv ≤ (5¹⁸/2⁴⁰)·2170557036555806152/10¹⁹`. -/ +/-- The link-1 jitter budget on the nonpositive half. -/ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) + (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (269746241 : Real) * 2 ^ 480 * (-(int256 (tTree x) : Real)) * ((int256 (r0ScaledTree scale x) : Real) + (scale : Real)) / (DENv (vTree x) (int256 (tTree x)) : Real) ≤ - 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by + 2 * 2170557036555806152 / 10000000000000000000 := by obtain ⟨htlo, _⟩ := tTree_in_cert_domain_wide hx hW have hr0le := r0_le_scale_neg hshi hx hW htneg obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW have hDEN_ge := DENv_ge_ev_neg hx hW htneg obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 - have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num + have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by + unfold scaleMax; norm_num rw [hs] at h exact h set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -1014,12 +1017,13 @@ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) have hsnn : (0:Real) ≤ (scale : Real) := by positivity linarith [this, hsnn] have hr0pH : (r0 : Real) + (scale : Real) ≤ - 2 * 0x6f05b59d3b2000000000000000000000 := by + 2 * 0x7fffffffffffffffffffffffffffffff := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h linarith [h, hshiR] have hnum_le : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) ≤ - (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * (2 * (0x6f05b59d3b2000000000000000000000 : Real)) := by + (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * + (2 * (0x7fffffffffffffffffffffffffffffff : Real)) := by have h1 : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 := mul_le_mul_of_nonneg_left hntH (by positivity) @@ -1029,32 +1033,34 @@ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) push_cast at h linarith [h] have hbudget : (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * - (2 * (0x6f05b59d3b2000000000000000000000 : Real)) ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * + (2 * (0x7fffffffffffffffffffffffffffffff : Real)) ≤ + (2 * 2170557036555806152 / 10000000000000000000) * ((2:Real) ^ 637 * 415147853590918758559635130244235626256) := by norm_num calc (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) - ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * (2 * (0x6f05b59d3b2000000000000000000000 : Real)) := + ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * + (2 * (0x7fffffffffffffffffffffffffffffff : Real)) := hnum_le - _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * + _ ≤ (2 * 2170557036555806152 / 10000000000000000000) * ((2:Real) ^ 637 * 415147853590918758559635130244235626256) := hbudget - _ ≤ (3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552)) * (DENv v t : Real) := + _ ≤ (2 * 2170557036555806152 / 10000000000000000000) * (DENv v t : Real) := mul_le_mul_of_nonneg_left hDENlowR (by norm_num) -/-- **The per-point never-over (nonpositive half).** The granularity is free here; the `Mp` factor -and reduced-argument gap shrink (`Et ≤ 1`), so the same budget `B` covers the half. -/ +/-- **The per-point never-over on the nonpositive half.** The granularity is free here; the `Mp` +factor and reduced-argument gap shrink because `Et ≤ 1`. -/ theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) + (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + 2 * 2446770622956801280 / 10000000000000000000 := by have htdom := tdom_neg hx hW htneg have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num + have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by + have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi + have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by + unfold scaleMax; norm_num rw [hs] at h exact h set t := int256 (tTree x) with htdef @@ -1067,7 +1073,7 @@ theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by exact_mod_cast hDEpos -- link 1: r0 ≤ scale·Qv + jitter have hlink1 : (r0 : Real) ≤ (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + - 3814697265625 * 2170557036555806152 / (10000000000000000000 * 2199023255552) := by + 2 * 2170557036555806152 / 10000000000000000000 := by have hi := link1_over_neg hslo hshi hx hW htneg have hiR : (r0 : Real) * (DENv v t : Real) - (scale : Real) * (NUMv v t : Real) ≤ (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) := by @@ -1143,28 +1149,42 @@ theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) linarith [hgranR, hNEMp, hcMp, hEtErt] have h234S := mul_le_mul_of_nonneg_left h234 hsRnn have hCs : (scale : Real) * (276213586400995128 / 10000000000000000000) ≤ - (0x6f05b59d3b2000000000000000000000 : Real) * (276213586400995128 / 10000000000000000000) := + (0x7fffffffffffffffffffffffffffffff : Real) * + (276213586400995128 / 10000000000000000000) := mul_le_mul_of_nonneg_right hshiR (by positivity) rw [hErtdef] at * nlinarith [hlink1, h234S, hCs] -/-- **Per-point never-over (tight, any sign):** `r0 ≤ scale·exp(rt) + (5¹⁸/2⁴⁰)·B` -(the budget's image is strictly below `MARGIN = 1`; the budget is certified at the maximal -scale, and smaller scales only shrink the true error). -/ +theorem over_budget_nonneg_lt_half : + (4668745981919039833 / 10000000000000000000 : Real) < 1 / 2 := by + norm_num + +theorem over_budget_nonpos_lt_half : + (2446770622956801280 / 10000000000000000000 : Real) < 1 / 2 := by + norm_num + +theorem over_budget_image_lt_one : + (2 * 4668745981919039833 / 10000000000000000000 : Real) < 1 := by + norm_num + +/-- **Per-point never-over, for either sign.** The Q126 budget is below one half, and +`scale < 2¹²⁷`, so its image is below the one-unit runtime margin. -/ theorem r0Scaled_real_over_within {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) : - (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : + (int256 (r0ScaledTree scale x) : Real) ≤ + (scale : Real) * Real.exp (reducedArg x) + + 2 * 4668745981919039833 / 10000000000000000000 := by rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg · exact r0_real_over_tight hslo hshi hx hW htnn - · exact r0_real_over_tight_neg hslo hshi hx hW (le_of_lt htneg) + · have h := r0_real_over_tight_neg hslo hshi hx hW (le_of_lt htneg) + nlinarith [h] theorem r0_real_over_within_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + 2 * 4668745981919039833 / 10000000000000000000 := by have h := r0Scaled_real_over_within (scale := scaleQ67) (by unfold scaleQ67; norm_num) - (le_refl _) hx hW + scaleQ67_le_scaleMax hx hW rw [r0Tree_eq_scaled] have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by unfold scaleQ67; norm_num @@ -1174,7 +1194,7 @@ theorem r0_real_over_within_wide {x : Nat} (hx : x < 2 ^ 256) theorem r0_real_over_within {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := + 2 * 4668745981919039833 / 10000000000000000000 := r0_real_over_within_wide hx (wideRegion_of_wad hC hC0) /-! ## The octave real identity `E·2^(68−k) = WAD·2⁶⁸·exp(rt)` diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean index 4cf8aa1aa..cd12ec9b2 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean @@ -1,25 +1,23 @@ import ExpProof.Floor.R0Exp +import ExpProof.Cert.ExpUnderCarry /-! # The deficit (under) side of the per-point `r0`-vs-`exp` bridge, and the seam bound This module contains the counterpart to the never-over `r0Scaled_real_over_within`: the per-point -deficit `scale·exp(rt) ≤ r0 + 2993/1000` (`r0Scaled_real_under_within`), both signs and any scale -`2¹²⁵ ≤ scale ≤ scaleQ67`, with the same four-link chain: - -1. link-1 deficit against the grid rational including the `div` floor, `≤ 2378/1000`; -2. the argument granularity (`Floor.GranV`) — free on the `t ≥ 0` half, `≤ (5¹⁸/2⁴¹)·1644901622230542074/10¹⁹` - (`Mp`-folded) on the `t ≤ 0` half; -3. the `Mp` factor, `≤ 2/25` (via `r0 ≤ 1.45·scaleQ67`); -4. the under-direction reduced-argument gap, `≤ 307/1000` (via `exp(rt) ≤ √2·(1+ε)`). - -Per sign half the links sum inside the budget: `2378/1000 + 2/25 + 307/1000 ≤ 2993/1000` on the -`t ≥ 0` half (granularity free there) and `2378/1000 + 2/25 + -(5¹⁸/2⁴¹)·1644901622230542074/10¹⁹ + 218/1000 ≤ 2993/1000` on the `t ≤ 0` half. The budget feeds -the `k = 65` deficit envelope `(2993/1000 + MARGIN)/2² < 1`. The module closes with the -octave-seam `r0`-doubling -bound `r0₁ + 3 ≤ 2·r0₂` (`SeamR0Bound`), where the `1 − exp(−1/RAY)` seam slack (≈ `8.5·10¹⁰` grid -units against `r0₂ > 2¹²³`) dwarfs both per-point budgets and the three integer units. +deficit `scale·exp(rt) ≤ r0 + 2993/1000` (`r0Scaled_real_under_within`), for both signs and every +scale in `2¹²⁵ ≤ scale ≤ scaleMax`. + +On the nonnegative half, generated carry certificates bound the quotient deficit by +`258857/100000`; the proof retains the quotient-factor and reduced-argument terms at their exact +maximal-scale images until their final rational sum. On the nonpositive half, the quotient deficit +is `2378/1000`, and the quotient-factor, granularity, and reduced-argument terms likewise retain +their exact maximal-scale images. Both exact sums fit `2993/1000`. + +The budget feeds the `k = 65` deficit envelope `(2993/1000 + MARGIN)/2² < 1`. The module closes +with the octave-seam bound `r0₁ + 3 ≤ 2·r0₂` (`SeamR0Bound`), where the +`1 − exp(−1/RAY)` seam slack (≈ `8.5·10¹⁰` grid units against `r0₂ > 2¹²³`) dominates the +per-point budgets and the three integer units. -/ namespace ExpYul @@ -78,8 +76,8 @@ theorem exp_reducedArg_le_sqrt2bound {x : Nat} (hx : x < 2 ^ 256) /-! ## The `r0` bracket on the nonneg half -/ -/-- `r0` is bracketed on the nonneg half: `scaleQ67 ≤ r0` and `100·r0 ≤ 145·scaleQ67`. -/ -theorem r0_bracket_nonneg {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) +/-- `r0` is bracketed on the nonnegative half: `scale ≤ r0` and `100·r0 ≤ 145·scale`. -/ +theorem r0_bracket_nonneg {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (scale : Int) ≤ int256 (r0ScaledTree scale x) ∧ @@ -117,92 +115,147 @@ theorem r0_bracket_nonneg {scale x : Nat} (hshi : scale ≤ scaleQ67) (hx : x < /-! ## The piecewise link-1 carry table -/ -/-- Horner evaluation of a nonnegative-coefficient polynomial is nonnegative and monotone on the -nonnegative axis. -/ -theorem evalPoly_nonneg_mono {p : List Int} (hp : ∀ c ∈ p, 0 ≤ c) : +private theorem evalPoly_nonneg_mono {p : List Int} (hp : ∀ c ∈ p, 0 ≤ c) : ∀ {a b : Int}, 0 ≤ a → a ≤ b → - 0 ≤ Common.Poly.evalPoly p a ∧ Common.Poly.evalPoly p a ≤ Common.Poly.evalPoly p b := by + 0 ≤ evalPoly p a ∧ evalPoly p a ≤ evalPoly p b := by induction p with - | nil => intro a b _ _; simp [Common.Poly.evalPoly] + | nil => intro a b _ _; simp [evalPoly] | cons c cs ih => intro a b ha hab have hc : 0 ≤ c := hp c List.mem_cons_self - have hcs : ∀ d ∈ cs, (0:Int) ≤ d := fun d hd => hp d (List.mem_cons_of_mem _ hd) - obtain ⟨hnn_a, hmono⟩ := ih hcs ha hab + have hcs : ∀ d ∈ cs, (0 : Int) ≤ d := fun d hd => hp d (List.mem_cons_of_mem _ hd) + obtain ⟨hnn, hmono⟩ := ih hcs ha hab have hb : 0 ≤ b := le_trans ha hab - refine ⟨?_, ?_⟩ - · simp only [Common.Poly.evalPoly] - have := mul_nonneg ha hnn_a - omega - · simp only [Common.Poly.evalPoly] - have h1 : a * Common.Poly.evalPoly cs a ≤ b * Common.Poly.evalPoly cs a := - mul_le_mul_of_nonneg_right hab hnn_a - have h2 : b * Common.Poly.evalPoly cs a ≤ b * Common.Poly.evalPoly cs b := - mul_le_mul_of_nonneg_left hmono hb - omega - -/-- The odd-accumulator domain cap `odNumV v ≤ odCap` (`= odVPoly` at `vmaxV + 1`): all `odVPoly` -coefficients are nonnegative, so the edge evaluation caps every grid point of the domain. -/ -def odCap : Int := 174678221397644049575777143361928794627879205226578653562590130996770143609877303657406822247010342954119346790867564782461851026886997547906404137068846862087419955814213206609572436845308432 - -theorem odNumV_le_odCap {v : Nat} (hv : (v : Int) ≤ (ExpCertV.vmaxV : Int) + 1) : - (odNumV v : Int) ≤ odCap := by + constructor + · simp only [evalPoly] + exact add_nonneg hc (mul_nonneg ha hnn) + · simp only [evalPoly] + calc c + a * evalPoly cs a ≤ c + b * evalPoly cs a := by + gcongr + _ ≤ c + b * evalPoly cs b := by + gcongr + +private def odCap : Int := + 174678221397644049575777143361928794627879205226578653562590130996770143609877303657406822247010342954119346790867564782461851026886997547906404137068846862087419955814213206609572436845308432 + +private theorem odNumV_le_odCap {v : Nat} + (hv : (v : Int) ≤ (ExpCertV.vmaxV : Int) + 1) : (odNumV v : Int) ≤ odCap := by rw [odNumV_eq_poly] - have hcoeffs : ∀ c ∈ ExpCertV.odVPoly, (0:Int) ≤ c := by - unfold ExpCertV.odVPoly; intro c hc; fin_cases hc <;> positivity + have hcoeffs : ∀ c ∈ ExpCertV.odVPoly, (0 : Int) ≤ c := by + unfold ExpCertV.odVPoly + intro c hc + fin_cases hc <;> positivity have h := (evalPoly_nonneg_mono hcoeffs (Int.natCast_nonneg v) hv).2 - calc Common.Poly.evalPoly ExpCertV.odVPoly (v : Int) - ≤ Common.Poly.evalPoly ExpCertV.odVPoly ((ExpCertV.vmaxV : Int) + 1) := h - _ = odCap := by unfold ExpCertV.odVPoly ExpCertV.vmaxV odCap; norm_num [Common.Poly.evalPoly] - -/-- The per-piece link-1 carry rows over the shared `granPieces` table, at the common `×100` -integer scale. Positive half (quadratic in the `DO` floor, `r0` bounded through the runtime floor -and the odd cap): the carry fits `1378/1000` of one denominator. Negative half over `DU` with -`r0 ≤ scaleQ67`. -/ -def Link1PieceOK : Int × Int × Int × Int × Int → Prop - | (_, _, T, DO, DU) => - 1000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * - (200 * (0x6f05b59d3b2000000000000000000000 : Int) * (DO * 2 ^ 725) + - 200 * (0x6f05b59d3b2000000000000000000000 : Int) * T * odCap + - 800 * (0x6f05b59d3b2000000000000000000000 : Int) * 2 ^ 637)) + - 200000 * 2 ^ 637 * (DO * 2 ^ 725) ≤ - 137800 * ((DO * 2 ^ 725) * (DO * 2 ^ 725)) ∧ - 1000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * - (200 * (0x6f05b59d3b2000000000000000000000 : Int) * (DU * 2 ^ 725) + - 800 * (0x6f05b59d3b2000000000000000000000 : Int) * 2 ^ 637)) + - 200000 * 2 ^ 637 * (DU * 2 ^ 725) ≤ - 137800 * ((DU * 2 ^ 725) * (DU * 2 ^ 725)) - -set_option maxHeartbeats 8000000 in -set_option maxRecDepth 8000 in -theorem link1Pieces_hold : ∀ p ∈ ExpCertV.granPieces, Link1PieceOK p := by - unfold Link1PieceOK + calc evalPoly ExpCertV.odVPoly (v : Int) + ≤ evalPoly ExpCertV.odVPoly ((ExpCertV.vmaxV : Int) + 1) := h + _ = odCap := by + unfold ExpCertV.odVPoly ExpCertV.vmaxV odCap + norm_num [evalPoly] + +/-- The facts attached to one carry-certificate row: the reduced-argument cap, the common bound +on its integer coefficient, the square cap for the row's interval, and the checked polynomial +inequality throughout that interval. -/ +def UnderCarryPieceHolds : Int × Int × Int × Int → Prop + | (vlo, vhi, T, R) => + 0 ≤ T ∧ T ≤ (ExpCertV.H129 : Int) + 63 ∧ 0 ≤ R ∧ R ≤ 158857 ∧ + 2 ^ 135 * vhi + 2 ^ 135 ≤ T ^ 2 ∧ + ∀ v : Int, vlo ≤ v → v ≤ vhi → + 0 ≤ evalPoly (ExpCertV.carryCert T R) v + +/-- Every carry row is anchored to its generated Kronecker certificate. -/ +theorem underCarryPieces_hold : + ∀ p ∈ ExpCertV.underCarryPieces, UnderCarryPieceHolds p := by + intro p hp + simp only [ExpCertV.underCarryPieces, ExpCertV.underCarryBounds, + ExpCertV.granPieces, ExpCertV.withCarryBound, List.zipWith, List.mem_cons, + List.not_mem_nil, or_false] at hp + rcases hp with rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl | + rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl + all_goals + unfold UnderCarryPieceHolds + refine ⟨by norm_num, by unfold ExpCertV.H129; norm_num, by norm_num, + by norm_num, by norm_num, ?_⟩ + · exact ExpCertV.carryP00_nonnegOn + · exact ExpCertV.carryP01_nonnegOn + · exact ExpCertV.carryP02_nonnegOn + · exact ExpCertV.carryP03_nonnegOn + · exact ExpCertV.carryP04_nonnegOn + · exact ExpCertV.carryP05_nonnegOn + · exact ExpCertV.carryP06_nonnegOn + · exact ExpCertV.carryP07_nonnegOn + · exact ExpCertV.carryP08_nonnegOn + · exact ExpCertV.carryP09_nonnegOn + · exact ExpCertV.carryP10_nonnegOn + · exact ExpCertV.carryP11_nonnegOn + · exact ExpCertV.carryP12_nonnegOn + · exact ExpCertV.carryP13_nonnegOn + · exact ExpCertV.carryP14_nonnegOn + · exact ExpCertV.carryP15_nonnegOn + · exact ExpCertV.carryP16_nonnegOn + · exact ExpCertV.carryP17_nonnegOn + · exact ExpCertV.carryP18_nonnegOn + · exact ExpCertV.carryP19_nonnegOn + · exact ExpCertV.carryP20_nonnegOn + · exact ExpCertV.carryP21_nonnegOn + · exact ExpCertV.carryP22_nonnegOn + · exact ExpCertV.carryP23_nonnegOn + · exact ExpCertV.carryP24_nonnegOn + · exact ExpCertV.carryP25_nonnegOn + · exact ExpCertV.carryP26_nonnegOn + · exact ExpCertV.carryP27_nonnegOn + · exact ExpCertV.carryP28_nonnegOn + · exact ExpCertV.carryP29_nonnegOn + · exact ExpCertV.carryP30_nonnegOn + · exact ExpCertV.carryP31_nonnegOn + +/-- Closed row intervals cover the entire certified square grid. -/ +def underCarryPiecesCover (lo hi : Int) : List (Int × Int × Int × Int) → Bool + | [] => false + | p :: rest => + decide (p.1 ≤ lo) && + (decide (hi ≤ p.2.1) || underCarryPiecesCover (p.2.1 + 1) hi rest) + +theorem underCarryPiecesCover_sound {ps : List (Int × Int × Int × Int)} {hi v : Int} + (hhi : v ≤ hi) : ∀ lo : Int, underCarryPiecesCover lo hi ps = true → lo ≤ v → + ∃ p ∈ ps, p.1 ≤ v ∧ v ≤ p.2.1 := by + induction ps with + | nil => intro lo h _; simp [underCarryPiecesCover] at h + | cons p rest ih => + intro lo h hlo + simp only [underCarryPiecesCover, Bool.and_eq_true, Bool.or_eq_true, + decide_eq_true_eq] at h + obtain ⟨h1, h2⟩ := h + rcases le_or_gt v p.2.1 with hv | hv + · exact ⟨p, List.mem_cons_self, le_trans h1 hlo, hv⟩ + · rcases h2 with h2 | h2 + · omega + · obtain ⟨q, hq, hql, hqh⟩ := ih _ h2 (by omega) + exact ⟨q, List.mem_cons_of_mem _ hq, hql, hqh⟩ + +theorem underCarryPieces_cover : + underCarryPiecesCover 0 (ExpCertV.vmaxV : Int) ExpCertV.underCarryPieces = true := by decide +kernel /-! ## Link 1 (under side): the grid rational vs `r0` -/ -/-- **Link-1 under (nonneg half)**: `1000·(scaleQ67·NUMv − r0·DENv) ≤ 2378·DENv`. The floor residual -costs one denominator; the odd-truncation carry `(2⁶³⁷ + Wod·2⁴⁸⁰·t)·(scaleQ67 + r0)` is aggregated -piecewise over `granPieces` (`t ≤ T` and `DO·2⁷²⁵ ≤ DENv` per piece, the certified -`Link1PieceOK` row closing the quadratic), fitting `1.378` denominators. -/ -theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- **Link-1 under (nonnegative half).** The quotient floor costs one denominator. The remaining +carry is bounded jointly with the exact denominator polynomial on each square-grid interval; the +largest checked row coefficient is `158857/100000` denominators. -/ +theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : - 1000 * ((scale : Int) * NUMv (vTree x) (int256 (tTree x)) - + 100000 * ((scale : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x))) ≤ - 2378 * DENv (vTree x) (int256 (tTree x)) := by + 258857 * DENv (vTree x) (int256 (tTree x)) := by obtain ⟨hfloor_lo, hfloor_hi⟩ := r0_floor_sandwich hshi hx hW obtain ⟨hEp_lo, _, _, _⟩ := bridge_facts hx hW obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hW htnn obtain ⟨hr0lo, hr0hi145⟩ := r0_bracket_nonneg hshi hx hW htnn obtain ⟨hDEN_lo, hDEN_up⟩ := DENv_runtime_bracket hx hW htnn - have hshiI : (scale : Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by - have h : ((scale : Nat) : Int) ≤ ((scaleQ67 : Nat) : Int) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Int) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num - rw [hs] at h - exact h + have hshiI : (scale : Int) ≤ (scaleMax : Int) := by exact_mod_cast hshi have hLHS : (scale : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + @@ -232,41 +285,66 @@ theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale have hfloor638 : (2:Int) ^ 637 * ((scale : Int) * (ev + tod) - r0 * (ev - tod)) ≤ 2 ^ 637 * (ev - tod) := mul_le_mul_of_nonneg_left hfloor (by positivity) nlinarith [hterm1, hterm2, hfloor638] - -- select the covering piece; its certified facts drive the aggregation + -- Select the carry row containing the runtime square-grid point. obtain ⟨_, hvsplit⟩ := tsq_split_wide hx hW have hvmaxI : ((vTree x : Nat) : Int) ≤ (ExpCertV.vmaxV : Int) := by exact_mod_cast vTree_le_vmax_wide hx hW obtain ⟨p, hp, hplo, hphi⟩ := - piecesCover_sound hvmaxI 0 granPieces_cover (Int.natCast_nonneg (vTree x)) - obtain ⟨vlo, vhi, T, DO, DU⟩ := p - obtain ⟨hDOpos, _, _, hTnn, hDOfl, _, _, _, _, _, _⟩ := - granPieces_ok _ hp (vTree x) hplo hphi - have hrow := (link1Pieces_hold _ hp).1 - have hcaps := granPieces_caps _ hp + underCarryPiecesCover_sound hvmaxI 0 underCarryPieces_cover + (Int.natCast_nonneg (vTree x)) + obtain ⟨vlo, vhi, T, R⟩ := p + obtain ⟨hTnn, hTH, hRnn, hRmax, hcaps, hrowCert⟩ := underCarryPieces_hold _ hp + have hrow := hrowCert (vTree x : Int) hplo hphi set r0 := int256 (r0ScaledTree scale x) with hr0def set t := int256 (tTree x) with htdef set den := (evTree x : Int) - int256 (todTree x) with hdendef set D := DENv (vTree x) t with hDdef + set Dc := DENv (vTree x) T with hDcdef set S := (scale : Int) with hSdef set Op := (odNumV (vTree x) : Int) with hOpdef have hSpos : (0 : Int) < S := by rw [hSdef] exact_mod_cast lt_of_lt_of_le (by norm_num : (0:Nat) < 2 ^ 125) hslo - have hS67 : S ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by rw [hSdef]; exact hshiI + have hSmax : S ≤ (scaleMax : Int) := by rw [hSdef]; exact hshiI have hr0nn : (0 : Int) ≤ r0 := le_trans (le_of_lt hSpos) hr0lo - -- `t ≤ T` on the piece + -- The row's square cap implies `t ≤ T` on the nonnegative half. have htT : t ≤ T := by have hsq := tsq_lt_capsq hvsplit hphi hcaps nlinarith [hsq, htnn, hTnn] have hOpnn : (0 : Int) ≤ Op := by rw [hOpdef]; exact Int.natCast_nonneg _ - have hOple : Op ≤ odCap := by rw [hOpdef]; exact odNumV_le_odCap (by linarith [hvmaxI]) - -- the piece's denominator floor holds at the runtime `t` - have hDO_D : DO * 2 ^ 725 ≤ D := by - have h1 : t * Op ≤ T * Op := mul_le_mul_of_nonneg_right htT hOpnn - have h2 : DO * 2 ^ 725 ≤ (evNumV (vTree x) : Int) * 2 ^ 111 - T * Op := by - rw [hOpdef]; exact hDOfl - rw [hDdef]; unfold DENv; rw [← hOpdef]; linarith [h1, h2] - have hDOpos' : (0 : Int) < DO * 2 ^ 725 := by positivity + have hOple : Op ≤ odCap := by + rw [hOpdef] + exact odNumV_le_odCap (by linarith [hvmaxI]) + have hDcD : Dc ≤ D := by + rw [hDcdef, hDdef] + unfold DENv + rw [← hOpdef] + exact sub_le_sub_left (mul_le_mul_of_nonneg_right htT hOpnn) _ + have hTH' : T ≤ 235865763225513294137944142764154484399 + 63 := by + simpa [ExpCertV.H129] using hTH + have hDH : 1108965543718 * 2 ^ 725 ≤ + DENv (vTree x) 235865763225513294137944142764154484399 := + DENv_ge_over (by omega) (le_refl _) + have hTOp : T * Op ≤ + 235865763225513294137944142764154484399 * Op + 63 * odCap := by + have h1 := mul_le_mul_of_nonneg_right hTH' hOpnn + have h2 := mul_le_mul_of_nonneg_left hOple (by norm_num : (0 : Int) ≤ 63) + nlinarith [h1, h2] + have hDcFloor : 1108965543718 * 2 ^ 725 - 63 * odCap ≤ Dc := by + rw [hDcdef] + unfold DENv at hDH ⊢ + rw [← hOpdef] at hDH ⊢ + linarith [hDH, hTOp] + have hDcFloorPos : (0 : Int) < 1108965543718 * 2 ^ 725 - 63 * odCap := by + norm_num [odCap] + have hDcpos : (0 : Int) < Dc := lt_of_lt_of_le hDcFloorPos hDcFloor + have hdenEval : evalPoly (ExpCertV.denAtCap T) (vTree x : Int) = Dc := by + rw [ExpCertV.eval_denAtCap, ← evNumV_eq_poly, ← odNumV_eq_poly, hDcdef] + unfold DENv + ring + rw [ExpCertV.eval_carryCert, ExpCertV.eval_carryLhs, hdenEval, + ← odNumV_eq_poly, ← hOpdef] at hrow + unfold ExpCertV.S2 at hrow -- ×100 floor lift: `100·r0·D ≤ 100·S·NUMv + 145·Wev·2^591·S` have hEp111 : 2 ^ 637 * (evTree x : Int) ≤ (evNumV (vTree x) : Int) * 2 ^ 111 := by nlinarith [hEp_lo] @@ -284,67 +362,60 @@ theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale have h4 : 100 * (72572599271425 * 2 ^ 591 * r0) ≤ 145 * (72572599271425 * 2 ^ 591) * S := by nlinarith [hr0hi145] nlinarith [h1, h2, h3, h4] - -- transfer to the piece floor + -- Transfer the runtime quotient floor to the row denominator at `T`. have hK : 200 * (S * (t * Op)) + 145 * (72572599271425 * 2 ^ 591) * S ≤ - 200 * S * T * odCap + 800 * S * 2 ^ 637 := by - have htOple : t * Op ≤ T * odCap := by nlinarith [htT, hOple, htnn, hOpnn] + 200 * S * T * Op + 800 * S * 2 ^ 637 := by + have htOple : t * Op ≤ T * Op := mul_le_mul_of_nonneg_right htT hOpnn have hW : (145 : Int) * (72572599271425 * 2 ^ 591) ≤ 800 * 2 ^ 637 := by norm_num nlinarith [htOple, hW, hSpos] - have htransfer : (100 * (S + r0) - 200 * S) * (DO * 2 ^ 725) ≤ - 200 * S * T * odCap + 800 * S * 2 ^ 637 := by + have htransfer : (100 * (S + r0) - 200 * S) * Dc ≤ + 200 * S * T * Op + 800 * S * 2 ^ 637 := by have hnn : (0 : Int) ≤ 100 * (S + r0) - 200 * S := by linarith [hr0lo] - have h1 : (100 * (S + r0) - 200 * S) * (DO * 2 ^ 725) ≤ (100 * (S + r0) - 200 * S) * D := - mul_le_mul_of_nonneg_left hDO_D hnn + have h1 : (100 * (S + r0) - 200 * S) * Dc ≤ + (100 * (S + r0) - 200 * S) * D := + mul_le_mul_of_nonneg_left hDcD hnn nlinarith [h1, h100, hK, hNUMD] - have h100DO : 100 * ((S + r0) * (DO * 2 ^ 725)) ≤ - 200 * S * (DO * 2 ^ 725) + 200 * S * T * odCap + 800 * S * 2 ^ 637 := by + have h100Dc : 100 * ((S + r0) * Dc) ≤ + 200 * S * Dc + 200 * S * T * Op + 800 * S * 2 ^ 637 := by nlinarith [htransfer] - -- feed the certified piece row and cancel one factor of `DO·2^725` + -- Feed the checked polynomial row and cancel one positive denominator factor. have hcoefT_nn : (0 : Int) ≤ 2 ^ 637 + 269746241 * 2 ^ 480 * T := by nlinarith [hTnn] - -- the certified row holds at the literal maximal scale; every scale coefficient on its - -- left-hand side is nonnegative, so it holds a fortiori at the symbolic scale have hrow_s : 1000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * - (200 * S * (DO * 2 ^ 725) + 200 * S * T * odCap + 800 * S * 2 ^ 637)) + - 200000 * 2 ^ 637 * (DO * 2 ^ 725) ≤ - 137800 * ((DO * 2 ^ 725) * (DO * 2 ^ 725)) := by - have hS67S_nn : (0 : Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) - S := by - linarith [hS67] - have hOpcap_nn : (0 : Int) ≤ odCap := le_trans hOpnn hOple - have h1 : 200 * S * (DO * 2 ^ 725) ≤ - 200 * (0x6f05b59d3b2000000000000000000000 : Int) * (DO * 2 ^ 725) := by - nlinarith [mul_nonneg hS67S_nn (le_of_lt hDOpos')] - have h2 : 200 * S * T * odCap ≤ - 200 * (0x6f05b59d3b2000000000000000000000 : Int) * T * odCap := by - nlinarith [mul_nonneg hS67S_nn (mul_nonneg hTnn hOpcap_nn)] + (200 * S * Dc + 200 * S * T * Op + 800 * S * 2 ^ 637)) + + 200000 * 2 ^ 637 * Dc ≤ R * (Dc * Dc) := by + have hSmaxS_nn : (0 : Int) ≤ (scaleMax : Int) - S := by linarith [hSmax] + have h1 : 200 * S * Dc ≤ 200 * (scaleMax : Int) * Dc := by + nlinarith [mul_nonneg hSmaxS_nn (le_of_lt hDcpos)] + have h2 : 200 * S * T * Op ≤ 200 * (scaleMax : Int) * T * Op := by + nlinarith [mul_nonneg hSmaxS_nn (mul_nonneg hTnn hOpnn)] have h3 : 800 * S * 2 ^ 637 ≤ - 800 * (0x6f05b59d3b2000000000000000000000 : Int) * 2 ^ 637 := by - nlinarith [hS67S_nn] - have hsum_le : 200 * S * (DO * 2 ^ 725) + 200 * S * T * odCap + 800 * S * 2 ^ 637 ≤ - 200 * (0x6f05b59d3b2000000000000000000000 : Int) * (DO * 2 ^ 725) + - 200 * (0x6f05b59d3b2000000000000000000000 : Int) * T * odCap + - 800 * (0x6f05b59d3b2000000000000000000000 : Int) * 2 ^ 637 := by + 800 * (scaleMax : Int) * 2 ^ 637 := by nlinarith [hSmaxS_nn] + have hsum_le : 200 * S * Dc + 200 * S * T * Op + 800 * S * 2 ^ 637 ≤ + 200 * (scaleMax : Int) * Dc + 200 * (scaleMax : Int) * T * Op + + 800 * (scaleMax : Int) * 2 ^ 637 := by linarith [h1, h2, h3] have hmul_le := mul_le_mul_of_nonneg_left hsum_le hcoefT_nn + norm_num [scaleMax] at hmul_le linarith [hrow, hmul_le] - have hXY : (100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + 200000 * 2 ^ 637) * - (DO * 2 ^ 725) ≤ (137800 * (DO * 2 ^ 725)) * (DO * 2 ^ 725) := by - have h1 := mul_le_mul_of_nonneg_left h100DO hcoefT_nn + have hXY : (100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + + 200000 * 2 ^ 637) * Dc ≤ (R * Dc) * Dc := by + have h1 := mul_le_mul_of_nonneg_left h100Dc hcoefT_nn nlinarith [h1, hrow_s] - have hDIV : 100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + 200000 * 2 ^ 637 ≤ - 137800 * (DO * 2 ^ 725) := - le_of_mul_le_mul_right hXY hDOpos' - -- `coef ≤ coefT`, then assemble + have hDIV : 100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + + 200000 * 2 ^ 637 ≤ R * Dc := le_of_mul_le_mul_right hXY hDcpos have hcoef_le : 100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * t) * (S + r0)) ≤ 100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) := by have hSr0 : (0 : Int) ≤ S + r0 := by linarith [hr0nn, hSpos] nlinarith [htT, hSr0] - have hfin3 : (1378 : Int) * (DO * 2 ^ 725) ≤ 1378 * D := by linarith [hDO_D] - linarith [hLHS, hDEN_lo, hDIV, hcoef_le, hfin3] + have hRD : R * Dc ≤ 158857 * D := by + calc R * Dc ≤ 158857 * Dc := mul_le_mul_of_nonneg_right hRmax (le_of_lt hDcpos) + _ ≤ 158857 * D := mul_le_mul_of_nonneg_left hDcD (by norm_num) + linarith [hLHS, hDEN_lo, hDIV, hcoef_le, hRD] /-- **Link-1 under (nonpositive half)**: the same `2378/1000` budget, with no piece machinery: on -this half `DENv = Ep·2¹¹¹ − t·Op ≥ 2⁶³⁸·ev`, so the even-truncation width and the `tod`-floor unit -are absorbed against `2⁶³⁸·ev ≥ 2⁶³⁸·A0`. -/ -theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +this half `DENv = Ep·2¹¹¹ − t·Op ≥ 2⁶³⁷·ev`, so the even-truncation width and the `tod`-floor unit +are absorbed against `2⁶³⁷·ev ≥ 2⁶³⁷·A0`. -/ +theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : @@ -358,12 +429,7 @@ theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 obtain ⟨htod_lo126, _, _, _⟩ := todTree_bound_wide hx hW - have hshiI : (scale : Int) ≤ (0x6f05b59d3b2000000000000000000000 : Int) := by - have h : ((scale : Nat) : Int) ≤ ((scaleQ67 : Nat) : Int) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Int) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num - rw [hs] at h - exact h + have hshiI : (scale : Int) ≤ (scaleMax : Int) := by exact_mod_cast hshi have hSnn : (0:Int) ≤ (scale : Int) := Int.natCast_nonneg _ have hLHS : (scale : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) ≤ @@ -408,7 +474,7 @@ theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s have hfloor638 : (2:Int) ^ 637 * ((scale : Int) * (ev + tod) - r0 * (ev - tod)) ≤ 2 ^ 637 * (ev - tod) := mul_le_mul_of_nonneg_left hfloor (by positivity) nlinarith [hterm1, hterm2, hfloor638] - -- budget against DENv = Ep·2^111 − t·Op ≥ 2^638·ev ≥ 2^638·A0; den ≤ ev + 2^126 + -- budget against DENv = Ep·2^111 − t·Op ≥ 2^637·ev ≥ 2^637·A0; den ≤ ev + 2^126 set ev := (evTree x : Int) with hevdef set tod := int256 (todTree x) with htoddef set D := DENv (vTree x) (int256 (tTree x)) with hDdef @@ -439,21 +505,21 @@ theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s -- literal maximal one first have hSrelax : 1000 * (72572599271425 * 2 ^ 591 * (scale : Int) + 2 * 2 ^ 637 * (scale : Int)) ≤ - 1000 * (72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) + - 2 * 2 ^ 637 * (0x6f05b59d3b2000000000000000000000 : Int)) := by + 1000 * (72572599271425 * 2 ^ 591 * (scaleMax : Int) + + 2 * 2 ^ 637 * (scaleMax : Int)) := by nlinarith [hshiI] have hlit : 1000 * (2 ^ 637 : Int) + - 1000 * (72572599271425 * 2 ^ 591 * (0x6f05b59d3b2000000000000000000000 : Int) + - 2 * 2 ^ 637 * (0x6f05b59d3b2000000000000000000000 : Int)) ≤ + 1000 * (72572599271425 * 2 ^ 591 * (scaleMax : Int) + + 2 * 2 ^ 637 * (scaleMax : Int)) ≤ (1378 : Int) * (2 ^ 637 * 415147853590918758559635130244235626256) := by - norm_num + norm_num [scaleMax] linarith [hLHS, hDden, hD_A, hlit, hSrelax] /-! ## The per-point deficit (nonneg half) -/ -/-- **The per-point deficit (nonneg half).** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`: link-1 `≤ 2378/1000`, the -`Mp` factor `≤ 2/25`, the under gap `≤ 307/1000`; the granularity is free on this half. -/ -theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- **The per-point deficit (nonnegative half).** The carry, quotient-factor excess, and reduced- +argument gap retain their exact rational budgets until the final sum. -/ +theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : @@ -461,12 +527,7 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num - rw [hs] at h - exact h + have hshiR : (scale : Real) ≤ (scaleMax : Real) := by exact_mod_cast hshi set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -481,17 +542,17 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s have hDER : (0:Real) < (evalPoly ExpCertV.denExpV t : Real) := by have : (0:Int) < evalPoly ExpCertV.denExpV t := lt_of_lt_of_le one_pos hDE exact_mod_cast this - -- link 1: scale·Qv ≤ r0 + 2378/1000 + -- link 1: scale·Qv ≤ r0 + 258857/100000 have hlink1 := link1_under_int hslo hshi hx hW htnn have hQv_le : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ - (r0 : Real) + 2378 / 1000 := by + (r0 : Real) + 258857 / 100000 := by rw [mul_div_assoc', div_le_iff₀ hDR] have hR := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hlink1 push_cast at hR nlinarith [hR, hDR] -- link 2 (free): NE/DE ≤ Qv obtain ⟨hgran1, _⟩ := gran_over_pair hx hW htnn - -- link 3: Et ≤ (NE/DE)·Mpp ≤ Qv·Mpp; Mpp excess ≤ 2/25 via r0 ≤ 1.45·2^126 + -- link 3: the quotient-factor excess is bounded at the maximal scale have hcertup := certUp_real htnn htdom set Et := Real.exp ((t : Real) / (2 ^ 129 : Real)) with hEtdef set NE := evalPoly ExpCertV.numExpV t with hNEdef @@ -510,34 +571,39 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s le_trans hEt_le (mul_le_mul_of_nonneg_right hgran1 hMpp_nn) have hMpp1 : Mpp - 1 = 1 / (2 ^ 132 : Real) := by rw [hMppdef]; field_simp obtain ⟨_, hr0hi145⟩ := r0_bracket_nonneg hshi hx hW htnn - have hr0R : (r0 : Real) ≤ (145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) := by + have hr0R : (r0 : Real) ≤ (145 / 100) * (scaleMax : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0hi145 push_cast at h - nlinarith [h, hshiR] - have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + 2 / 25 := by + calc (r0 : Real) ≤ (145 / 100) * (scale : Real) := by nlinarith [h] + _ ≤ (145 / 100) * (scaleMax : Real) := + mul_le_mul_of_nonneg_left hshiR (by norm_num) + have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 258857 / 100000 + + ((145 / 100) * (scaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) := by have h1 : (scale : Real) * Et ≤ (scale : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) := mul_le_mul_of_nonneg_left hEt_le_Qv hsRnn have h2 : (scale : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) = (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) + ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) := by ring - have h3 : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) ≤ 2 / 25 := by + have h3 : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * + (Mpp - 1) ≤ + ((145 / 100) * (scaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) := by rw [hMpp1] have hcap : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ - (145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000 := by linarith [hQv_le, hr0R] + (145 / 100) * (scaleMax : Real) + 258857 / 100000 := by + linarith [hQv_le, hr0R] have := mul_le_mul_of_nonneg_right hcap (by positivity : (0:Real) ≤ 1 / (2 ^ 132 : Real)) - have hfin : ((145 / 100) * (0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000) * (1 / (2 ^ 132 : Real)) ≤ - 2 / 25 := by norm_num - linarith [this, hfin] + simpa [div_eq_mul_inv] using this linarith [h1, h2 ▸ h1, h3, hQv_le] - -- link 4 (under gap): 2^126·(Ert − Et) ≤ 307/1000 + -- link 4 keeps the maximal-scale image exact. set Ert := Real.exp (reducedArg x) with hErtdef have hgapunder := reducedArg_close_under_wide hx hW have hExp_diff : Ert - Et ≤ (reducedArg x - (t : Real) / (2 ^ 129 : Real)) * Ert := exp_diff_le _ _ have hErt_le := exp_reducedArg_le_sqrt2bound hx hW rw [← hErtdef] at hErt_le have hErt_nn : (0:Real) ≤ Ert := le_of_lt (Real.exp_pos _) - have hgap126 : (scale : Real) * (Ert - Et) ≤ 307 / 1000 := by + have hgap126 : (scale : Real) * (Ert - Et) ≤ + (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := by have hgap : Ert - Et ≤ (1025 / (1024 * (2 ^ 129 : Real))) * Ert := le_trans hExp_diff (mul_le_mul_of_nonneg_right (le_of_lt hgapunder) hErt_nn) have h1 : (scale : Real) * (Ert - Et) ≤ (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := @@ -546,36 +612,32 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) hsRnn have h2' : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ - (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := + (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := mul_le_mul_of_nonneg_right hshiR (by positivity) - have h3 : (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ 307 / 1000 := by - norm_num - linarith [h1, h2, h2', h3] + linarith [h1, h2, h2'] have hdist : (scale : Real) * Ert = (scale : Real) * Et + (scale : Real) * (Ert - Et) := by ring show (scale : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 - have hsum : (2378 : Real) / 1000 + 2 / 25 + 307 / 1000 ≤ 2993 / 1000 := by norm_num + have hsum : (258857 : Real) / 100000 + + ((145 / 100) * (scaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) + + (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ + 2993 / 1000 := by + norm_num [scaleMax] linarith [hEt_bound, hgap126, hdist, hsum] /-! ## The per-point deficit (nonpositive half) -/ -/-- **The per-point deficit (nonpositive half).** `scaleQ67·exp(rt) ≤ r0 + 2993/1000`: link-1 `≤ 2378/1000`, -the `Mp`-folded granularity `≤ (5¹⁸/2⁴¹)·1644901622230542074/10¹⁹`, the `Mp` factor `≤ 2/25` -(via `r0 ≤ scaleQ67`), the under gap `≤ 307/1000`. -/ +/-- **The per-point deficit (nonpositive half).** The quotient floor, quotient-factor excess, +granularity envelope, and reduced-argument gap retain their exact maximal-scale images. -/ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) + (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by have htdom := tdom_neg hx hW htneg have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleQ67 : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by - unfold scaleQ67; norm_num - rw [hs] at h - exact h + have hshiR : (scale : Real) ≤ (scaleMax : Real) := by exact_mod_cast hshi set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -612,7 +674,7 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) positivity have hMp1 : Mp - 1 = 1 / ((2 ^ 132 : Real) - 1) := by rw [hMpdef]; field_simp have hr0le := r0_le_scale_neg hshi hx hW htneg - have hr0R : (r0 : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) := by + have hr0R : (r0 : Real) ≤ (scaleMax : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h linarith [h, hshiR] @@ -620,7 +682,8 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) -- scale and relaxed to the literal maximal-scale budget have hgran2S : (scale : Real) * Mp * ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) ≤ - 3814697265625 * 1644901622230542074 / (10000000000000000000 * 2199023255552) := by + (scaleMax : Real) * 1644901622230542074 / + (10000000000000000000 * (2 ^ 126 : Real)) := by have hdiff_nn : (0:Real) ≤ (NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real) := by linarith [hgran1] have hMp' : Mp ≤ (2 ^ 131 : Real) / ((2 ^ 131 : Real) - 1) := by @@ -634,11 +697,13 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_left hMp' hsRnn) hdiff_nn have h2 := mul_le_mul_of_nonneg_left hgran2 hsRnn have h3 : (scale : Real) * (1644901622230542074 / 10000000000000000000) ≤ - (0x6f05b59d3b2000000000000000000000 : Real) * (1644901622230542074 / 10000000000000000000) := + (scaleMax : Real) * (1644901622230542074 / 10000000000000000000) := mul_le_mul_of_nonneg_right hshiR (by positivity) nlinarith [h1, h2, h3] - have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + 2 / 25 + - 3814697265625 * 1644901622230542074 / (10000000000000000000 * 2199023255552) := by + have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + + ((scaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) + + (scaleMax : Real) * 1644901622230542074 / + (10000000000000000000 * (2 ^ 126 : Real)) := by have h1 : (scale : Real) * Et ≤ (scale : Real) * (((NE : Real) / (DE : Real)) * Mp) := mul_le_mul_of_nonneg_left hEt_le hsRnn -- split: scale·(NE/DE)·Mp = scale·Qv + scale·Qv·(Mp−1) + scale·Mp·(NE/DE − Qv) @@ -648,18 +713,16 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (scale : Real) * Mp * ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) := by ring have hMpterm : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mp - 1) ≤ - 2 / 25 := by + ((scaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) := by rw [hMp1] have hcap : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ - (0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000 := by linarith [hQv_le, hr0R] + (scaleMax : Real) + 2378 / 1000 := by + exact le_trans hQv_le (add_le_add_right hr0R _) have := mul_le_mul_of_nonneg_right hcap (by positivity : (0:Real) ≤ 1 / ((2 ^ 132 : Real) - 1)) - have hfin : ((0x6f05b59d3b2000000000000000000000 : Real) + 2378 / 1000) * (1 / ((2 ^ 132 : Real) - 1)) ≤ 2 / 25 := by - rw [mul_one_div, div_le_div_iff₀ (by norm_num) (by norm_num)] - norm_num - linarith [this, hfin] + simpa [div_eq_mul_inv] using this linarith [h1, hsplit ▸ h1, hMpterm, hgran2S, hQv_le] - -- link 4 (under gap): 2^126·(Ert − Et) ≤ 307/1000 + -- link 4 retains the maximal-scale image of the reduced-argument gap set Ert := Real.exp (reducedArg x) with hErtdef have hgapunder := reducedArg_close_under_wide hx hW have hExp_diff : Ert - Et ≤ (reducedArg x - (t : Real) / (2 ^ 129 : Real)) * Ert := exp_diff_le _ _ @@ -689,7 +752,8 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) have hfin : (1:Real) / (1 - u) ≤ 10001 / 10000 := by rw [div_le_div_iff₀ h1u (by norm_num)]; nlinarith [husmall] linarith [hmono, hexpu, hfin] - have hgap126 : (scale : Real) * (Ert - Et) ≤ 218 / 1000 := by + have hgap126 : (scale : Real) * (Ert - Et) ≤ + (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := by have hgap : Ert - Et ≤ (1025 / (1024 * (2 ^ 129 : Real))) * Ert := le_trans hExp_diff (mul_le_mul_of_nonneg_right (le_of_lt hgapunder) hErt_nn) have h1 : (scale : Real) * (Ert - Et) ≤ (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := @@ -698,22 +762,25 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) hsRnn have h2' : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ - (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := + (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := mul_le_mul_of_nonneg_right hshiR (by positivity) - have h3 : (0x6f05b59d3b2000000000000000000000 : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ 218 / 1000 := by - norm_num - linarith [h1, h2, h2', h3] + linarith [h1, h2, h2'] have hdist : (scale : Real) * Ert = (scale : Real) * Et + (scale : Real) * (Ert - Et) := by ring show (scale : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 - have hsum : (2378 : Real) / 1000 + 2 / 25 + 3814697265625 * 1644901622230542074 / (10000000000000000000 * 2199023255552) + - 218 / 1000 ≤ 2993 / 1000 := by norm_num + have hsum : (2378 : Real) / 1000 + + ((scaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) + + (scaleMax : Real) * 1644901622230542074 / + (10000000000000000000 * (2 ^ 126 : Real)) + + (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ + 2993 / 1000 := by + norm_num [scaleMax] linarith [hEt_bound, hgap126, hdist, hsum] /-- **Per-point deficit (tight, any sign):** `scale·exp(rt) ≤ r0 + 2993/1000` (the deficit budget is certified at the maximal scale, and smaller scales only shrink the true deficit). -/ theorem r0Scaled_real_under_within {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) : + (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg · exact r0_real_under_tight hslo hshi hx hW htnn @@ -723,7 +790,7 @@ theorem r0_real_under_within_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by have h := r0Scaled_real_under_within (scale := scaleQ67) (by unfold scaleQ67; norm_num) - (le_refl _) hx hW + scaleQ67_le_scaleMax hx hW rw [r0Tree_eq_scaled] have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by unfold scaleQ67; norm_num @@ -746,8 +813,8 @@ theorem r0Tree_gt_2126 {x : Nat} (hx : x < 2 ^ 256) have h2 : (2 : Real) ^ 123 < ((2 ^ 124 : Int) : Real) := by norm_num linarith [h, h2] -/-- `2¹²² < r0ScaledTree scale x` on the region, for `2^125 ≤ scale ≤ scaleQ67`. -/ -theorem r0Scaled_gt_2122 {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- `2¹²² < r0ScaledTree scale x` on the region, for `2^125 ≤ scale ≤ scaleMax`. -/ +theorem r0Scaled_gt_2122 {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : (2 : Real) ^ 122 < (int256 (r0ScaledTree scale x) : Real) := by obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW @@ -806,11 +873,11 @@ theorem r0_seam_double_wide {x1 x2 : Nat} hunder2 have hr0_1 : (int256 (r0Tree x1) : Real) ≤ 2 * ((int256 (r0Tree x2) : Real) + (2993 / 1000 : Real)) * y + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + 2 * 4668745981919039833 / 10000000000000000000 := by have h1 : (0x6f05b59d3b2000000000000000000000 : Real) * E1 = 2 * ((0x6f05b59d3b2000000000000000000000 : Real) * E2) * y := by rw [hseam]; ring have h2 : (int256 (r0Tree x1) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * E1 + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := hover1 + 2 * 4668745981919039833 / 10000000000000000000 := hover1 rw [h1] at h2 have h3 : 2 * ((0x6f05b59d3b2000000000000000000000 : Real) * E2) * y ≤ 2 * ((int256 (r0Tree x2) : Real) + (2993 / 1000 : Real)) * y := @@ -821,7 +888,8 @@ theorem r0_seam_double_wide {x1 x2 : Nat} have hr0_2nn : (0:Real) ≤ (int256 (r0Tree x2) : Real) := by linarith [hr0_2_big, (by positivity : (0:Real) ≤ (2:Real)^126)] have hkey : 2 * ((int256 (r0Tree x2) : Real) + (2993 / 1000 : Real)) * y + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) + 3 < 2 * (int256 (r0Tree x2) : Real) := by + 2 * 4668745981919039833 / 10000000000000000000 + 3 < + 2 * (int256 (r0Tree x2) : Real) := by -- the seam gap is dominated by `(r0 + U) / RAY`; the quotient exceeds `8.5·10¹⁰` here have hyb : 2 * ((int256 (r0Tree x2) : Real) + (2993 / 1000 : Real)) * y ≤ 2 * ((int256 (r0Tree x2) : Real) + (2993 / 1000 : Real)) * (1 - 1 / (2 * (10 ^ 27 : Real))) := by @@ -836,7 +904,8 @@ theorem r0_seam_double_wide {x1 x2 : Nat} have hbig : ((int256 (r0Tree x2) : Real) + (2993 / 1000 : Real)) / (10 ^ 27 : Real) > 30 := by rw [gt_iff_lt, lt_div_iff₀ (by positivity)] nlinarith [hr0_2_big, (by norm_num : (30:Real) * 10 ^ 27 + 1 < 2 ^ 126)] - have hUB : 2 * (2993 / 1000 : Real) + 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) + 3 < 30 := by norm_num + have hUB : 2 * (2993 / 1000 : Real) + + 2 * 4668745981919039833 / 10000000000000000000 + 3 < 30 := by norm_num linarith [hyb, hexpand ▸ hyb, hbig, hUB] have hreal : (int256 (r0Tree x1) : Real) + 3 ≤ 2 * (int256 (r0Tree x2) : Real) := by linarith [hr0_1, hkey] @@ -858,7 +927,7 @@ theorem r0_seam_double {x1 x2 : Nat} the seam slack `exp(−1/RAY) < 1` against `r0₂ > 2¹²²` (worth `≈ 5·10⁹` grid units at the minimal scale) still dwarfs the per-point envelopes and the three integer units. -/ theorem r0Scaled_seam_double {scale x1 x2 : Nat} - (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) + (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hk : int256 (kTree x2) = int256 (kTree x1) + 1) @@ -887,11 +956,11 @@ theorem r0Scaled_seam_double {scale x1 x2 : Nat} hunder2 have hr0_1 : (int256 (r0ScaledTree scale x1) : Real) ≤ 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := by + 2 * 4668745981919039833 / 10000000000000000000 := by have h1 : (scale : Real) * E1 = 2 * ((scale : Real) * E2) * y := by rw [hseam]; ring have h2 : (int256 (r0ScaledTree scale x1) : Real) ≤ (scale : Real) * E1 + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) := hover1 + 2 * 4668745981919039833 / 10000000000000000000 := hover1 rw [h1] at h2 have h3 : 2 * ((scale : Real) * E2) * y ≤ 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y := @@ -902,7 +971,7 @@ theorem r0Scaled_seam_double {scale x1 x2 : Nat} have hr0_2nn : (0:Real) ≤ (int256 (r0ScaledTree scale x2) : Real) := by linarith [hr0_2_big, (by positivity : (0:Real) ≤ (2:Real)^122)] have hkey : 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) + 3 < + 2 * 4668745981919039833 / 10000000000000000000 + 3 < 2 * (int256 (r0ScaledTree scale x2) : Real) := by have hyb : 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * y ≤ 2 * ((int256 (r0ScaledTree scale x2) : Real) + (2993 / 1000 : Real)) * (1 - 1 / (2 * (10 ^ 27 : Real))) := by @@ -918,7 +987,7 @@ theorem r0Scaled_seam_double {scale x1 x2 : Nat} rw [gt_iff_lt, lt_div_iff₀ (by positivity)] nlinarith [hr0_2_big, (by norm_num : (30:Real) * 10 ^ 27 + 1 < 2 ^ 122)] have hUB : 2 * (2993 / 1000 : Real) + - 3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) + 3 < 30 := by + 2 * 4668745981919039833 / 10000000000000000000 + 3 < 30 := by norm_num linarith [hyb, hexpand ▸ hyb, hbig, hUB] have hreal : (int256 (r0ScaledTree scale x1) : Real) + 3 ≤ diff --git a/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean b/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean index 9045fc947..cf45567c6 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean @@ -33,14 +33,12 @@ set_option maxRecDepth 100000 /-! ## Strict never-over: the accumulator stays a positive distance below the target -`accumReal_over` gives `accumReal x ≤ E`. With `B' = (5¹⁸/2⁴¹)·B ≈ 0.99527` the never-over -envelope's image on the output grid, `MARGIN = 1` exceeds it strictly — the slack -`δ = MARGIN − B' ≈ 0.0047` (worth `δ/2^s` after the closing shift). The round trip needs this +`accumReal_over` gives `accumReal x ≤ E`. The never-over envelope's image on the output grid is +below `0.934`, so `MARGIN = 1` exceeds it strictly. The round trip needs this strictness to rule out `accumReal x = w` exactly. -/ /-- **Strict never-over.** On the region the real pre-floor accumulator is strictly below the -target. The proven over bound `r0 ≤ scaleQ67·exp(rt) + (5¹⁸/2⁴¹)·B` plus `(5¹⁸/2⁴¹)·B < MARGIN` -give a strictly negative residue. -/ +target. The proven over bound and its image below `MARGIN` give a strictly negative residue. -/ theorem accumReal_over_strict (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : accumReal x < expRayToWadTarget (int256 x) := by @@ -49,14 +47,13 @@ theorem accumReal_over_strict (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < have hfold := target_octave_fold s hsint have hover := r0_real_over_within hx hC hC0 set Ert := Real.exp (reducedArg x) with hErt - -- r0 − MARGIN < scaleQ67·Ert = E·2^s, using (5¹⁸/2⁴⁰)·B < MARGIN + -- r0 − MARGIN < scaleQ67·Ert = E·2^s have hbound : (int256 (r0Tree x) : Real) - 1 < expRayToWadTarget (int256 x) * (2 ^ s : Real) := by rw [hfold] have hwad : (WAD : Real) = (10 ^ 18 : Real) := by unfold WAD; norm_num rw [hwad] - -- (5¹⁸/2⁴⁰)·B < 1 = MARGIN, strictly - have hBM : (3814697265625 * 5737291786393199862 / (10000000000000000000 * 2199023255552) : Real) < 1 := by norm_num + have hBM := over_budget_image_lt_one linarith [hover, hBM] rw [hAeq, div_lt_iff₀ hps]; linarith [hbound] diff --git a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean index 64df92e41..cf3262fc2 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean @@ -4,7 +4,7 @@ namespace ExpYul open FormalYul.Preservation -/-! Runtime constants used by the generated exp kernel normal form. -/ +/-! Runtime constants and derived bounds used by the exp kernel proofs. -/ abbrev Cmask : Nat := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 abbrev C0thresh : Nat := 0x92b2f16cc66c5a4ae96e80d4 @@ -41,6 +41,7 @@ abbrev odShift4 : Nat := 0x80 abbrev todShift : Nat := 0x81 abbrev foldShift : Nat := 0x43 abbrev scaleQ67 : Nat := 0x6f05b59d3b2000000000000000000000 +abbrev scaleMax : Nat := 0x7fffffffffffffffffffffffffffffff abbrev scaleMaxClz : Nat := 0x81 abbrev marginWord : Nat := 0x1 abbrev mulExpRayHi : Nat := 0x119146ae9d22b7454e84ce34c @@ -51,6 +52,18 @@ theorem scaleQ67_eq : (scaleQ67 : Int) = 3814697265625 * 2 ^ 85 := by theorem scaleQ67_lt_2127 : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num +theorem scaleMax_eq : scaleMax = 2 ^ 127 - 1 := by + unfold scaleMax + norm_num + +theorem scaleMax_lt_2127 : scaleMax < 2 ^ 127 := by + unfold scaleMax + norm_num + +theorem scaleQ67_le_scaleMax : scaleQ67 ≤ scaleMax := by + unfold scaleQ67 scaleMax + norm_num + theorem int256_Cmask : int256 Cmask = -41446531673892822312323846185 := by unfold Cmask int256 norm_num diff --git a/formal/exp/ExpProof/ExpProof/Mono/Cross.lean b/formal/exp/ExpProof/ExpProof/Mono/Cross.lean index 457071e79..392c4bc59 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Cross.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Cross.lean @@ -43,9 +43,9 @@ theorem numSum_lt {W : Nat} {ev tod : Int} (hW : int256 W = ev + tod) rw [hW, show (2:Int)^129 = 3 * 2^127 + 2^127 from by ring]; omega /-- The `mul scale N` dividend as a plain `Nat` product when `N`'s signed value is in -`[0, 2^128)` and `scale ≤ scaleQ67`: `evmMul scale N = scale * N` (no wrap), and `N` is its own +`[0, 2^129)` and `scale ≤ scaleMax`: `evmMul scale N = scale * N` (no wrap), and `N` is its own signed value. -/ -theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ scaleQ67) +theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ scaleMax) (hNw : N < 2 ^ 256) (hNnn : 0 ≤ int256 N) (hNlt : int256 N < 2 ^ 129) : evmMul scale N = scale * N ∧ N < 2 ^ 129 := by @@ -53,18 +53,18 @@ theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ scaleQ67) have hNnat : N < 2 ^ 129 := by have : ((N : Nat) : Int) < 2 ^ 129 := by rw [← hNi]; exact hNlt exact_mod_cast this - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) have hfit : scale * N < 2 ^ 256 := by - have h1 : scale * N ≤ scaleQ67 * 2 ^ 129 := + have h1 : scale * N ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hNnat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega exact ⟨evmMul_eq_nat hsw hNw hfit, hNnat⟩ /-- Abstract `r0` monotonicity from the `tod·ev` cross inequality, over opaque even/odd words. Given the numerator/denominator positivity and `tod1·ev2 ≤ tod2·ev1`, the two `div` quotients are `≤`-ordered. -/ -theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleQ67) +theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleMax) (hE1 : E1 < 2 ^ 256) (hTD1 : TD1 < 2 ^ 256) (hE2 : E2 < 2 ^ 256) (hTD2 : TD2 < 2 ^ 256) (hev1_lo : (415147853590918758559635130244235626256 : Int) ≤ (E1 : Int)) (hev1_hi : (E1 : Int) < 3 * 2 ^ 127) @@ -108,16 +108,16 @@ theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleQ67) exact_mod_cast h have hD1nz : evmSub E1 TD1 ≠ 0 := Nat.pos_iff_ne_zero.mp hD1posN have hD2nz : evmSub E2 TD2 ≠ 0 := Nat.pos_iff_ne_zero.mp hD2posN - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) have hfit1 : scale * evmAdd E1 TD1 < 2 ^ 256 := by - have h1 : scale * evmAdd E1 TD1 ≤ scaleQ67 * 2 ^ 129 := + have h1 : scale * evmAdd E1 TD1 ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hN1nat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hfit2 : scale * evmAdd E2 TD2 < 2 ^ 256 := by - have h1 : scale * evmAdd E2 TD2 ≤ scaleQ67 * 2 ^ 129 := + have h1 : scale * evmAdd E2 TD2 ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hN2nat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega -- the two quotients as plain Nat floor divisions have hq1 : evmDiv (evmMul scale (evmAdd E1 TD1)) (evmSub E1 TD1) = diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean index 4b2694aba..8dd59e7af 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -26,11 +26,9 @@ def signTree (y : Nat) : Nat := def absTree (y : Nat) : Nat := evmSub (evmXor y (signTree y)) (signTree y) -/-- The largest shift chosen by the compiled bit-length estimate, corrected by one if the shifted -magnitude exceeds `scaleQ67`. -/ +/-- The scale headroom computed from the magnitude's bit length. -/ def scaleShiftTree (ay : Nat) : Nat := - let s := evmSub (evmClz ay) scaleMaxClz - evmSub s (evmGt (evmShl s ay) scaleQ67) + evmSub (evmClz ay) scaleMaxClz /-- Dynamic pre-shift scale `abs(y) << S`. -/ def mulScaleTree (y : Nat) : Nat := @@ -42,11 +40,9 @@ def mulShiftTree (y x : Nat) : Nat := /-- The branch word for the `Panic(17)` guard. -/ def mulExpGuardTree (y x : Nat) : Nat := - let outOfRange := evmOr (evmGt (absTree y) scaleQ67) (evmIszero (evmSlt x mulExpRayHi)) - let inaccurate := - evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) - (evmSlt (mulShiftTree y x) 2) - evmOr outOfRange inaccurate + let outOfRange := evmOr (evmGt (scaleShiftTree (absTree y)) 127) + (evmSgt x (evmSub mulExpRayHi 1)) + evmOr outOfRange (evmSlt (mulShiftTree y x) 2) /-- The dynamic-scaled quotient before the closing shift. -/ def r0MulTree (y x : Nat) : Nat := diff --git a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean index 4ef344c01..e4c91e7de 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean @@ -266,10 +266,10 @@ theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) /-! ## The scaled quotient at a symbolic scale -/ -/-- Abstract scaled-quotient bounds at a symbolic scale `2^125 ≤ scale ≤ scaleQ67`: `⌊scale·N/D⌋` +/-- Abstract scaled-quotient bounds at a symbolic scale `2^125 ≤ scale ≤ scaleMax`: `⌊scale·N/D⌋` lies in `[2^123, 2^130)`. The lower bound is tight at the minimal scale: `2^123·D < 2^123·2^129 = 2^125·2^127 ≤ scale·N`. -/ -theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD : D < 2 ^ 256) (hDi : int256 D = (D : Int)) (hNpos : 0 < (N : Int)) (hDpos : 0 < (D : Int)) @@ -280,10 +280,10 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : have hNw : N < 2 ^ 256 := by have : (2:Nat) ^ 128 < 2 ^ 256 := by norm_num omega - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleQ67; norm_num) + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) have hfit : scale * N < 2 ^ 256 := by - have h1 : scale * N ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hN) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h1 : scale * N ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hN) + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hmul : evmMul scale N = scale * N := evmMul_eq_nat hsw hNw hfit have hDnat_pos : 0 < D := by exact_mod_cast hDpos @@ -297,10 +297,10 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : have h4 : ((4 * D : Nat) : Int) = 4 * (D : Int) := by push_cast; ring rw [← h4] at hND; exact_mod_cast hND have h1 : scale * N < scale * (4 * D) := (Nat.mul_lt_mul_left hspos).mpr hND' - have h2 : scale * (4 * D) ≤ scaleQ67 * (4 * D) := Nat.mul_le_mul_right _ hshi - have h3 : scaleQ67 * (4 * D) ≤ 2 ^ 130 * D := by - have h4S : (4:Nat) * scaleQ67 ≤ 2 ^ 130 := by unfold scaleQ67; norm_num - calc scaleQ67 * (4 * D) = (4 * scaleQ67) * D := by ring + have h2 : scale * (4 * D) ≤ scaleMax * (4 * D) := Nat.mul_le_mul_right _ hshi + have h3 : scaleMax * (4 * D) ≤ 2 ^ 130 * D := by + have h4S : (4:Nat) * scaleMax ≤ 2 ^ 130 := by unfold scaleMax; norm_num + calc scaleMax * (4 * D) = (4 * scaleMax) * D := by ring _ ≤ 2 ^ 130 * D := Nat.mul_le_mul_right _ h4S omega have hq_ge : 2 ^ 123 ≤ q := by @@ -318,9 +318,9 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : exact ⟨by exact_mod_cast hq_ge, by exact_mod_cast hq_lt⟩ /-- Abstract scaled `r0` bounds over opaque even/odd words: `2^123 ≤ r0 < 2^130` with -`r0 = div(scale·(E+TD), E−TD)` at any `2^125 ≤ scale ≤ scaleQ67`. -/ +`r0 = div(scale·(E+TD), E−TD)` at any `2^125 ≤ scale ≤ scaleMax`. -/ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleQ67) (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) + (hshi : scale ≤ scaleMax) (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) (hev_lo : (415147853590918758559635130244235626256 : Int) ≤ (E : Int)) (hev_hi : (E : Int) < 3 * 2 ^ 127) (htod_lo : -(85070591730234615865843651857942052864 : Int) ≤ int256 TD) @@ -352,8 +352,8 @@ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) have hDpos : 0 < ((evmSub E TD : Nat) : Int) := by rw [← hDi, hsub]; omega exact r0Scaled_bounds_of hslo hshi hNlt128 hDlt128 hDwlt hDi hNpos hDpos hNlo hND -/-- `2^123 ≤ r0ScaledTree scale x < 2^130` on the wide region, for `2^125 ≤ scale ≤ scaleQ67`. -/ -theorem r0Scaled_bounds {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleQ67) +/-- `2^123 ≤ r0ScaledTree scale x < 2^130` on the wide region, for `2^125 ≤ scale ≤ scaleMax`. -/ +theorem r0Scaled_bounds {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : 2 ^ 123 ≤ int256 (r0ScaledTree scale x) ∧ int256 (r0ScaledTree scale x) < 2 ^ 130 := by obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW diff --git a/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean b/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean index dc13c2fc3..74afe71df 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean @@ -51,7 +51,7 @@ theorem r0_mono_adjacent {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) have hr02 : r0Tree x2 = evmDiv (evmMul scaleQ67 (evmAdd (evTree x2) (todTree x2))) (evmSub (evTree x2) (todTree x2)) := rfl rw [hr01, hr02] - exact r0_mono_of_cross (le_refl scaleQ67) hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo + exact r0_mono_of_cross scaleQ67_le_scaleMax hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo htod1hi hev2lo hev2hi htod2lo htod2hi hcross /-- The closing shift words coincide across an octave. -/ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean index 0e062d4fb..04c78e676 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean @@ -9,7 +9,7 @@ magnitude, and at least two bits of closing shift — the kernel magnitude is th the decremented dynamic-scale quotient. The scale-symbolic per-point brackets (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) confine that quotient to `(scale·exp(rt) − 2993/1000 − 1, scale·exp(rt) + 1)` at `scale = mulScaleTree y ∈ -[2^125, scaleQ67]`, and the target fold `A·2^shift = scale·exp(rt)` (`A = abs(y)·exp(x/10²⁷)`) +[2^125, scaleMax]`, and the target fold `A·2^shift = scale·exp(rt)` (`A = abs(y)·exp(x/10²⁷)`) turns the `shr` floor sandwich into the two-unit magnitude bracket `0 ≤ m ≤ A < m + 2`. Sign reapplication then yields the public signed bracket on the whole value domain, with the floor membership `m ∈ {⌊A⌋, ⌊A⌋ − 1}` and the `A < 1 → m = 0` pin as corollaries. @@ -81,7 +81,7 @@ noncomputable section /-- **Live-region magnitude bracket.** On the live region the kernel magnitude `m` is a nonnegative value below `2^128` with `m ≤ A < m + 2`. -/ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (hy0 : y ≠ 0) (habs : absTree y ≤ scaleQ67) + (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : 0 ≤ int256 (mulMagnitudeTree y x) ∧ @@ -89,7 +89,7 @@ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 2 (int256 (mulMagnitudeTree y x) : Real) ≤ mulExpRayMagnitudeTarget (int256 y) (int256 x) ∧ mulExpRayMagnitudeTarget (int256 y) (int256 x) < (int256 (mulMagnitudeTree y x) : Real) + 2 := by - -- the dynamic scale is live: 2^125 ≤ scale ≤ scaleQ67 + -- the dynamic scale is live: 2^125 ≤ scale ≤ scaleMax have hpos : 1 ≤ absTree y := absTree_pos hy hy0 have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs obtain ⟨hs256, hscale_eq, hshi⟩ := mulScaleTree_spec hy habs @@ -184,8 +184,9 @@ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 2 push_cast at h rw [← hWR] linarith [h] - have hBlt1 : (3814697265625 * 5737291786393199862 / - (10000000000000000000 * 2199023255552) : Real) < 1 := by norm_num + have hBlt1 : + (2 * 4668745981919039833 / 10000000000000000000 : Real) < 1 := + over_budget_image_lt_one have h4 : (4:Real) ≤ (2 : Real) ^ (sh : Nat) := by calc (4:Real) = (2:Real) ^ (2:Nat) := by norm_num _ ≤ (2 : Real) ^ (sh : Nat) := by @@ -209,7 +210,7 @@ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 2 /-- Live-region signed bracket for the tree result. -/ theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (hy0 : y ≠ 0) (habs : absTree y ≤ scaleQ67) + (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : MulExpRayBracket (int256 y) (int256 x) (int256 (mulExpTree y x)) := by @@ -271,28 +272,25 @@ theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256 satisfying the signed two-unit magnitude bracket. -/ theorem mulExpRay_run_bracket {y x : Nat} (h : MulExpRayValueDomain y x) : MulExpRayRunBracket y x := by - obtain ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ := h + obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ := h + have habs : absTree y ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale rcases Nat.eq_zero_or_pos y with hy0 | hypos · subst hy0 exact mulExpRay_run_bracket_zero x - ((valueDomain_iff_guard_eq_zero ⟨hy, hx⟩).mp ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩) + ((valueDomain_iff_guard_eq_zero ⟨hy, hx⟩).mp ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩) by_cases hclamp : int256 x ≤ int256 mulExpRayZeroMax - · exact mulExpRay_run_bracket_clamped hy hx habs hclamp + · exact mulExpRay_run_bracket_clamped hy hx habs hlive hclamp by_cases hx0 : int256 x = 0 · have hxw0 : x = 0 := by have h := (int256_zero_iff_of_canonical hx).1 hx0 exact h subst hxw0 - exact mulExpRay_run_bracket_scale_point hy habs + exact mulExpRay_run_bracket_scale_point hy habs hlive · -- the live region - have hlive : 2 ≤ int256 (mulShiftTree y x) := by - rcases hcase with h0 | hcl | hsh - · exact absurd h0 hx0 - · omega - · exact hsh have hWx : WideRegion x := ⟨by omega, hxhi⟩ have hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := - run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ + run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ exact ⟨mulExpTree y x, hrun, mulExpTree_bracket_live hy hx (by omega) habs hx0 hWx hlive⟩ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean index b278fb562..d4f1b446d 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -6,10 +6,9 @@ import ExpProof.Mul.WordBridge The runtime guard partitions canonical calldata into a value path and a `Panic(17)` path. Every multiplier takes the same guard: the magnitude bound, the unconditional upper fence at the first -octave past the deficit envelope, and the accuracy test on the closing shift — the latter waived -at the exact scale point `x = 0` and at or below the zero-clamp cutoff. Each predicate mirrors -one signed comparison of the compiled guard; `int256 (mulShiftTree y x) < 2` is exactly the -runtime's `slt(shift, 2)`. +octave past the deficit envelope, and the accuracy test on the closing shift. Each predicate mirrors +one comparison of the compiled guard; `int256 (mulShiftTree y x) < 2` is exactly the runtime's +`slt(shift, 2)`. -/ namespace ExpYul @@ -17,6 +16,8 @@ namespace ExpYul open FormalYul open FormalYul.Preservation +set_option maxRecDepth 100000 + /-- ABI words transported into this proof layer. -/ def MulExpRayCanonical (y x : Nat) : Prop := y < 2 ^ 256 ∧ x < 2 ^ 256 @@ -24,33 +25,24 @@ def MulExpRayCanonical (y x : Nat) : Prop := /-- The exact successful-input domain induced by the implementation guard. -/ def MulExpRayValueDomain (y x : Nat) : Prop := MulExpRayCanonical y x ∧ - absTree y ≤ scaleQ67 ∧ - int256 x < int256 mulExpRayHi ∧ - (int256 x = 0 ∨ - int256 x ≤ int256 mulExpRayZeroMax ∨ - 2 ≤ int256 (mulShiftTree y x)) + scaleShiftTree (absTree y) ≤ 127 ∧ + int256 x < int256 mulExpRayHi ∧ 2 ≤ int256 (mulShiftTree y x) /-- The exact panic domain induced by the implementation guard. -/ def MulExpRayPanicDomain (y x : Nat) : Prop := MulExpRayCanonical y x ∧ - (scaleQ67 < absTree y ∨ + (127 < scaleShiftTree (absTree y) ∨ int256 mulExpRayHi ≤ int256 x ∨ - (int256 x ≠ 0 ∧ - int256 mulExpRayZeroMax < int256 x ∧ - int256 (mulShiftTree y x) < 2)) + int256 (mulShiftTree y x) < 2) /-- Canonical inputs are either accepted by the value guard or rejected by the panic guard. -/ theorem mulExpRay_value_or_panic_of_canonical {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := by - by_cases hscale : absTree y ≤ scaleQ67 + by_cases hscale : scaleShiftTree (absTree y) ≤ 127 · by_cases hxhi : int256 x < int256 mulExpRayHi - · by_cases hx0 : int256 x = 0 - · exact Or.inl ⟨hcanon, hscale, hxhi, Or.inl hx0⟩ - · by_cases hxlo : int256 x ≤ int256 mulExpRayZeroMax - · exact Or.inl ⟨hcanon, hscale, hxhi, Or.inr (Or.inl hxlo)⟩ - · by_cases hshift : 2 ≤ int256 (mulShiftTree y x) - · exact Or.inl ⟨hcanon, hscale, hxhi, Or.inr (Or.inr hshift)⟩ - · exact Or.inr ⟨hcanon, Or.inr (Or.inr ⟨hx0, by omega, by omega⟩)⟩ + · by_cases hshift : 2 ≤ int256 (mulShiftTree y x) + · exact Or.inl ⟨hcanon, hscale, hxhi, hshift⟩ + · exact Or.inr ⟨hcanon, Or.inr (Or.inr (by omega))⟩ · exact Or.inr ⟨hcanon, Or.inr (Or.inl (by omega))⟩ · exact Or.inr ⟨hcanon, Or.inl (by omega)⟩ @@ -59,13 +51,10 @@ theorem mulExpRay_value_not_panic {y x : Nat} : MulExpRayValueDomain y x → ¬ MulExpRayPanicDomain y x := by intro hv hp obtain ⟨_, hscale, hxhi, hlive⟩ := hv - obtain ⟨_, hbadScale | hbadHi | ⟨hxne, hbadLo, hbadShift⟩⟩ := hp + obtain ⟨_, hbadScale | hbadHi | hbadShift⟩ := hp + · omega · omega · omega - · rcases hlive with hx0 | hxlo | hshift - · exact hxne hx0 - · omega - · omega /-- Canonical inputs are accepted exactly when they are not in the panic domain. -/ theorem mulExpRay_value_iff_not_panic {y x : Nat} (hcanon : MulExpRayCanonical y x) : @@ -83,84 +72,54 @@ theorem mulExpRay_value_iff_not_panic {y x : Nat} (hcanon : MulExpRayCanonical y /-- The guard word is the `if`-encoding of the exact panic condition. -/ theorem mulExpGuardTree_eq_ite {y x : Nat} (hx : x < 2 ^ 256) : mulExpGuardTree y x = - if scaleQ67 < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ - (int256 x ≠ 0 ∧ int256 mulExpRayZeroMax < int256 x ∧ - int256 (mulShiftTree y x) < 2) then 1 else 0 := by + if 127 < scaleShiftTree (absTree y) ∨ int256 mulExpRayHi ≤ int256 x ∨ + int256 (mulShiftTree y x) < 2 then 1 else 0 := by have hux : u256 x = x := u256_of_lt_pow256 hx - have hab : u256 (absTree y) = absTree y := u256_of_lt_pow256 (absTree_lt y) + have hs : u256 (scaleShiftTree (absTree y)) = scaleShiftTree (absTree y) := + u256_of_lt_pow256 (scaleShiftTree_lt _) have hsh : u256 (mulShiftTree y x) = mulShiftTree y x := u256_of_lt_pow256 (mulShiftTree_lt y x) - have hhi : u256 mulExpRayHi = mulExpRayHi := u256_of_lt_pow256 mulExpRayHi_lt - have hzm : u256 mulExpRayZeroMax = mulExpRayZeroMax := u256_of_lt_pow256 mulExpRayZeroMax_lt - have hq : u256 scaleQ67 = scaleQ67 := u256_of_lt_pow256 (by unfold scaleQ67; norm_num) - have h0 : u256 0 = 0 := u256_of_lt_pow256 (by norm_num) + have hhim1 : evmSub mulExpRayHi 1 = mulExpRayHi - 1 := by + unfold evmSub mulExpRayHi u256 WORD_MOD + norm_num + have hhim1w : evmSub mulExpRayHi 1 < 2 ^ 256 := evmSub_lt _ _ + have hhim1u : u256 (evmSub mulExpRayHi 1) = evmSub mulExpRayHi 1 := + u256_of_lt_pow256 hhim1w + have h127 : u256 127 = 127 := u256_of_lt_pow256 (by norm_num) have h2 : u256 2 = 2 := u256_of_lt_pow256 (by norm_num) have hint2 : int256 (u256 2) = 2 := by rw [h2]; unfold int256; norm_num - have hxz : (int256 (u256 x) = 0) = (int256 x = 0) := by rw [hux] + have hhi : int256 (evmSub mulExpRayHi 1) = int256 mulExpRayHi - 1 := by + rw [hhim1, int256_mulExpRayHi] + unfold mulExpRayHi int256 + norm_num + have hscaleCmp : evmGt (scaleShiftTree (absTree y)) 127 = + if 127 < scaleShiftTree (absTree y) then 1 else 0 := by + rw [evmGt_eq_ite, hs, h127] + have hxCmp : evmSgt x (evmSub mulExpRayHi 1) = + if int256 mulExpRayHi ≤ int256 x then 1 else 0 := by + rw [evmSgt_eq_evmSlt_swap, evmSlt_eq_ite, hhim1u, hux, hhi] + split_ifs <;> omega + have hshiftCmp : evmSlt (mulShiftTree y x) 2 = + if int256 (mulShiftTree y x) < 2 then 1 else 0 := by + rw [evmSlt_eq_ite, hsh, hint2] unfold mulExpGuardTree - rw [evmSgt_eq_evmSlt_swap, evmSlt_eq_ite x mulExpRayHi, evmSlt_eq_ite mulExpRayZeroMax x, - evmSlt_eq_ite (mulShiftTree y x) 2, evmGt_eq_ite, evmEq_eq_ite] - rw [hux, hab, hhi, hzm, hq, h0, hsh, hint2] - rw [show (if x = (0 : Nat) then (1 : Nat) else 0) = - if int256 x = 0 then (1 : Nat) else 0 from by - rcases (int256_zero_iff_of_canonical hx) with ⟨h1, h2⟩ - split_ifs with ha hb hb - · rfl - · exact absurd (h2 ha) hb - · exact absurd (h1 hb) ha - · rfl] - rw [evmIszero_ite, evmIszero_ite] - rw [show (if int256 x < int256 mulExpRayHi then (0 : Nat) else 1) = - if int256 mulExpRayHi ≤ int256 x then (1 : Nat) else 0 from by - split_ifs <;> omega] - rw [show (if int256 x = 0 then (0 : Nat) else 1) = - if int256 x ≠ 0 then (1 : Nat) else 0 from by - split_ifs <;> simp_all] - rw [evmAnd_ite, evmAnd_ite, evmOr_ite, evmOr_ite] - congr 1 - simp only [eq_iff_iff] - constructor - · rintro ((h | h) | h) - · exact Or.inl h - · exact Or.inr (Or.inl h) - · exact Or.inr (Or.inr ⟨h.1.1, h.1.2, h.2⟩) - · rintro (h | h | h) - · exact Or.inl (Or.inl h) - · exact Or.inl (Or.inr h) - · exact Or.inr ⟨⟨h.1, h.2.1⟩, h.2.2⟩ + rw [hscaleCmp, hxCmp, evmOr_ite, hshiftCmp, evmOr_ite] + simp only [or_assoc] /-- The guard word is zero exactly on the accepted inputs. -/ theorem mulExpGuardTree_eq_zero_iff {y x : Nat} (hx : x < 2 ^ 256) : mulExpGuardTree y x = 0 ↔ - absTree y ≤ scaleQ67 ∧ int256 x < int256 mulExpRayHi ∧ - (int256 x = 0 ∨ int256 x ≤ int256 mulExpRayZeroMax ∨ - 2 ≤ int256 (mulShiftTree y x)) := by + scaleShiftTree (absTree y) ≤ 127 ∧ int256 x < int256 mulExpRayHi ∧ + 2 ≤ int256 (mulShiftTree y x) := by rw [mulExpGuardTree_eq_ite hx, ite_one_zero_eq_zero_iff] - constructor - · intro h - push_neg at h - obtain ⟨h1, h2, h3⟩ := h - refine ⟨by omega, by omega, ?_⟩ - by_cases hx0 : int256 x = 0 - · exact Or.inl hx0 - · by_cases hzm : int256 x ≤ int256 mulExpRayZeroMax - · exact Or.inr (Or.inl hzm) - · exact Or.inr (Or.inr (by have := h3 hx0 (by omega); omega)) - · intro ⟨h1, h2, h3⟩ - push_neg - refine ⟨by omega, by omega, ?_⟩ - intro hx0 hzm - rcases h3 with h | h | h - · exact absurd h hx0 - · omega - · omega + push_neg + omega /-- The guard word is one exactly on the rejected inputs. -/ theorem mulExpGuardTree_eq_one_iff {y x : Nat} (hx : x < 2 ^ 256) : mulExpGuardTree y x = 1 ↔ - scaleQ67 < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ - (int256 x ≠ 0 ∧ int256 mulExpRayZeroMax < int256 x ∧ - int256 (mulShiftTree y x) < 2) := by + 127 < scaleShiftTree (absTree y) ∨ int256 mulExpRayHi ≤ int256 x ∨ + int256 (mulShiftTree y x) < 2 := by rw [mulExpGuardTree_eq_ite hx, ite_one_zero_eq_one_iff] /-- The value domain is exactly the guard word being zero. -/ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean index 95bd91a77..bc15ba8c0 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean @@ -9,9 +9,9 @@ in the magnitude: shrinking the magnitude only grows the accepted exponent set. case needs no intermediate — a nonpositive multiplier's result is nonpositive and a nonnegative multiplier's is nonnegative, directly from the signed bracket's shape. -The guard also admits the octave vocabulary of the natspec: on canonical inputs, rejection is -exactly a too-large magnitude, an exponent at or beyond the unconditional fence, or a live -exponent whose octave count exceeds the headroom shift less two. +The guard also admits the magnitude vocabulary of the natspec: on canonical inputs, rejection +is exactly a magnitude above `scaleMax`, an exponent at or beyond the unconditional fence, or +an unconditional closing shift below two. -/ namespace ExpYul @@ -26,13 +26,13 @@ set_option maxHeartbeats 1600000 /-! ## Acceptance transfers along the antitone headroom -/ /-- The headroom shift is antitone in the magnitude, including the zero magnitude. -/ -theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleQ67) : +theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleMax) : scaleShiftTree b ≤ scaleShiftTree a := by rcases Nat.eq_zero_or_pos a with h0 | hpos · subst h0 rw [scaleShiftTree_zero] have hb' : absTree b = b := - absTree_nonneg (lt_of_le_of_lt hb (by unfold scaleQ67; norm_num)) + absTree_nonneg (lt_of_le_of_lt hb (by unfold scaleMax; norm_num)) have h := scaleShiftTree_le_127 (y := b) (by rw [hb']; exact hb) rw [hb'] at h exact h @@ -42,22 +42,15 @@ theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleQ67) : theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : y1 < 2 ^ 256) (h2 : MulExpRayValueDomain y2 x) (hab : absTree y1 ≤ absTree y2) : MulExpRayValueDomain y1 x := by - obtain ⟨⟨hy2, hx⟩, habs2, hxhi, hcase⟩ := h2 - have habs1 : absTree y1 ≤ scaleQ67 := le_trans hab habs2 - refine ⟨⟨hy1, hx⟩, habs1, hxhi, ?_⟩ - by_cases hx0 : int256 x = 0 - · exact Or.inl hx0 - by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax - · exact Or.inr (Or.inl hcl) - have hlv2 : 2 ≤ int256 (mulShiftTree y2 x) := by - rcases hcase with h | h | h - · exact absurd h hx0 - · exact absurd h hcl - · exact h - have hW : WideRegion x := ⟨by omega, hxhi⟩ - refine Or.inr (Or.inr ?_) - have ht1 := mulShiftTree_transport hy1 hx habs1 hW - have ht2 := mulShiftTree_transport hy2 hx habs2 hW + obtain ⟨⟨_, hx⟩, hscale2, hxhi, hlv2⟩ := h2 + have habs2 : absTree y2 ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y2)).mp hscale2 + have habs1 : absTree y1 ≤ scaleMax := le_trans hab habs2 + have hscale1 : scaleShiftTree (absTree y1) ≤ 127 := + (scaleShiftTree_le_127_iff (absTree_lt y1)).mpr habs1 + refine ⟨⟨hy1, hx⟩, hscale1, hxhi, ?_⟩ + have ht1 := mulShiftTree_transport_global (y := y1) (x := x) habs1 + have ht2 := mulShiftTree_transport_global (y := y2) (x := x) habs2 have hanti : scaleShiftTree (absTree y2) ≤ scaleShiftTree (absTree y1) := scaleShift_antitone' hab habs2 have hantiI : (scaleShiftTree (absTree y2) : Int) ≤ (scaleShiftTree (absTree y1) : Int) := by @@ -71,7 +64,9 @@ theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : y1 < 2 ^ 256) /-- A nonnegative multiplier's accepted result is nonnegative. -/ theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) (hyw : y < 2 ^ 255) : 0 ≤ int256 (mulExpTree y x) := by - obtain ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ := h + obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlv⟩ := h + have habs : absTree y ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale rcases Nat.eq_zero_or_pos y with h0 | hpos · subst h0 rw [mulExpTree_zero, int256_zero_word'] @@ -82,12 +77,7 @@ theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) subst hxz rw [mulExpTree_scale_point hy habs, int256_of_lt hyw] exact Int.natCast_nonneg y - · have hlv : 2 ≤ int256 (mulShiftTree y x) := by - rcases hcase with h | h | h - · exact absurd h hx0 - · exact absurd h hcl - · exact h - have hW : WideRegion x := ⟨by omega, hxhi⟩ + · have hW : WideRegion x := ⟨by omega, hxhi⟩ obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy hx (by omega) habs hx0 hW hlv rw [int256_tree_pos hpos hyw] @@ -96,7 +86,9 @@ theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) /-- A nonpositive multiplier's accepted result is nonpositive. -/ theorem mulExpTree_result_nonpos {y x : Nat} (h : MulExpRayValueDomain y x) (hyneg : int256 y ≤ 0) : int256 (mulExpTree y x) ≤ 0 := by - obtain ⟨⟨hy, hx⟩, habs, hxhi, hcase⟩ := h + obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlv⟩ := h + have habs : absTree y ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale rcases Nat.eq_zero_or_pos y with h0 | hpos · subst h0 rw [mulExpTree_zero, int256_zero_word'] @@ -112,12 +104,7 @@ theorem mulExpTree_result_nonpos {y x : Nat} (h : MulExpRayValueDomain y x) subst hxz rw [mulExpTree_scale_point hy habs] exact hyneg - · have hlv : 2 ≤ int256 (mulShiftTree y x) := by - rcases hcase with h | h | h - · exact absurd h hx0 - · exact absurd h hcl - · exact h - have hW : WideRegion x := ⟨by omega, hxhi⟩ + · have hW : WideRegion x := ⟨by omega, hxhi⟩ obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy hx (by omega) habs hx0 hW hlv have hm255 := mag_word_small hy (by omega) hx habs hx0 hW hlv @@ -231,42 +218,34 @@ theorem run_mul_exp_ray_evm_mono_joint {y1 y2 x1 x2 : Nat} have h2nn := mulExpTree_result_nonneg h2 hy2small linarith [h1np, h2nn] -/-! ## The octave vocabulary of the guard -/ +/-! ## The guard in magnitude vocabulary -/ -/-- **The panic domain in octave language.** On canonical inputs, `mulExpRay` rejects exactly a -magnitude above the maximal scale, an exponent at or beyond the unconditional fence, or a live -exponent whose octave count exceeds the headroom shift less two. -/ -theorem panicDomain_iff_octave {y x : Nat} (hcanon : MulExpRayCanonical y x) : +/-- **The panic domain in magnitude language.** On canonical inputs, `mulExpRay` rejects exactly +when the magnitude exceeds `scaleMax`, the exponent reaches the unconditional upper fence, or +the unconditional closing-shift guard fails. -/ +theorem panicDomain_iff_magnitude_guard {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayPanicDomain y x ↔ - scaleQ67 < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ - (int256 x ≠ 0 ∧ int256 mulExpRayZeroMax < int256 x ∧ - (scaleShiftTree (absTree y) : Int) - 2 < int256 (kTree x)) := by + scaleMax < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ + int256 (mulShiftTree y x) < 2 := by obtain ⟨hy, hx⟩ := hcanon constructor · rintro ⟨_, hbad⟩ - rcases hbad with h | h | ⟨hx0, hzm, hsh⟩ - · exact Or.inl h + rcases hbad with h | h | h + · have hiff := scaleShiftTree_le_127_iff (absTree_lt y) + exact Or.inl (by + by_contra hcap + have := hiff.mpr (by omega : absTree y ≤ scaleMax) + omega) · exact Or.inr (Or.inl h) - · by_cases habs : absTree y ≤ scaleQ67 - · by_cases hxhi : int256 x < int256 mulExpRayHi - · have hW : WideRegion x := ⟨hzm, hxhi⟩ - have ht := mulShiftTree_transport hy hx habs hW - rw [ht] at hsh - exact Or.inr (Or.inr ⟨hx0, hzm, by linarith [hsh]⟩) - · exact Or.inr (Or.inl (by omega)) - · exact Or.inl (by omega) - · rintro (h | h | ⟨hx0, hzm, hk⟩) - · exact ⟨⟨hy, hx⟩, Or.inl h⟩ + · exact Or.inr (Or.inr h) + · rintro (h | h | h) + · have hiff := scaleShiftTree_le_127_iff (absTree_lt y) + refine ⟨⟨hy, hx⟩, Or.inl ?_⟩ + by_contra hshift + have := hiff.mp (by omega : scaleShiftTree (absTree y) ≤ 127) + omega · exact ⟨⟨hy, hx⟩, Or.inr (Or.inl h)⟩ - · by_cases habs : absTree y ≤ scaleQ67 - · by_cases hxhi : int256 x < int256 mulExpRayHi - · have hW : WideRegion x := ⟨hzm, hxhi⟩ - have ht := mulShiftTree_transport hy hx habs hW - refine ⟨⟨hy, hx⟩, Or.inr (Or.inr ⟨hx0, hzm, ?_⟩)⟩ - rw [ht] - linarith [hk] - · exact ⟨⟨hy, hx⟩, Or.inr (Or.inl (by omega))⟩ - · exact ⟨⟨hy, hx⟩, Or.inl (by omega)⟩ + · exact ⟨⟨hy, hx⟩, Or.inr (Or.inr h)⟩ /-- **The `type(int256).min` multiplier always reverts**: its magnitude word is `2^255`, above the maximal scale. -/ @@ -274,8 +253,11 @@ theorem run_mul_exp_ray_evm_revert_int_min {x : Nat} (hx : x < 2 ^ 256) : run_mul_exp_ray_evm (2 ^ 255) x = .error "revert" := by apply run_mul_exp_ray_evm_revert refine ⟨⟨by norm_num, hx⟩, Or.inl ?_⟩ - rw [absTree_neg (le_refl _) (by norm_num)] - unfold scaleQ67 - norm_num + have hiff := scaleShiftTree_le_127_iff (absTree_lt (2 ^ 255)) + by_contra hshift + have hcap := hiff.mp (by omega : scaleShiftTree (absTree (2 ^ 255)) ≤ 127) + rw [absTree_neg (le_refl _) (by norm_num)] at hcap + unfold scaleMax at hcap + norm_num at hcap end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean index 14f1a5ddc..6aceec1c9 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean @@ -196,109 +196,73 @@ theorem mulExpTree_negative {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) /-! ## The scale headroom realizes the scale exactly -/ -theorem mulScaleTree_spec {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : - scaleShiftTree (absTree y) < 256 ∧ +theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) : + scaleShiftTree (absTree y) ≤ 127 ∧ mulScaleTree y = absTree y * 2 ^ scaleShiftTree (absTree y) ∧ - mulScaleTree y ≤ scaleQ67 := by + mulScaleTree y ≤ scaleMax := by have haylt : absTree y < 2 ^ 256 := absTree_lt y + have hay127 : absTree y < 2 ^ 127 := + lt_of_le_of_lt habs scaleMax_lt_2127 rcases Nat.eq_zero_or_pos (absTree y) with h0 | hpos · have hclz : evmClz 0 = 256 := by unfold evmClz rw [u256_self (by norm_num)] simp - have hs0 : evmSub 256 scaleMaxClz = 127 := by + have hs : evmSub 256 scaleMaxClz = 127 := by rw [evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] unfold scaleMaxClz norm_num + have hsst : scaleShiftTree (absTree y) = 127 := by + rw [h0] + unfold scaleShiftTree + rw [hclz] + exact hs have hshl : evmShl 127 (0 : Nat) = 0 := by rw [evmShl_small (by norm_num) (by norm_num) (by norm_num)] ring - have hgt : evmGt (0 : Nat) scaleQ67 = 0 := by - unfold evmGt - rw [u256_self (by norm_num), u256_self (by unfold scaleQ67; norm_num), if_neg (by omega)] - have hsub : evmSub 127 (0 : Nat) = 127 := evmSub_small (by omega) (by norm_num) - have hsst : scaleShiftTree (absTree y) = 127 := by - unfold scaleShiftTree - simp only [h0, hclz, hs0, hshl, hgt, hsub] have hscale : mulScaleTree y = 0 := by unfold mulScaleTree rw [hsst, h0, hshl] rw [hsst, hscale, h0] - exact ⟨by norm_num, by ring, by unfold scaleQ67; norm_num⟩ + exact ⟨by norm_num, by ring, Nat.zero_le _⟩ · have hlog : Nat.log2 (absTree y) ≤ 126 := by - have h1 : 2 ^ Nat.log2 (absTree y) ≤ absTree y := Nat.log2_self_le (by omega) - have hQ : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num + have h1 : 2 ^ Nat.log2 (absTree y) ≤ absTree y := + Nat.log2_self_le (by omega) by_contra h push_neg at h have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 (absTree y) := Nat.pow_le_pow_right (by norm_num) h omega - have hlt : absTree y < 2 ^ (Nat.log2 (absTree y) + 1) := Nat.lt_log2_self + have hlt : absTree y < 2 ^ (Nat.log2 (absTree y) + 1) := + Nat.lt_log2_self have hclz : evmClz (absTree y) = 255 - Nat.log2 (absTree y) := by unfold evmClz rw [u256_self haylt, if_neg (by omega)] - have hs0eq : evmSub (evmClz (absTree y)) scaleMaxClz = 126 - Nat.log2 (absTree y) := by + have hs : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) := by + unfold scaleShiftTree rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] unfold scaleMaxClz omega have hfit : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) < 2 ^ 127 := by calc absTree y * 2 ^ (126 - Nat.log2 (absTree y)) - < 2 ^ (Nat.log2 (absTree y) + 1) * 2 ^ (126 - Nat.log2 (absTree y)) := + < 2 ^ (Nat.log2 (absTree y) + 1) * + 2 ^ (126 - Nat.log2 (absTree y)) := mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) - _ = 2 ^ (Nat.log2 (absTree y) + 1 + (126 - Nat.log2 (absTree y))) := by + _ = 2 ^ (Nat.log2 (absTree y) + 1 + + (126 - Nat.log2 (absTree y))) := by rw [← pow_add] _ ≤ 2 ^ 127 := Nat.pow_le_pow_right (by norm_num) (by omega) have hshl : evmShl (126 - Nat.log2 (absTree y)) (absTree y) = absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := evmShl_small (by omega) haylt (lt_trans hfit (by norm_num)) - by_cases hover : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) > scaleQ67 - · have hgt : evmGt (absTree y * 2 ^ (126 - Nat.log2 (absTree y))) scaleQ67 = 1 := by - unfold evmGt - rw [u256_self (lt_trans hfit (by norm_num)), - u256_self (by unfold scaleQ67; norm_num), if_pos hover] - have hs0pos : 0 < 126 - Nat.log2 (absTree y) := by - rcases Nat.eq_zero_or_pos (126 - Nat.log2 (absTree y)) with h | h - · rw [h] at hover - simp at hover - omega - · exact h - have hsub : evmSub (126 - Nat.log2 (absTree y)) 1 = 126 - Nat.log2 (absTree y) - 1 := - evmSub_small (by omega) (by omega) - have hsst : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) - 1 := by - unfold scaleShiftTree - simp only [hs0eq, hshl, hgt, hsub] - have hfit' : absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) < 2 ^ 126 := by - calc absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) - < 2 ^ (Nat.log2 (absTree y) + 1) * 2 ^ (126 - Nat.log2 (absTree y) - 1) := - mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) - _ = 2 ^ (Nat.log2 (absTree y) + 1 + (126 - Nat.log2 (absTree y) - 1)) := by - rw [← pow_add] - _ ≤ 2 ^ 126 := Nat.pow_le_pow_right (by norm_num) (by omega) - have hshl' : evmShl (126 - Nat.log2 (absTree y) - 1) (absTree y) = - absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) := - evmShl_small (by omega) haylt - (lt_trans hfit' (by norm_num : (2 : Nat) ^ 126 < 2 ^ 256)) - have hscale : mulScaleTree y = absTree y * 2 ^ (126 - Nat.log2 (absTree y) - 1) := by - unfold mulScaleTree - rw [hsst, hshl'] - rw [hsst, hscale] - have h126 : (2 : Nat) ^ 126 ≤ scaleQ67 := by unfold scaleQ67; norm_num - exact ⟨by omega, rfl, by omega⟩ - · have hgt : evmGt (absTree y * 2 ^ (126 - Nat.log2 (absTree y))) scaleQ67 = 0 := by - unfold evmGt - rw [u256_self (lt_trans hfit (by norm_num)), - u256_self (by unfold scaleQ67; norm_num), if_neg hover] - have hsub : evmSub (126 - Nat.log2 (absTree y)) 0 = 126 - Nat.log2 (absTree y) := - evmSub_small (by omega) (by omega) - have hsst : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) := by - unfold scaleShiftTree - simp only [hs0eq, hshl, hgt, hsub] - have hscale : mulScaleTree y = absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := by - unfold mulScaleTree - rw [hsst, hshl] - rw [hsst, hscale] - exact ⟨by omega, rfl, by omega⟩ - + have hscale : mulScaleTree y = + absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := by + unfold mulScaleTree + rw [hs, hshl] + rw [hs, hscale] + refine ⟨by omega, rfl, ?_⟩ + rw [scaleMax_eq] + omega /-! ## The scale point `x = 0` -/ private theorem kTree_zero : kTree 0 = 0 := by @@ -331,7 +295,7 @@ private theorem todTree_zero : todTree 0 = 0 := by norm_num [evmSar, evmMul, u256, WORD_MOD] private theorem r0MulTree_scale_point {y : Nat} (hy : y < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) : r0MulTree y 0 = mulScaleTree y := by + (habs : absTree y ≤ scaleMax) : r0MulTree y 0 = mulScaleTree y := by obtain ⟨_, _, hcap⟩ := mulScaleTree_spec hy habs unfold r0MulTree have hnum : evmAdd (evTree 0) (todTree 0) = ev4 := by @@ -344,8 +308,8 @@ private theorem r0MulTree_scale_point {y : Nat} (hy : y < 2 ^ 256) rw [hnum, hden] exact evmDiv_exact (by unfold ev4; norm_num) (mulScaleTree_lt y) (by unfold ev4; norm_num) (by - calc mulScaleTree y * ev4 ≤ scaleQ67 * ev4 := Nat.mul_le_mul_right _ hcap - _ < 2 ^ 256 := by unfold scaleQ67 ev4; norm_num) + calc mulScaleTree y * ev4 ≤ scaleMax * ev4 := Nat.mul_le_mul_right _ hcap + _ < 2 ^ 256 := by unfold scaleMax ev4; norm_num) private theorem mulShiftTree_scale_point (y : Nat) : mulShiftTree y 0 = scaleShiftTree (absTree y) := by @@ -354,10 +318,10 @@ private theorem mulShiftTree_scale_point (y : Nat) : omega theorem mulMagnitudeTree_scale_point {y : Nat} (hy : y < 2 ^ 256) - (hpos : 0 < absTree y) (habs : absTree y ≤ scaleQ67) : + (hpos : 0 < absTree y) (habs : absTree y ≤ scaleMax) : mulMagnitudeTree y 0 = absTree y := by obtain ⟨hs256, hscale, hcap⟩ := mulScaleTree_spec hy habs - have hQlt : scaleQ67 < 2 ^ 256 := by unfold scaleQ67; norm_num + have hQlt : scaleMax < 2 ^ 256 := by unfold scaleMax; norm_num have hscalepos : 0 < mulScaleTree y := by rw [hscale] exact Nat.mul_pos hpos (Nat.two_pow_pos _) @@ -382,7 +346,7 @@ theorem mulMagnitudeTree_scale_point {y : Nat} (hy : y < 2 ^ 256) rw [hsub] have hshr : evmShr (scaleShiftTree (absTree y)) (absTree y * 2 ^ scaleShiftTree (absTree y) - 1) = absTree y - 1 := by - rw [evmShr_small hs256 (by omega)] + rw [evmShr_small (by omega) (by omega)] generalize scaleShiftTree (absTree y) = S obtain ⟨k, hk⟩ : ∃ k, absTree y = k + 1 := ⟨absTree y - 1, by omega⟩ rw [hk] @@ -402,7 +366,7 @@ theorem mulMagnitudeTree_scale_point {y : Nat} (hy : y < 2 ^ 256) omega /-- **Scale point (tree).** At `x = 0`, the result word is the multiplier itself. -/ -theorem mulExpTree_scale_point {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : +theorem mulExpTree_scale_point {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) : mulExpTree y 0 = y := by rcases Nat.eq_zero_or_pos y with h0 | hypos · subst h0 @@ -442,26 +406,28 @@ theorem mulExpTree_clamped {y x : Nat} (hx : x < 2 ^ 256) private theorem int256_zero_word : int256 (0 : Nat) = 0 := by unfold int256; norm_num -/-- **Scale point.** `mulExpRay(y, 0)` returns `y` for every supported magnitude. -/ +/-- **Scale point.** `mulExpRay(y, 0)` returns `y` whenever the two-bit closing-shift guard accepts. -/ theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : y < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) : + (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := by + obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy habs have hguard : mulExpGuardTree y 0 = 0 := by rw [mulExpGuardTree_eq_zero_iff (by norm_num)] - refine ⟨habs, ?_, Or.inl int256_zero_word⟩ + refine ⟨hs127, ?_, hshift⟩ rw [int256_mulExpRayHi, int256_zero_word] norm_num have h := run_mul_exp_ray_evm_eq_tree_of_guard y 0 hguard rwa [mulExpTree_scale_point hy habs] at h -/-- **Clamp.** `mulExpRay(y, x)` returns zero at or below the zero cutoff, for every supported -magnitude. -/ +/-- **Clamp.** An accepted `mulExpRay(y, x)` returns zero at or below the zero cutoff. -/ theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : + (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) + (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : run_mul_exp_ray_evm y x = .ok 0 := by + obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy habs have hguard : mulExpGuardTree y x = 0 := by rw [mulExpGuardTree_eq_zero_iff hx] - refine ⟨habs, ?_, Or.inr (Or.inl hclamp)⟩ + refine ⟨hs127, ?_, hshift⟩ rw [int256_mulExpRayHi] rw [int256_mulExpRayZeroMax] at hclamp omega @@ -474,8 +440,9 @@ noncomputable section /-- **Scale-point bracket.** The exact result `y` satisfies the public bracket at `x = 0`. -/ theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : y < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) : MulExpRayRunBracket y 0 := by - refine ⟨y, run_mul_exp_ray_evm_scale_point hy habs, ?_⟩ + (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : + MulExpRayRunBracket y 0 := by + refine ⟨y, run_mul_exp_ray_evm_scale_point hy habs hshift, ?_⟩ rw [int256_zero_word] have hA : mulExpRayMagnitudeTarget (int256 y) 0 = ((int256 y).natAbs : ℝ) := by unfold mulExpRayMagnitudeTarget @@ -504,8 +471,8 @@ theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : y < 2 ^ 256) linarith /-- Below the zero cutoff, every supported magnitude's real target is below one. -/ -theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : +theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleMax) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : mulExpRayMagnitudeTarget (int256 y) (int256 x) < 1 := by unfold mulExpRayMagnitudeTarget have hRAY : (RAY : ℝ) = 10 ^ 27 := by unfold RAY; push_cast; norm_num @@ -524,11 +491,11 @@ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) rw [Real.log_pow]; push_cast; ring] rw [Real.exp_log (by positivity)] ring - have hnat : ((int256 y).natAbs : ℝ) ≤ ((scaleQ67 : Nat) : ℝ) := by + have hnat : ((int256 y).natAbs : ℝ) ≤ ((scaleMax : Nat) : ℝ) := by have h := absTree_eq_natAbs hy exact_mod_cast (h ▸ habs) - have hQ : ((scaleQ67 : Nat) : ℝ) < (2 : ℝ) ^ (127 : ℕ) := by - unfold scaleQ67 + have hQ : ((scaleMax : Nat) : ℝ) < (2 : ℝ) ^ (127 : ℕ) := by + unfold scaleMax norm_num calc ((int256 y).natAbs : ℝ) * Real.exp z ≤ (2 : ℝ) ^ (127 : ℕ) * Real.exp z := by @@ -539,9 +506,10 @@ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) /-- **Clamp bracket.** The zero result satisfies the public bracket at or below the cutoff. -/ theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : + (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) + (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : MulExpRayRunBracket y x := by - refine ⟨0, run_mul_exp_ray_evm_clamped hy hx habs hclamp, ?_⟩ + refine ⟨0, run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp, ?_⟩ rw [int256_zero_word] have hlt := clamped_target_lt_one hy hx habs hclamp have hnn := mulExpRayMagnitudeTarget_nonneg (int256 y) (int256 x) diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean index 1d7d2a4e9..0946de217 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -11,8 +11,8 @@ shift `S − k`. This module transports those words to arithmetic facts the accu monotonicity arguments consume: * the headroom shift `S` is at most `127`, and for a nonzero magnitude the scale is *maximal* — - one more doubling overshoots `scaleQ67` — which pins it into `(scaleQ67/2, scaleQ67]`, so every - live scale satisfies `2^125 ≤ scale ≤ scaleQ67`; + the all-ones 127-bit cap aligns every nonzero supported magnitude into `[2^126, 2^127)`, so every + live scale satisfies `2^125 ≤ scale ≤ scaleMax`; * the closing-shift word is the signed difference `S − k` on the wide region, and on the live region (`2 ≤ shift` from the guard) it is a plain small `Nat` in `[2, 254]`; * the closing `shr` keeps nonnegative small values small for any shift below the word size. @@ -44,169 +44,211 @@ private theorem evmShl_small {s v : Nat} (hs : s < 256) (hv : v < 2 ^ 256) unfold u256 WORD_MOD omega -/-! ## The headroom shift: range and scale maximality -/ +/-! ## The headroom shift and normalized scale -/ -/-- The corrected headroom shift, by cases on the magnitude: `127` exactly at zero, and otherwise -at most `126` with the shifted scale maximal (one more doubling overshoots `scaleQ67`). -/ -private theorem scaleShiftTree_cases (ay : Nat) (hy : ay < 2 ^ 256) (habs : ay ≤ scaleQ67) : - (ay = 0 → scaleShiftTree ay = 127) ∧ - (1 ≤ ay → scaleShiftTree ay ≤ 126 ∧ - scaleQ67 < ay * 2 ^ (scaleShiftTree ay + 1)) := by +/-- Every positive supported magnitude aligns its highest set bit with bit 126. -/ +private theorem scaleShiftTree_pos {ay : Nat} (hy : ay < 2 ^ 256) + (hpos : 1 ≤ ay) (habs : ay ≤ scaleMax) : + scaleShiftTree ay = 126 - Nat.log2 ay := by + have hay127 : ay < 2 ^ 127 := lt_of_le_of_lt habs scaleMax_lt_2127 + have hlog : Nat.log2 ay ≤ 126 := by + have h1 : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) + by_contra h + push_neg at h + have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 ay := + Nat.pow_le_pow_right (by norm_num) h + omega + have hclz : evmClz ay = 255 - Nat.log2 ay := by + unfold evmClz + rw [u256_self hy, if_neg (by omega)] + unfold scaleShiftTree + rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] + unfold scaleMaxClz + omega + +/-- The zero magnitude takes the maximal headroom shift. -/ +theorem scaleShiftTree_zero : scaleShiftTree 0 = 127 := by + have hclz : evmClz 0 = 256 := by + unfold evmClz + rw [u256_self (by norm_num)] + simp + unfold scaleShiftTree + rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] + unfold scaleMaxClz + norm_num + +/-- The maximal supported magnitude has no normalization headroom. -/ +theorem scaleShiftTree_scaleMax : scaleShiftTree scaleMax = 0 := by + have hscaleMax : scaleMax ≠ 0 := by unfold scaleMax; norm_num + have hloglo : 126 ≤ Nat.log2 scaleMax := + (Nat.le_log2 hscaleMax).2 (by unfold scaleMax; norm_num) + have hloghi : Nat.log2 scaleMax < 127 := + (Nat.log2_lt hscaleMax).2 (by unfold scaleMax; norm_num) + have hlog : Nat.log2 scaleMax = 126 := by omega + rw [scaleShiftTree_pos (by unfold scaleMax; norm_num) (by unfold scaleMax; norm_num) + (le_refl _), hlog] + +/-- The headroom shift never exceeds 127 on supported magnitudes. -/ +theorem scaleShiftTree_le_127 {y : Nat} (habs : absTree y ≤ scaleMax) : + scaleShiftTree (absTree y) ≤ 127 := by + rcases Nat.eq_zero_or_pos (absTree y) with h0 | hpos + · rw [h0, scaleShiftTree_zero] + · rw [scaleShiftTree_pos (absTree_lt y) hpos habs] + omega + +/-- The derived headroom guard is exactly the 127-bit magnitude cap. -/ +theorem scaleShiftTree_le_127_iff {ay : Nat} (hay : ay < 2 ^ 256) : + scaleShiftTree ay ≤ 127 ↔ ay ≤ scaleMax := by constructor - · intro h0 - subst h0 - have hclz : evmClz 0 = 256 := by - unfold evmClz - rw [u256_self (by norm_num)] - simp - have hs0 : evmSub 256 scaleMaxClz = 127 := by - rw [evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] - unfold scaleMaxClz - norm_num - have hshl : evmShl 127 (0 : Nat) = 0 := by - rw [evmShl_small (by norm_num) (by norm_num) (by norm_num)] - ring - have hgt : evmGt (0 : Nat) scaleQ67 = 0 := by - unfold evmGt - rw [u256_self (by norm_num), u256_self (by unfold scaleQ67; norm_num), if_neg (by omega)] - have hsub : evmSub 127 (0 : Nat) = 127 := evmSub_small (by omega) (by norm_num) - unfold scaleShiftTree - simp only [hclz, hs0, hshl, hgt, hsub] - · intro hpos - have hlog : Nat.log2 ay ≤ 126 := by - have h1 : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) - have hQ : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num + · intro hs + by_contra hcap + push_neg at hcap + have haylo : 2 ^ 127 ≤ ay := by + rw [scaleMax_eq] at hcap + omega + have hpos : 1 ≤ ay := by omega + have hloglo : 127 ≤ Nat.log2 ay := by + by_contra h + push_neg at h + have hlt := Nat.lt_log2_self (n := ay) + have hp : (2 : Nat) ^ (Nat.log2 ay + 1) ≤ 2 ^ 127 := + Nat.pow_le_pow_right (by norm_num) (by omega) + omega + have hloghi : Nat.log2 ay ≤ 255 := by + have hp := Nat.log2_self_le (by omega : ay ≠ 0) by_contra h push_neg at h - have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 ay := + have hpow : (2 : Nat) ^ 256 ≤ 2 ^ Nat.log2 ay := Nat.pow_le_pow_right (by norm_num) h omega - have hloglo : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) - have hlt : ay < 2 ^ (Nat.log2 ay + 1) := Nat.lt_log2_self have hclz : evmClz ay = 255 - Nat.log2 ay := by unfold evmClz - rw [u256_self hy, if_neg (by omega)] - have hs0eq : evmSub (evmClz ay) scaleMaxClz = 126 - Nat.log2 ay := by - rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] + rw [u256_self hay, if_neg (by omega)] + have hc : 255 - Nat.log2 ay < 129 := by omega + have hraw : 255 - Nat.log2 ay + 2 ^ 256 - 129 < 2 ^ 256 := by + omega + have hsub : scaleShiftTree ay = 255 - Nat.log2 ay + 2 ^ 256 - 129 := by + unfold scaleShiftTree + rw [hclz, evmSub_eq_mod_pow256 (by omega) (by unfold scaleMaxClz; norm_num)] unfold scaleMaxClz + rw [Nat.mod_eq_of_lt hraw] + rw [hsub] at hs + omega + · intro hcap + rcases Nat.eq_zero_or_pos ay with h0 | hpos + · rw [h0, scaleShiftTree_zero] + · rw [scaleShiftTree_pos hay hpos hcap] omega - have hfit : ay * 2 ^ (126 - Nat.log2 ay) < 2 ^ 127 := by - calc ay * 2 ^ (126 - Nat.log2 ay) - < 2 ^ (Nat.log2 ay + 1) * 2 ^ (126 - Nat.log2 ay) := - mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) - _ = 2 ^ (Nat.log2 ay + 1 + (126 - Nat.log2 ay)) := by rw [← pow_add] - _ ≤ 2 ^ 127 := Nat.pow_le_pow_right (by norm_num) (by omega) - have hshl : evmShl (126 - Nat.log2 ay) ay = ay * 2 ^ (126 - Nat.log2 ay) := - evmShl_small (by omega) hy (lt_trans hfit (by norm_num)) - -- the uncorrected scale already clears half of scaleQ67: ay·2^(126−log2) ≥ 2^126 > scaleQ67/2 - have hbig : (2 : Nat) ^ 126 ≤ ay * 2 ^ (126 - Nat.log2 ay) := by - calc (2:Nat) ^ 126 ≤ 2 ^ Nat.log2 ay * 2 ^ (126 - Nat.log2 ay) := by - rw [← pow_add] - exact Nat.pow_le_pow_right (by norm_num) (by omega) - _ ≤ ay * 2 ^ (126 - Nat.log2 ay) := Nat.mul_le_mul_right _ hloglo - by_cases hover : ay * 2 ^ (126 - Nat.log2 ay) > scaleQ67 - · have hgt : evmGt (ay * 2 ^ (126 - Nat.log2 ay)) scaleQ67 = 1 := by - unfold evmGt - rw [u256_self (lt_trans hfit (by norm_num)), - u256_self (by unfold scaleQ67; norm_num), if_pos hover] - have hs0pos : 0 < 126 - Nat.log2 ay := by - rcases Nat.eq_zero_or_pos (126 - Nat.log2 ay) with h | h - · rw [h] at hover - simp at hover - omega - · exact h - have hsub : evmSub (126 - Nat.log2 ay) 1 = 126 - Nat.log2 ay - 1 := - evmSub_small (by omega) (by omega) - have hsst : scaleShiftTree ay = 126 - Nat.log2 ay - 1 := by - unfold scaleShiftTree - simp only [hs0eq, hshl, hgt, hsub] - refine ⟨by omega, ?_⟩ - rw [hsst] - have hexp : 126 - Nat.log2 ay - 1 + 1 = 126 - Nat.log2 ay := by omega - rw [hexp] - exact hover - · have hgt : evmGt (ay * 2 ^ (126 - Nat.log2 ay)) scaleQ67 = 0 := by - unfold evmGt - rw [u256_self (lt_trans hfit (by norm_num)), - u256_self (by unfold scaleQ67; norm_num), if_neg hover] - have hsub : evmSub (126 - Nat.log2 ay) 0 = 126 - Nat.log2 ay := - evmSub_small (by omega) (by omega) - have hsst : scaleShiftTree ay = 126 - Nat.log2 ay := by - unfold scaleShiftTree - simp only [hs0eq, hshl, hgt, hsub] - refine ⟨by omega, ?_⟩ - rw [hsst] - -- doubling the uncorrected scale clears 2^127 > scaleQ67 - have hQ : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num - calc scaleQ67 < 2 ^ 127 := hQ - _ = 2 ^ 126 * 2 := by ring - _ ≤ ay * 2 ^ (126 - Nat.log2 ay) * 2 := Nat.mul_le_mul_right _ hbig - _ = ay * 2 ^ (126 - Nat.log2 ay + 1) := by rw [pow_succ]; ring -/-- The zero magnitude takes the maximal headroom shift. -/ -theorem scaleShiftTree_zero : scaleShiftTree 0 = 127 := - (scaleShiftTree_cases 0 (by norm_num) (by unfold scaleQ67; norm_num)).1 rfl - -/-- The headroom shift never exceeds `127` on supported magnitudes. -/ -theorem scaleShiftTree_le_127 {y : Nat} (habs : absTree y ≤ scaleQ67) : - scaleShiftTree (absTree y) ≤ 127 := by - obtain ⟨h0, hpos⟩ := scaleShiftTree_cases (absTree y) (absTree_lt y) habs - rcases Nat.eq_zero_or_pos (absTree y) with h | h - · omega - · have := (hpos h).1 +/-- Scale maximality: for a nonzero supported magnitude, one more doubling of the normalized +scale exceeds the 127-bit cap. -/ +theorem mulScaleTree_max {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) + (habs : absTree y ≤ scaleMax) : scaleMax < 2 * mulScaleTree y := by + obtain ⟨_, hscale, _⟩ := mulScaleTree_spec hy habs + have hs := scaleShiftTree_pos (absTree_lt y) hpos habs + have hloglo : 2 ^ Nat.log2 (absTree y) ≤ absTree y := + Nat.log2_self_le (by omega) + have hlog : Nat.log2 (absTree y) ≤ 126 := by + have hay127 : absTree y < 2 ^ 127 := + lt_of_le_of_lt habs scaleMax_lt_2127 + by_contra h + push_neg at h + have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 (absTree y) := + Nat.pow_le_pow_right (by norm_num) h omega + have hbig : (2 : Nat) ^ 126 ≤ + absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := by + calc (2 : Nat) ^ 126 + ≤ 2 ^ Nat.log2 (absTree y) * + 2 ^ (126 - Nat.log2 (absTree y)) := by + rw [← pow_add] + exact Nat.pow_le_pow_right (by norm_num) (by omega) + _ ≤ absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := + Nat.mul_le_mul_right _ hloglo + rw [hscale, hs, scaleMax_eq] + omega -/-- **Scale maximality.** For a nonzero supported magnitude, one more doubling of the headroom -scale overshoots `scaleQ67`. -/ -theorem mulScaleTree_max {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) - (habs : absTree y ≤ scaleQ67) : scaleQ67 < 2 * mulScaleTree y := by - obtain ⟨_, hspec, _⟩ := mulScaleTree_spec hy habs - obtain ⟨_, hposcase⟩ := scaleShiftTree_cases (absTree y) (absTree_lt y) habs - obtain ⟨_, hmax⟩ := hposcase hpos - rw [hspec] - calc scaleQ67 < absTree y * 2 ^ (scaleShiftTree (absTree y) + 1) := hmax - _ = 2 * (absTree y * 2 ^ scaleShiftTree (absTree y)) := by rw [pow_succ]; ring - -/-- **Scale lower bound.** Every nonzero supported magnitude's headroom scale is at least -`2^125`. -/ +/-- Every nonzero supported magnitude's normalized scale is at least 2^125. -/ theorem mulScaleTree_lower {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) - (habs : absTree y ≤ scaleQ67) : 2 ^ 125 ≤ mulScaleTree y := by + (habs : absTree y ≤ scaleMax) : 2 ^ 125 ≤ mulScaleTree y := by have hmax := mulScaleTree_max hy hpos habs - have hQ : (2:Nat) ^ 126 ≤ scaleQ67 := by unfold scaleQ67; norm_num + have hQ : (2 : Nat) ^ 126 ≤ scaleMax := by + unfold scaleMax + norm_num omega - /-! ## The closing-shift word -/ -/-- The closing-shift word carries the signed difference `S − k` on the wide region. -/ -theorem mulShiftTree_transport {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) : +/-- The arithmetic right shift that forms the octave index keeps it in a signed 64-bit range, +independently of the exponent word. -/ +theorem kTree_global_bounds (x : Nat) : + -(2 ^ 63) ≤ int256 (kTree x) ∧ int256 (kTree x) < 2 ^ 63 := by + set w := evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x) with hwdef + have hw : w < 2 ^ 256 := by + rw [hwdef] + exact evmAdd_lt _ _ + have hword : -(2 ^ 255) ≤ int256 w ∧ int256 w < 2 ^ 255 := by + unfold int256 + split_ifs <;> omega + have hsar := Common.Word.evmSar_sandwich (s := kRoundShift) + (by unfold kRoundShift; norm_num) hw + have hk : kTree x = evmSar kRoundShift w := by rw [hwdef]; rfl + rw [← hk] at hsar + unfold kRoundShift at hsar + constructor <;> nlinarith [hword.1, hword.2, hsar.2.1, hsar.2.2] + +/-- The closing shift carries the signed difference globally on supported magnitudes. The octave +word's signed 64-bit range leaves ample room for the headroom shift in `[0, 127]`, so the EVM +subtraction cannot cross either signed boundary. -/ +theorem mulShiftTree_transport_global {y x : Nat} (habs : absTree y ≤ scaleMax) : int256 (mulShiftTree y x) = (scaleShiftTree (absTree y) : Int) - int256 (kTree x) := by have hs127 := scaleShiftTree_le_127 habs - obtain ⟨hklo, hkhi⟩ := kTree_bound_wide hx hW + obtain ⟨hklo, hkhi⟩ := kTree_global_bounds x have hsw : scaleShiftTree (absTree y) < 2 ^ 256 := scaleShiftTree_lt _ have hkw : kTree x < 2 ^ 256 := by unfold kTree; exact evmSar_lt _ _ have hsi : int256 (scaleShiftTree (absTree y)) = (scaleShiftTree (absTree y) : Int) := - int256_of_lt (by - have : (127:Nat) < 2 ^ 255 := by norm_num - omega) + int256_of_lt (by omega) unfold mulShiftTree rw [evmSub_transport hsw hkw ?_ ?_, hsi] · rw [hsi] - have hs : (scaleShiftTree (absTree y) : Int) ≤ 127 := by exact_mod_cast hs127 have hs0 : (0 : Int) ≤ (scaleShiftTree (absTree y) : Int) := Int.natCast_nonneg _ + have hs : (scaleShiftTree (absTree y) : Int) ≤ 127 := by exact_mod_cast hs127 simp only [ipow255] - linarith [hs, hs0, hklo, hkhi] + nlinarith [hs0, hs, hklo, hkhi] · rw [hsi] have hs0 : (0 : Int) ≤ (scaleShiftTree (absTree y) : Int) := Int.natCast_nonneg _ have hs : (scaleShiftTree (absTree y) : Int) ≤ 127 := by exact_mod_cast hs127 simp only [ipow255] - linarith [hs, hs0, hklo, hkhi] + nlinarith [hs0, hs, hklo, hkhi] + +/-- At the magnitude cap, an exponent in octave `-2` has exactly the minimum accepted closing +shift and lies in the value domain whenever it is below the unconditional upper fence. -/ +theorem scaleMax_octave_neg_two_valueDomain {x : Nat} (hx : x < 2 ^ 256) + (hxhi : int256 x < int256 mulExpRayHi) (hk : int256 (kTree x) = -2) : + scaleShiftTree (absTree scaleMax) = 0 ∧ + int256 (mulShiftTree scaleMax x) = 2 ∧ + MulExpRayValueDomain scaleMax x := by + have hy : scaleMax < 2 ^ 256 := by unfold scaleMax; norm_num + have habs : absTree scaleMax = scaleMax := + absTree_nonneg (by unfold scaleMax; norm_num) + have hcap : absTree scaleMax ≤ scaleMax := by rw [habs] + have hs : scaleShiftTree (absTree scaleMax) = 0 := by rw [habs, scaleShiftTree_scaleMax] + have hshift : int256 (mulShiftTree scaleMax x) = 2 := by + rw [mulShiftTree_transport_global hcap, hs, hk] + norm_num + exact ⟨hs, hshift, ⟨⟨hy, hx⟩, by rw [hs]; norm_num, hxhi, by omega⟩⟩ + +/-- The closing-shift word carries the signed difference `S − k` on the wide region. -/ +theorem mulShiftTree_transport {y x : Nat} (_hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) + (habs : absTree y ≤ scaleMax) (_hW : WideRegion x) : + int256 (mulShiftTree y x) = + (scaleShiftTree (absTree y) : Int) - int256 (kTree x) := + mulShiftTree_transport_global habs /-- On the live region the closing-shift word is a plain small `Nat` in `[2, 254]`, equal to `S − k` on the signed side. -/ theorem mulShift_word_facts {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) + (habs : absTree y ≤ scaleMax) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : 2 ≤ mulShiftTree y x ∧ mulShiftTree y x < 256 ∧ (mulShiftTree y x : Int) = int256 (mulShiftTree y x) := by diff --git a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean index bc0dd261f..c543c605b 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean @@ -51,7 +51,7 @@ private theorem mulShift_word_eq {y x1 x2 : Nat} /-- The signed shift is antitone in the exponent (the octave index is monotone). -/ theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (habs : absTree y ≤ scaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hle : int256 x1 ≤ int256 x2) : int256 (mulShiftTree y x2) ≤ int256 (mulShiftTree y x1) := by rw [mulShiftTree_transport hy hx1 habs hW1, mulShiftTree_transport hy hx2 habs hW2] @@ -60,7 +60,7 @@ theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) /-- The decremented quotient word: transport and range at the dynamic scale. -/ theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) (hW : WideRegion x) : + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW : WideRegion x) : int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 ∧ 0 ≤ int256 (r0MulTree y x) - 1 ∧ int256 (r0MulTree y x) - 1 < 2 ^ 130 := by have hpos : 1 ≤ absTree y := absTree_pos hy hy0 @@ -91,7 +91,7 @@ theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- Adjacent same-octave quotient monotonicity at the dynamic scale. -/ theorem r0Mul_mono_adjacent {y x1 x2 : Nat} (hy : y < 2 ^ 256) - (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hk : int256 (kTree x1) = int256 (kTree x2)) (hadj : int256 x2 = int256 x1 + 1) : @@ -122,7 +122,7 @@ theorem r0Mul_mono_adjacent {y x1 x2 : Nat} (hy : y < 2 ^ 256) /-- **The live unit step**: for adjacent live exponents the kernel magnitude is nondecreasing. -/ theorem mulMagnitude_step {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hx10 : int256 x1 ≠ 0) (hx20 : int256 x2 ≠ 0) (hlive1 : 2 ≤ int256 (mulShiftTree y x1)) (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) @@ -201,7 +201,7 @@ theorem mulMagnitude_step {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) (the endpoint's live shift bounds every intermediate through octave monotonicity, and the sign condition keeps the scale point outside the range). -/ theorem mulMagnitude_mono_steps {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleQ67) (n : Nat) : + (habs : absTree y ≤ scaleMax) (n : Nat) : ∀ x1 : Nat, x1 < 2 ^ 256 → int256 mulExpRayZeroMax < int256 x1 → int256 x1 + n < int256 mulExpRayHi → @@ -300,7 +300,7 @@ theorem mulMagnitude_mono_steps {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- **Region monotonicity of the live magnitude**: for live exponents `x1 ≤ x2` on a common sign side, the kernel magnitude is nondecreasing. -/ theorem mulMagnitude_region_mono {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleQ67) + (habs : absTree y ≤ scaleMax) (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hle : int256 x1 ≤ int256 x2) @@ -355,18 +355,18 @@ private theorem kTree_one : int256 (kTree 1) = 0 := by /-- The magnitude at the scale point is the multiplier's magnitude. -/ theorem int256_mulMagnitude_zero {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleQ67) : + (habs : absTree y ≤ scaleMax) : int256 (mulMagnitudeTree y 0) = (absTree y : Int) := by have hpos : 0 < absTree y := absTree_pos hy hy0 rw [mulMagnitudeTree_scale_point hy hpos habs] - exact int256_of_lt (lt_of_le_of_lt habs (by unfold scaleQ67; norm_num)) + exact int256_of_lt (lt_of_le_of_lt habs (lt_trans scaleMax_lt_2127 (by norm_num))) /-- **The analytic pin step.** At `x = 1` the live magnitude is at least the multiplier's magnitude: one exponent unit is worth `scale/10²⁷ ≥ 2⁹⁸` quotient units, far above the deficit envelope, so the decremented quotient still clears `scale` and its closing shift clears `abs(y)`. -/ theorem mulMagnitude_pin_step {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleQ67) + (habs : absTree y ≤ scaleMax) (hlive1 : 2 ≤ int256 (mulShiftTree y 1)) : (absTree y : Int) ≤ int256 (mulMagnitudeTree y 1) := by have hx1 : (1 : Nat) < 2 ^ 256 := by norm_num @@ -450,7 +450,8 @@ theorem mulMagnitude_pin_step {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) push_cast linarith [hq2I] exact_mod_cast h1 - rw [evmShr_eq_div hs256 halt] + have hslt256 : S < 256 := by omega + rw [evmShr_eq_div hslt256 halt] have hdiv : ay ≤ arg / 2 ^ S := by rw [Nat.le_div_iff_mul_le (Nat.two_pow_pos _)] calc ay * 2 ^ S = sc := hscale_eq.symm @@ -464,7 +465,7 @@ theorem mulMagnitude_pin_step {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- A negative live exponent's magnitude never exceeds the multiplier's magnitude: its real target is already below it. -/ theorem mulMagnitude_le_abs_of_neg {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW : WideRegion x) (hxneg : int256 x < 0) (hlive : 2 ≤ int256 (mulShiftTree y x)) : int256 (mulMagnitudeTree y x) ≤ (absTree y : Int) := by @@ -546,7 +547,7 @@ theorem int256_tree_neg {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) /-- The live magnitude word stays below `2^255`. -/ theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : mulMagnitudeTree y x < 2 ^ 255 := by @@ -562,7 +563,7 @@ theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- A positive live exponent's magnitude is at least the multiplier's magnitude (through the analytic pin step at `x = 1`). -/ theorem mulMagnitude_ge_abs_of_pos {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW : WideRegion x) (hxpos : 0 < int256 x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : (absTree y : Int) ≤ int256 (mulMagnitudeTree y x) := by @@ -588,7 +589,7 @@ theorem mulMagnitude_ge_abs_of_pos {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0 /-- **Magnitude monotonicity over the live region**, both sign sides, through the scale point. -/ theorem mulMagnitude_mono_pair {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleQ67) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hx10 : int256 x1 ≠ 0) (hx20 : int256 x2 ≠ 0) (hlive1 : 2 ≤ int256 (mulShiftTree y x1)) (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) @@ -614,12 +615,12 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} (h1 : MulExpRayValueDomain y x1) (h2 : MulExpRayValueDomain y x2) (hle : int256 x1 ≤ int256 x2) : MulExpRayRunMonotone y x1 x2 := by - obtain ⟨⟨hy, hx1w⟩, habs1, hxhi1, hcase1⟩ := h1 - obtain ⟨⟨_, hx2w⟩, habs2, hxhi2, hcase2⟩ := h2 have hrun1 : run_mul_exp_ray_evm y x1 = .ok (mulExpTree y x1) := - run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx1w⟩, habs1, hxhi1, hcase1⟩ + run_mul_exp_ray_evm_eq_tree h1 have hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2) := - run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx2w⟩, habs2, hxhi2, hcase2⟩ + run_mul_exp_ray_evm_eq_tree h2 + obtain ⟨⟨hy, hx1w⟩, hscale1, hxhi1, hshift1⟩ := h1 + obtain ⟨⟨_, hx2w⟩, _, hxhi2, hshift2⟩ := h2 refine ⟨mulExpTree y x1, mulExpTree y x2, hrun1, hrun2, hle, ?_⟩ rcases Nat.eq_zero_or_pos y with hy0 | hypos · subst hy0 @@ -627,25 +628,22 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} split <;> exact le_refl 0 have hy0 : y ≠ 0 := Nat.pos_iff_ne_zero.mp hypos -- the signed magnitude of each accepted result - have habs := habs1 + have habs : absTree y ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale1 -- classify each exponent: clamp, scale point, or live - have hclass : ∀ x : Nat, x < 2 ^ 256 → int256 x < int256 mulExpRayHi → - (int256 x = 0 ∨ int256 x ≤ int256 mulExpRayZeroMax ∨ 2 ≤ int256 (mulShiftTree y x)) → + have hclass : ∀ x : Nat, x < 2 ^ 256 → 2 ≤ int256 (mulShiftTree y x) → int256 x ≤ int256 mulExpRayZeroMax ∨ x = 0 ∨ (int256 mulExpRayZeroMax < int256 x ∧ int256 x ≠ 0 ∧ 2 ≤ int256 (mulShiftTree y x)) := by - intro x hxw hxhi hcase + intro x hxw hshift by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax · exact Or.inl hcl by_cases hx0 : int256 x = 0 · exact Or.inr (Or.inl ((int256_zero_iff_of_canonical hxw).1 hx0)) - · rcases hcase with h | h | h - · exact absurd h hx0 - · exact absurd h hcl - · exact Or.inr (Or.inr ⟨by omega, hx0, h⟩) + · exact Or.inr (Or.inr ⟨by omega, hx0, hshift⟩) -- the two sign branches share the magnitude comparisons - rcases hclass x1 hx1w hxhi1 hcase1 with hc1 | hp1 | ⟨hzm1, hx10, hlv1⟩ <;> - rcases hclass x2 hx2w hxhi2 hcase2 with hc2 | hp2 | ⟨hzm2, hx20, hlv2⟩ + rcases hclass x1 hx1w hshift1 with hc1 | hp1 | ⟨hzm1, hx10, hlv1⟩ <;> + rcases hclass x2 hx2w hshift2 with hc2 | hp2 | ⟨hzm2, hx20, hlv2⟩ -- (clamp, clamp) · rw [mulExpTree_clamped hx1w hc1, mulExpTree_clamped hx2w hc2] split <;> exact le_refl _ diff --git a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean index ca67e17f4..7fc693b33 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean @@ -28,18 +28,18 @@ set_option maxHeartbeats 1600000 /-! ## Magnitude words normalize through the absolute value -/ /-- A supported magnitude word is its own absolute value. -/ -private theorem absTree_of_small {a : Nat} (ha : a ≤ scaleQ67) : absTree a = a := - absTree_nonneg (lt_of_le_of_lt ha (by unfold scaleQ67; norm_num)) +private theorem absTree_of_small {a : Nat} (ha : a ≤ scaleMax) : absTree a = a := + absTree_nonneg (lt_of_le_of_lt ha (by unfold scaleMax; norm_num)) /-- The kernel magnitude depends on the multiplier only through its magnitude word. -/ -theorem mulMagnitude_abs_norm {y : Nat} (habs : absTree y ≤ scaleQ67) (x : Nat) : +theorem mulMagnitude_abs_norm {y : Nat} (habs : absTree y ≤ scaleMax) (x : Nat) : mulMagnitudeTree y x = mulMagnitudeTree (absTree y) x := by have h : absTree (absTree y) = absTree y := absTree_of_small habs unfold mulMagnitudeTree mulShiftTree r0MulTree mulScaleTree rw [h] /-- The closing shift depends on the multiplier only through its magnitude word. -/ -theorem mulShift_abs_norm {y : Nat} (habs : absTree y ≤ scaleQ67) (x : Nat) : +theorem mulShift_abs_norm {y : Nat} (habs : absTree y ≤ scaleMax) (x : Nat) : mulShiftTree y x = mulShiftTree (absTree y) x := by have h : absTree (absTree y) = absTree y := absTree_of_small habs unfold mulShiftTree @@ -48,11 +48,11 @@ theorem mulShift_abs_norm {y : Nat} (habs : absTree y ≤ scaleQ67) (x : Nat) : /-! ## Headroom arithmetic from scale maximality -/ /-- The headroom shift is antitone in the magnitude. -/ -theorem scaleShift_antitone {a b : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleQ67) : +theorem scaleShift_antitone {a b : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleMax) : scaleShiftTree b ≤ scaleShiftTree a := by - have haQ : a ≤ scaleQ67 := le_trans hab hb - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) - have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleQ67; norm_num) + have haQ : a ≤ scaleMax := le_trans hab hb + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) + have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleMax; norm_num) have haa : absTree a = a := absTree_of_small haQ have hba : absTree b = b := absTree_of_small hb have hmax := mulScaleTree_max (y := a) haw (by rw [haa]; exact ha) (by rw [haa]; exact haQ) @@ -82,11 +82,11 @@ theorem scaleShift_antitone {a b : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b omega /-- A unit magnitude step drops the headroom shift by at most one. -/ -theorem scaleShift_step {a : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleQ67) : +theorem scaleShift_step {a : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleMax) : scaleShiftTree a ≤ scaleShiftTree (a + 1) + 1 := by - have haQ : a ≤ scaleQ67 := le_trans (Nat.le_succ a) ha1 - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) - have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleQ67; norm_num) + have haQ : a ≤ scaleMax := le_trans (Nat.le_succ a) ha1 + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) + have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleMax; norm_num) have haa : absTree a = a := absTree_of_small haQ have ha1a : absTree (a + 1) = a + 1 := absTree_of_small ha1 obtain ⟨_, hspec_a, hcap_a⟩ := mulScaleTree_spec (y := a) haw (by rw [haa]; exact haQ) @@ -136,7 +136,7 @@ theorem num_den_ratio {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : linarith [hev, htod_lo, htod_hi] /-- The scaled quotient is monotone in the scale at a fixed exponent. -/ -theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 ≤ scaleQ67) +theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (r0ScaledTree sc1 x) ≤ int256 (r0ScaledTree sc2 x) := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW @@ -175,16 +175,16 @@ theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 rw [hp126] linarith [hev, htod_hi] exact_mod_cast h - have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt (le_trans h12 hshi2) (by unfold scaleQ67; norm_num) - have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleQ67; norm_num) + have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt (le_trans h12 hshi2) (by unfold scaleMax; norm_num) + have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleMax; norm_num) have hfit1 : sc1 * num < 2 ^ 256 := by - have h1 : sc1 * num ≤ scaleQ67 * 2 ^ 129 := + have h1 : sc1 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul (le_trans h12 hshi2) (le_of_lt hnumnat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hfit2 : sc2 * num < 2 ^ 256 := by - have h1 : sc2 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h1 : sc2 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hq1 : r0ScaledTree sc1 x = sc1 * num / den := by show evmDiv (evmMul sc1 num) den = _ @@ -212,7 +212,7 @@ theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 `2·sc2 = sc1 + 2^S` with `S ≥ 1` gives `r0(sc1) ≤ 2·r0(sc2)` (`2·num > den` pays the floor loss). -/ theorem r0Scaled_double_scale {sc1 sc2 S x : Nat} (hS : 1 ≤ S) - (hid : 2 * sc2 = sc1 + 2 ^ S) (hshi1 : sc1 ≤ scaleQ67) (hshi2 : sc2 ≤ scaleQ67) + (hid : 2 * sc2 = sc1 + 2 ^ S) (hshi1 : sc1 ≤ scaleMax) (hshi2 : sc2 ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (r0ScaledTree sc1 x) ≤ 2 * int256 (r0ScaledTree sc2 x) := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW @@ -258,15 +258,15 @@ theorem r0Scaled_double_scale {sc1 sc2 S x : Nat} (hS : 1 ≤ S) rw [← hdeneq, ← hnumeq, hadd, hsub] exact hratio exact_mod_cast h1 - have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt hshi1 (by unfold scaleQ67; norm_num) - have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleQ67; norm_num) + have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt hshi1 (by unfold scaleMax; norm_num) + have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleMax; norm_num) have hfit1 : sc1 * num < 2 ^ 256 := by - have h1 : sc1 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi1 (le_of_lt hnumnat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h1 : sc1 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi1 (le_of_lt hnumnat) + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hfit2 : sc2 * num < 2 ^ 256 := by - have h1 : sc2 * num ≤ scaleQ67 * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) - have h2 : scaleQ67 * 2 ^ 129 < 2 ^ 256 := by unfold scaleQ67; norm_num + have h1 : sc2 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) + have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num omega have hq1 : r0ScaledTree sc1 x = sc1 * num / den := by show evmDiv (evmMul sc1 num) den = _ @@ -375,12 +375,12 @@ theorem seam_close_odd {arg1 arg2 s1 s2 : Nat} /-! ## The adjacent magnitude step -/ /-- The signed closing shift is antitone in the magnitude word. -/ -theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleQ67) +theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (mulShiftTree b x) ≤ int256 (mulShiftTree a x) := by - have haQ : a ≤ scaleQ67 := le_trans hab hb - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) - have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleQ67; norm_num) + have haQ : a ≤ scaleMax := le_trans hab hb + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) + have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleMax; norm_num) have haa : absTree a = a := absTree_of_small haQ have hba : absTree b = b := absTree_of_small hb have hta := mulShiftTree_transport (y := a) haw hx (by rw [haa]; exact haQ) hW @@ -394,13 +394,13 @@ theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b /-- **The adjacent magnitude step**: at a fixed live exponent, one unit of magnitude never decreases the kernel magnitude. -/ -theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleQ67) +theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) (hlive2 : 2 ≤ int256 (mulShiftTree (a + 1) x)) : int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + 1) x) := by - have haQ : a ≤ scaleQ67 := le_trans (Nat.le_succ a) ha1 - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleQ67; norm_num) - have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleQ67; norm_num) + have haQ : a ≤ scaleMax := le_trans (Nat.le_succ a) ha1 + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) + have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleMax; norm_num) have haa : absTree a = a := absTree_of_small haQ have ha1a : absTree (a + 1) = a + 1 := absTree_of_small ha1 have hlive1 : 2 ≤ int256 (mulShiftTree a x) := @@ -506,7 +506,7 @@ theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleQ67) intermediate through the headroom antitonicity. -/ theorem mulMagnitudeY_mono_steps {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) (n : Nat) : - ∀ a : Nat, 1 ≤ a → a + n ≤ scaleQ67 → + ∀ a : Nat, 1 ≤ a → a + n ≤ scaleMax → 2 ≤ int256 (mulShiftTree (a + n) x) → int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + n) x) := by induction n with @@ -533,7 +533,7 @@ theorem mulMagnitudeY_mono_steps {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x /-- **Magnitude monotonicity in the multiplier at a fixed live exponent.** -/ theorem mulMagnitudeY_region_mono {a1 a2 x : Nat} (ha1 : 1 ≤ a1) (h12 : a1 ≤ a2) - (ha2 : a2 ≤ scaleQ67) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) + (ha2 : a2 ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) (hlive2 : 2 ≤ int256 (mulShiftTree a2 x)) : int256 (mulMagnitudeTree a1 x) ≤ int256 (mulMagnitudeTree a2 x) := by have h := mulMagnitudeY_mono_steps hx hW hx0 (a2 - a1) a1 ha1 @@ -549,12 +549,16 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} (h1 : MulExpRayValueDomain y1 x) (h2 : MulExpRayValueDomain y2 x) (hle : int256 y1 ≤ int256 y2) : MulExpRayRunYMonotone y1 y2 x := by - obtain ⟨⟨hy1, hxw⟩, habs1, hxhi, hcase1⟩ := h1 - obtain ⟨⟨hy2, _⟩, habs2, _, hcase2⟩ := h2 have hrun1 : run_mul_exp_ray_evm y1 x = .ok (mulExpTree y1 x) := - run_mul_exp_ray_evm_eq_tree ⟨⟨hy1, hxw⟩, habs1, hxhi, hcase1⟩ + run_mul_exp_ray_evm_eq_tree h1 have hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x) := - run_mul_exp_ray_evm_eq_tree ⟨⟨hy2, hxw⟩, habs2, hxhi, hcase2⟩ + run_mul_exp_ray_evm_eq_tree h2 + obtain ⟨⟨hy1, hxw⟩, hscale1, hxhi, hshift1⟩ := h1 + obtain ⟨⟨hy2, _⟩, hscale2, _, hshift2⟩ := h2 + have habs1 : absTree y1 ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y1)).mp hscale1 + have habs2 : absTree y2 ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y2)).mp hscale2 refine ⟨mulExpTree y1 x, mulExpTree y2 x, hrun1, hrun2, hle, ?_⟩ -- the exponent's class decides the result shape by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax @@ -566,16 +570,8 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} exact hle -- the live region have hW : WideRegion x := ⟨by omega, hxhi⟩ - have hlive : ∀ y : Nat, y < 2 ^ 256 → absTree y ≤ scaleQ67 → - (int256 x = 0 ∨ int256 x ≤ int256 mulExpRayZeroMax ∨ - 2 ≤ int256 (mulShiftTree y x)) → 2 ≤ int256 (mulShiftTree y x) := by - intro y _ _ hcase - rcases hcase with h | h | h - · exact absurd h hx0 - · exact absurd h hcl - · exact h - have hlv1 := hlive y1 hy1 habs1 hcase1 - have hlv2 := hlive y2 hy2 habs2 hcase2 + have hlv1 := hshift1 + have hlv2 := hshift2 -- the live magnitudes, at the magnitude words rcases Nat.eq_zero_or_pos y1 with hz1 | hp1 · subst hz1 diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 9ac706516..d714d2c7a 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -20,6 +20,7 @@ open FormalYul.Preservation open Common.Word set_option maxRecDepth 100000 +set_option Elab.async false /-- `zero_value_for_split_t_int256()` returns the word `0`. -/ theorem call_zero_value_for_split_t_int256_direct @@ -172,7 +173,7 @@ theorem call_cleanup_t_rational_67_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_cleanup_t_rational_SCALE_MAX_direct +theorem call_cleanup_t_rational_WAD_SCALE_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : @@ -349,7 +350,7 @@ theorem call_convert_67_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_convert_SCALE_MAX_to_uint256_direct +theorem call_convert_WAD_SCALE_to_uint256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : @@ -369,7 +370,7 @@ theorem call_convert_SCALE_MAX_to_uint256_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h1 := - call_cleanup_t_rational_SCALE_MAX_direct + call_cleanup_t_rational_WAD_SCALE_direct (v := 0x6f05b59d3b2000000000000000000000) (fuel := fuel + extra) (extra := 92) (shared := shared) (store := Finmap.insert "value" (FormalYul.word 0x6f05b59d3b2000000000000000000000) @@ -449,26 +450,26 @@ theorem call_convert_WAD_ZERO_MAX_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_constant__SCALE_MAX_direct +theorem call_constant__WAD_SCALE_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__SCALE_MAX) + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__WAD_SCALE) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x6f05b59d3b2000000000000000000000]) := by rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX] - simp only [yulFunctionBody_constant__SCALE_MAX, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__WAD_SCALE] + simp only [yulFunctionBody_constant__WAD_SCALE, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hconv := - call_convert_SCALE_MAX_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) + call_convert_WAD_SCALE_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) (shared := shared) - (store := Finmap.insert "expr_125" + (store := Finmap.insert "expr_128" (FormalYul.word 0x6f05b59d3b2000000000000000000000) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) @@ -537,8 +538,6 @@ theorem call_wrapping_sub_t_int256_direct (hlookup := hlookup) simp [FormalYul.word] at hcleanup simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.evalCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, @@ -658,8 +657,8 @@ theorem call_fun__octave_direct simp only [wordNat_sar, FormalYul.Preservation.wordNat_shiftLeft, FormalYul.Preservation.wordNat_add, FormalYul.Preservation.wordNat_mul, FormalYul.Preservation.wordNat_ofNat] - simp only [FormalYul.Preservation.evmAdd_u256_left, - FormalYul.Preservation.evmMul_u256_left, FormalYul.Preservation.evmMul_u256_right, + simp only [FormalYul.Preservation.evmMul_u256_left, + FormalYul.Preservation.evmMul_u256_right, FormalYul.Preservation.evmShl_u256_left, FormalYul.Preservation.evmShl_u256_right, evmSar_u256_left] have hsar : @@ -822,19 +821,19 @@ theorem call_zero_value_for_split_t_bool_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_cleanup_t_rational_0_direct +theorem call_cleanup_t_rational_1_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] - (.some "cleanup_t_rational_0_by_1") (.some yulContract) + (.some "cleanup_t_rational_1_by_1") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_cleanup_t_rational_0_by_1] - simp only [yulFunction_cleanup_t_rational_0_by_1, + lookup_cleanup_t_rational_1_by_1] + simp only [yulFunction_cleanup_t_rational_1_by_1, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -866,6 +865,28 @@ theorem call_cleanup_t_rational_2_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +theorem call_cleanup_t_rational_127_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_127_by_1") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_127_by_1] + simp only [yulFunction_cleanup_t_rational_127_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + theorem call_cleanup_t_rational_129_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -932,35 +953,35 @@ theorem call_cleanup_t_rational_MUL_EXP_RAY_ZERO_MAX_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_convert_0_to_int256_direct +theorem call_convert_2_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0] - (.some "convert_t_rational_0_by_1_to_t_int256") + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 2] + (.some "convert_t_rational_2_by_1_to_t_int256") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 2]) := by rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_convert_t_rational_0_by_1_to_t_int256] - simp only [yulFunction_convert_t_rational_0_by_1_to_t_int256, + lookup_convert_t_rational_2_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_2_by_1_to_t_int256, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h1 := - call_cleanup_t_rational_0_direct (v := 0) (fuel := fuel + extra) (extra := 92) + call_cleanup_t_rational_2_direct (v := 2) (fuel := fuel + extra) (extra := 92) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 0) (Inhabited.default : EvmYul.Yul.VarStore)) + (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h2 := - call_identity_direct (v := 0) (fuel := fuel + extra) (extra := 94) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 0) (Inhabited.default : EvmYul.Yul.VarStore)) + call_identity_direct (v := 2) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h3 := - call_cleanup_t_int256_direct (v := 0) (fuel := fuel + extra) (extra := 96) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 0) (Inhabited.default : EvmYul.Yul.VarStore)) + call_cleanup_t_int256_direct (v := 2) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) simp [FormalYul.word] at h1 h2 h3 simp +decide [EvmYul.Yul.execCall.eq_def, @@ -972,35 +993,76 @@ theorem call_convert_0_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_convert_2_to_int256_direct +theorem call_convert_1_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 2] - (.some "convert_t_rational_2_by_1_to_t_int256") + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 1] + (.some "convert_t_rational_1_by_1_to_t_int256") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 2]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 1]) := by rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_convert_t_rational_2_by_1_to_t_int256] - simp only [yulFunction_convert_t_rational_2_by_1_to_t_int256, + lookup_convert_t_rational_1_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_1_by_1_to_t_int256, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h1 := - call_cleanup_t_rational_2_direct (v := 2) (fuel := fuel + extra) (extra := 92) + call_cleanup_t_rational_1_direct (v := 1) (fuel := fuel + extra) (extra := 92) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) + (store := Finmap.insert "value" (FormalYul.word 1) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h2 := - call_identity_direct (v := 2) (fuel := fuel + extra) (extra := 94) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) + call_identity_direct (v := 1) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 1) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h3 := - call_cleanup_t_int256_direct (v := 2) (fuel := fuel + extra) (extra := 96) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 2) (Inhabited.default : EvmYul.Yul.VarStore)) + call_cleanup_t_int256_direct (v := 1) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 1) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_convert_127_to_uint256_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0x7f] + (.some "convert_t_rational_127_by_1_to_t_uint256") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x7f]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_127_by_1_to_t_uint256] + simp only [yulFunction_convert_t_rational_127_by_1_to_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_127_direct (v := 0x7f) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0x7f) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_uint256_direct (v := 0x7f) (fuel := fuel + extra) (extra := 96) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) simp [FormalYul.word] at h1 h2 h3 simp +decide [EvmYul.Yul.execCall.eq_def, @@ -1219,7 +1281,7 @@ theorem call_constant__SCALE_MAX_CLZ_direct have hconv := call_convert_129_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) (shared := shared) - (store := Finmap.insert "expr_128" (FormalYul.word scaleMaxClz) + (store := Finmap.insert "expr_125" (FormalYul.word scaleMaxClz) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) simp [FormalYul.word, scaleMaxClz] at hconv @@ -1255,8 +1317,6 @@ theorem call_wrapping_sub_t_uint256_direct (hlookup := hlookup) simp [FormalYul.word] at hcleanup simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.evalCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, @@ -1282,8 +1342,8 @@ theorem call_fun_clz_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, @@ -1388,8 +1448,8 @@ theorem call_fun_or_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, @@ -1399,33 +1459,6 @@ theorem call_fun_or_direct call_zero_value_for_split_t_bool_direct (fuel := fuel + extra) (extra := 56) (shared := shared) (hlookup := hlookup)] -theorem call_fun_and_direct - (a b fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word a, FormalYul.word b] (.some yulName_fun_and) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmAnd a b)]) := by - rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_fun_and] - simp only [yulFunctionBody_fun_and, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, - FormalYul.Preservation.uint256_ofNat_and_eq_word_evmAnd, - call_zero_value_for_split_t_bool_direct (fuel := fuel + extra) (extra := 56) - (shared := shared) (hlookup := hlookup)] - theorem uint256_ofNat_sgt_eq_word_evmSgt (a b : Nat) : EvmYul.UInt256.sgt (EvmYul.UInt256.ofNat a) (EvmYul.UInt256.ofNat b) = FormalYul.word (evmSgt a b) := by diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index 8a46d639c..152103054 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -42,8 +42,7 @@ theorem call_fun_mulExpRay_revert_direct EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] let sign := signTree y let ay := absTree y - let s0 := evmSub (evmClz ay) scaleMaxClz - let s := evmSub s0 (evmGt (evmShl s0 ay) scaleQ67) + let s := evmSub (evmClz ay) scaleMaxClz let k := kTree x let shift := evmSub s k have hzeroInit := @@ -61,168 +60,122 @@ theorem call_fun_mulExpRay_revert_direct have hscaleMaxClz := call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 2023) (shared := shared) (hlookup := hlookup) - have hwrapS0 := + have hwrapS := call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) - have hscaleMax1 := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2020) - (shared := shared) (hlookup := hlookup) have hoctave := - call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2055) + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2058) (shared := shared) (hlookup := hlookup) have hconvertS := - call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2051) + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2054) (shared := shared) (hlookup := hlookup) have hwrapShift := - call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2088) - (shared := shared) (hlookup := hlookup) - have hscaleMax2 := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2004) + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2091) (shared := shared) (hlookup := hlookup) - have hcleanupScaleMax := - call_cleanup_t_uint256_direct (v := scaleQ67) (fuel := fuel + extra) (extra := 2141) + have hconvert127 := + call_convert_127_to_uint256_direct (fuel := fuel + extra) (extra := 2044) (shared := shared) (hlookup := hlookup) - have hcleanupAyGuard := - call_cleanup_t_uint256_direct (v := ay) (fuel := fuel + extra) (extra := 2139) + have hcleanupSGuard := + call_cleanup_t_uint256_direct (v := s) (fuel := fuel + extra) (extra := 2142) (shared := shared) (hlookup := hlookup) have hHi := - call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 1998) + call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2001) (shared := shared) (hlookup := hlookup) - have hcleanupHi := - call_cleanup_t_int256_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 2133) + have hconvertOne := + call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2037) (shared := shared) (hlookup := hlookup) + have hsubHi := + call_wrapping_sub_t_int256_direct (x := mulExpRayHi) (y := 1) + (fuel := fuel + extra) (extra := 2079) (shared := shared) (hlookup := hlookup) + have hcleanupHiMinusOne := + call_cleanup_t_int256_direct (v := evmSub mulExpRayHi 1) + (fuel := fuel + extra) (extra := 2136) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2131) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2134) (shared := shared) (hlookup := hlookup) have hOrOut := - call_fun_or_direct (a := evmGt ay scaleQ67) (b := evmIszero (evmSlt x mulExpRayHi)) - (fuel := fuel + extra) (extra := 2076) (shared := shared) (hlookup := hlookup) - have hconvertZeroEq := - call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 2027) - (shared := shared) (hlookup := hlookup) - have hcleanupXEq := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2125) - (shared := shared) (hlookup := hlookup) - have hZM1 := - call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1986) - (shared := shared) (hlookup := hlookup) - have hcleanupZM := - call_cleanup_t_int256_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 2123) - (shared := shared) (hlookup := hlookup) - have hcleanupXForLo := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2121) - (shared := shared) (hlookup := hlookup) - have hAndLo := - call_fun_and_direct (a := evmIszero (evmEq x 0)) (b := evmSgt x mulExpRayZeroMax) - (fuel := fuel + extra) (extra := 2064) (shared := shared) (hlookup := hlookup) + call_fun_or_direct (a := evmGt s 127) (b := evmSgt x (evmSub mulExpRayHi 1)) + (fuel := fuel + extra) (extra := 2077) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2017) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2030) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2115) - (shared := shared) (hlookup := hlookup) - have hAndAccuracy := - call_fun_and_direct - (a := evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) - (b := evmSlt shift 2) (fuel := fuel + extra) (extra := 2058) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2128) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct - (a := evmOr (evmGt ay scaleQ67) (evmIszero (evmSlt x mulExpRayHi))) - (b := evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) - (evmSlt shift 2)) - (fuel := fuel + extra) (extra := 2057) (shared := shared) (hlookup := hlookup) + (a := evmOr (evmGt s 127) (evmSgt x (evmSub mulExpRayHi 1))) + (b := evmSlt shift 2) + (fuel := fuel + extra) (extra := 2071) (shared := shared) (hlookup := hlookup) have hoverflow := - call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1972) + call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1986) (shared := shared) (hlookup := hlookup) have hconvu := - call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2011) + call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2025) (shared := shared) (hlookup := hlookup) have hpanic := - call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1530) + call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1544) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS0 - simp only [Nat.reduceAdd, FormalYul.word] at hscaleMax1 hscaleMax2 + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave - simp only [Nat.reduceAdd, FormalYul.word, s, s0, ay, absTree, signTree, scaleMaxClz, - scaleQ67] at hconvertS - simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, s0, ay, absTree, signTree, scaleMaxClz, - scaleQ67] at hwrapShift - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, - scaleQ67] at hcleanupScaleMax hcleanupAyGuard + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] at hconvertS + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, scaleMaxClz] + at hwrapShift + simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] + at hcleanupSGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, mulExpRayHi] at hHi - simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hcleanupHi + simp only [Nat.reduceAdd, FormalYul.word] at hconvertOne + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hsubHi hcleanupHiMinusOne simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, ay, absTree, signTree, scaleQ67, - mulExpRayHi] at hOrOut - simp only [Nat.reduceAdd, FormalYul.word] at hconvertZeroEq hcleanupXEq - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, - mulExpRayZeroMax] at hZM1 - simp only [Nat.reduceAdd, FormalYul.word, mulExpRayZeroMax] at hcleanupZM - simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForLo - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, - mulExpRayZeroMax] at hAndLo + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, s, ay, absTree, signTree, + scaleMaxClz, mulExpRayHi] at hOrOut simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo - simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, s0, ay, absTree, signTree, - scaleMaxClz, scaleQ67] at hcleanupShift - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, k, kTree, shift, s, s0, ay, absTree, - signTree, scaleMaxClz, scaleQ67, mulExpRayZeroMax] at hAndAccuracy - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, s0, ay, absTree, - signTree, scaleMaxClz, scaleQ67, mulExpRayHi, mulExpRayZeroMax] at hOrGuard + simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, + scaleMaxClz] at hcleanupShift + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, ay, absTree, + signTree, scaleMaxClz, mulExpRayHi] at hOrGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant_ARITHMETIC_OVERFLOW] at hoverflow simp only [Nat.reduceAdd, FormalYul.word] at hconvu simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_panic] at hpanic have hguardUnfold : evmOr (evmOr - (evmGt (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)) - 147573952589676412928000000000000000000) - (evmIszero (evmSlt x 86989971160273136331862631244))) - (evmAnd - (evmAnd (evmIszero (evmEq x 0)) - (evmSgt x 115792089237316195423570985008687907853269984665552187773936190980962432544451)) + (evmGt + (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) + 127) + (evmSgt x (evmSub 86989971160273136331862631244 1))) (evmSlt (evmSub - (evmSub (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmGt - (evmShl (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) - 147573952589676412928000000000000000000)) + (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) - 2)) = 1 := by - simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, scaleQ67, - scaleMaxClz, mulExpRayHi, mulExpRayZeroMax] using hguard + 2) = 1 := by + simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, + scaleMaxClz, mulExpRayHi] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, - EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, - hguard, hguardUnfold, - hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS0, - hscaleMax1, hoctave, hconvertS, hwrapShift, hscaleMax2, hcleanupScaleMax, hcleanupAyGuard, - hHi, hcleanupHi, hcleanupXForHi, hOrOut, hconvertZeroEq, hcleanupXEq, hZM1, hcleanupZM, - hcleanupXForLo, hAndLo, hconvertTwo, hcleanupShift, hAndAccuracy, hOrGuard, + EvmYul.Yul.State.setStore, + FormalYul.word, + hguardUnfold, + hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS, + hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, + hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hOrOut, + hconvertTwo, hcleanupShift, hOrGuard, hoverflow, hconvu, hpanic, - FormalYul.Preservation.uint256_ofNat_eq_eq_word_evmEq, FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, - FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl, Common.Word.uint256_ofNat_xor_eq_word_evmXor, Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, uint256_ofNat_sgt_eq_word_evmSgt, - uint256_ofNat_iszero_eq_word_evmIszero, - mulExpGuardTree, mulShiftTree, kTree, scaleShiftTree, absTree, signTree, - scaleQ67, scaleMaxClz, mulExpRayHi, mulExpRayZeroMax, - sign, ay, s0, s, k, shift] + scaleMaxClz] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay` forwards the revert. -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 642c140b0..918be7dbf 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -42,8 +42,7 @@ theorem call_fun_mulExpRay_direct EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] let sign := signTree y let ay := absTree y - let s0 := evmSub (evmClz ay) scaleMaxClz - let s := evmSub s0 (evmGt (evmShl s0 ay) scaleQ67) + let s := evmSub (evmClz ay) scaleMaxClz let k := kTree x let shift := evmSub s k let scale := evmShl s ay @@ -62,158 +61,120 @@ theorem call_fun_mulExpRay_direct have hscaleMaxClz := call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 2023) (shared := shared) (hlookup := hlookup) - have hwrapS0 := + have hwrapS := call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) - have hscaleMax1 := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2020) - (shared := shared) (hlookup := hlookup) have hoctave := - call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2055) + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2058) (shared := shared) (hlookup := hlookup) have hconvertS := - call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2051) + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2054) (shared := shared) (hlookup := hlookup) have hwrapShift := - call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2088) - (shared := shared) (hlookup := hlookup) - have hscaleMax2 := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 2004) + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2091) (shared := shared) (hlookup := hlookup) - have hcleanupScaleMax := - call_cleanup_t_uint256_direct (v := scaleQ67) (fuel := fuel + extra) (extra := 2141) + have hconvert127 := + call_convert_127_to_uint256_direct (fuel := fuel + extra) (extra := 2044) (shared := shared) (hlookup := hlookup) - have hcleanupAyGuard := - call_cleanup_t_uint256_direct (v := ay) (fuel := fuel + extra) (extra := 2139) + have hcleanupSGuard := + call_cleanup_t_uint256_direct (v := s) (fuel := fuel + extra) (extra := 2142) (shared := shared) (hlookup := hlookup) have hHi := - call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 1998) + call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2001) (shared := shared) (hlookup := hlookup) - have hcleanupHi := - call_cleanup_t_int256_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 2133) + have hconvertOne := + call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2037) (shared := shared) (hlookup := hlookup) + have hsubHi := + call_wrapping_sub_t_int256_direct (x := mulExpRayHi) (y := 1) + (fuel := fuel + extra) (extra := 2079) (shared := shared) (hlookup := hlookup) + have hcleanupHiMinusOne := + call_cleanup_t_int256_direct (v := evmSub mulExpRayHi 1) + (fuel := fuel + extra) (extra := 2136) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2131) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2134) (shared := shared) (hlookup := hlookup) have hOrOut := - call_fun_or_direct (a := evmGt ay scaleQ67) (b := evmIszero (evmSlt x mulExpRayHi)) - (fuel := fuel + extra) (extra := 2076) (shared := shared) (hlookup := hlookup) - have hconvertZeroEq := - call_convert_0_to_int256_direct (fuel := fuel + extra) (extra := 2027) - (shared := shared) (hlookup := hlookup) - have hcleanupXEq := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2125) - (shared := shared) (hlookup := hlookup) - have hZM1 := - call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1986) - (shared := shared) (hlookup := hlookup) - have hcleanupZM := - call_cleanup_t_int256_direct (v := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 2123) - (shared := shared) (hlookup := hlookup) - have hcleanupXForLo := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2121) - (shared := shared) (hlookup := hlookup) - have hAndLo := - call_fun_and_direct (a := evmIszero (evmEq x 0)) (b := evmSgt x mulExpRayZeroMax) - (fuel := fuel + extra) (extra := 2064) (shared := shared) (hlookup := hlookup) + call_fun_or_direct (a := evmGt s 127) (b := evmSgt x (evmSub mulExpRayHi 1)) + (fuel := fuel + extra) (extra := 2077) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2017) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2030) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2115) - (shared := shared) (hlookup := hlookup) - have hAndAccuracy := - call_fun_and_direct - (a := evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) - (b := evmSlt shift 2) (fuel := fuel + extra) (extra := 2058) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2128) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct - (a := evmOr (evmGt ay scaleQ67) (evmIszero (evmSlt x mulExpRayHi))) - (b := evmAnd (evmAnd (evmIszero (evmEq x 0)) (evmSgt x mulExpRayZeroMax)) - (evmSlt shift 2)) - (fuel := fuel + extra) (extra := 2057) (shared := shared) (hlookup := hlookup) + (a := evmOr (evmGt s 127) (evmSgt x (evmSub mulExpRayHi 1))) + (b := evmSlt shift 2) + (fuel := fuel + extra) (extra := 2071) (shared := shared) (hlookup := hlookup) have hscaleShift := call_shift_left_t_uint256_t_uint256_direct (value := ay) (bits := s) - (fuel := fuel + extra) (extra := 1947) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 1961) (shared := shared) (hlookup := hlookup) have hconvertShiftOut := - call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2004) + call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2018) (shared := shared) (hlookup := hlookup) - have hZM2 := - call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1963) + have hZM := + call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1977) (shared := shared) (hlookup := hlookup) have hkernel := call_fun__expRayKernel_direct (x := x) (k := k) (scale := scale) (shift := shift) - (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1422) + (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1436) (shared := shared) (hlookup := hlookup) have hconvertOut := call_convert_uint256_to_int256_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 1997) (shared := shared) (hlookup := hlookup) + (extra := 2011) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS0 - simp only [Nat.reduceAdd, FormalYul.word] at hscaleMax1 hscaleMax2 + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave - simp only [Nat.reduceAdd, FormalYul.word, s, s0, ay, absTree, signTree, scaleMaxClz, - scaleQ67] at hconvertS - simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, s0, ay, absTree, signTree, scaleMaxClz, - scaleQ67] at hwrapShift - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, - scaleQ67] at hcleanupScaleMax hcleanupAyGuard + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] at hconvertS + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, scaleMaxClz] + at hwrapShift + simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] + at hcleanupSGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, mulExpRayHi] at hHi - simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hcleanupHi + simp only [Nat.reduceAdd, FormalYul.word] at hconvertOne + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hsubHi hcleanupHiMinusOne simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, ay, absTree, signTree, scaleQ67, - mulExpRayHi] at hOrOut - simp only [Nat.reduceAdd, FormalYul.word] at hconvertZeroEq hcleanupXEq - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, - mulExpRayZeroMax] at hZM1 hZM2 - simp only [Nat.reduceAdd, FormalYul.word, mulExpRayZeroMax] at hcleanupZM - simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForLo - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, - mulExpRayZeroMax] at hAndLo + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, s, ay, absTree, signTree, + scaleMaxClz, mulExpRayHi] at hOrOut simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo - simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, s0, ay, absTree, signTree, - scaleMaxClz, scaleQ67] at hcleanupShift - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_and, k, kTree, shift, s, s0, ay, absTree, - signTree, scaleMaxClz, scaleQ67, mulExpRayZeroMax] at hAndAccuracy - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, s0, ay, absTree, - signTree, scaleMaxClz, scaleQ67, mulExpRayHi, mulExpRayZeroMax] at hOrGuard - simp only [Nat.reduceAdd, FormalYul.word, s, s0, ay, absTree, signTree, scaleMaxClz, - scaleQ67] at hscaleShift - simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, s0, ay, absTree, signTree, - scaleMaxClz, scaleQ67] at hconvertShiftOut - simp only [Nat.reduceAdd, FormalYul.word, k, kTree, scale, shift, s, s0, ay, absTree, - signTree, scaleMaxClz, scaleQ67, mulExpRayZeroMax, evmShl_one_c0] at hkernel + simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, + scaleMaxClz] at hcleanupShift + simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, ay, absTree, + signTree, scaleMaxClz, mulExpRayHi] at hOrGuard + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] at hscaleShift + simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, + scaleMaxClz] at hconvertShiftOut + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, + mulExpRayZeroMax] at hZM + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, scale, shift, s, ay, absTree, + signTree, scaleMaxClz, mulExpRayZeroMax, evmShl_one_c0] at hkernel simp only [Nat.reduceAdd, FormalYul.word, mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, tTree, vTree, evTree, odTree, todTree, kTree, scaleShiftTree, absTree, signTree, tArgShift, k27Q235, ln2Q235, squareShift, ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, - todShift, marginWord, scaleQ67, scaleMaxClz, mulExpRayZeroMax] at hconvertOut + todShift, marginWord, scaleMaxClz, mulExpRayZeroMax] at hconvertOut have hguardUnfold : evmOr (evmOr - (evmGt (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)) - 147573952589676412928000000000000000000) - (evmIszero (evmSlt x 86989971160273136331862631244))) - (evmAnd - (evmAnd (evmIszero (evmEq x 0)) - (evmSgt x 115792089237316195423570985008687907853269984665552187773936190980962432544451)) + (evmGt + (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) + 127) + (evmSgt x (evmSub 86989971160273136331862631244 1))) (evmSlt (evmSub - (evmSub (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmGt - (evmShl (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) - 147573952589676412928000000000000000000)) + (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) - 2)) = 0 := by - simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, scaleQ67, - scaleMaxClz, mulExpRayHi, mulExpRayZeroMax] using hguard + 2) = 0 := by + simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, + scaleMaxClz, mulExpRayHi] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -223,34 +184,29 @@ theorem call_fun_mulExpRay_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - hguard, hguardUnfold, - hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS0, - hscaleMax1, hoctave, hconvertS, hwrapShift, hscaleMax2, hcleanupScaleMax, hcleanupAyGuard, - hHi, hcleanupHi, hcleanupXForHi, hOrOut, hconvertZeroEq, hcleanupXEq, hZM1, hcleanupZM, - hcleanupXForLo, hAndLo, hconvertTwo, hcleanupShift, hAndAccuracy, hOrGuard, hscaleShift, - hconvertShiftOut, hZM2, hkernel, hconvertOut, - FormalYul.Preservation.uint256_ofNat_eq_eq_word_evmEq, + hguardUnfold, + hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS, + hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, + hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hOrOut, + hconvertTwo, hcleanupShift, hOrGuard, hscaleShift, + hconvertShiftOut, hZM, hkernel, hconvertOut, FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, FormalYul.Preservation.uint256_ofNat_lt_eq_word_evmLt, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, FormalYul.Preservation.uint256_ofNat_mul_eq_word_evmMul, FormalYul.Preservation.uint256_ofNat_or_eq_word_evmOr, - FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl, Common.Word.uint256_ofNat_xor_eq_word_evmXor, Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, uint256_ofNat_sgt_eq_word_evmSgt, - uint256_ofNat_iszero_eq_word_evmIszero, - evmShl_one_c0, mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, tTree, vTree, evTree, odTree, todTree, tArgShift, k27Q235, ln2Q235, squareShift, ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, todShift, marginWord, - mulExpGuardTree, scaleShiftTree, absTree, signTree, kTree, - scaleQ67, scaleMaxClz, mulExpRayHi, mulExpRayZeroMax, - sign, ay, s0, s, k, scale, shift] + scaleShiftTree, absTree, signTree, kTree, + scaleMaxClz, mulExpRayZeroMax] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay(y, x)` forwards to the value path. -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/Value.lean b/formal/exp/ExpProof/ExpProof/Seam/Value.lean index 266cf9875..e6097d01a 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Value.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Value.lean @@ -95,7 +95,7 @@ theorem call_fun_expRayToWad_zero_direct call_fun__octave_direct (x := 0) (fuel := fuel + extra) (extra := 767) (shared := shared) (hlookup := hlookup) have hscale := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 721) + call_constant__WAD_SCALE_direct (fuel := fuel + extra) (extra := 721) (shared := shared) (hlookup := hlookup) have hconv67 := call_convert_67_to_int256_direct (fuel := fuel + extra) (extra := 759) @@ -498,7 +498,7 @@ theorem call_fun__expRayKernel_direct FormalYul.Preservation.wordNat_mul, FormalYul.Preservation.wordNat_iszero, FormalYul.Preservation.wordNat_ofNat, wordNat_sar, wordNat_div, wordNat_slt] simp only [FormalYul.Preservation.evmAdd_u256_left, - FormalYul.Preservation.evmSub_u256_left, FormalYul.Preservation.evmSub_u256_right, + FormalYul.Preservation.evmSub_u256_right, FormalYul.Preservation.evmMul_u256_left, FormalYul.Preservation.evmMul_u256_right, FormalYul.Preservation.evmShl_u256_left, FormalYul.Preservation.evmShl_u256_right, FormalYul.Preservation.evmShr_u256_left, @@ -560,7 +560,7 @@ theorem call_fun_expRayToWad_direct call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 767) (shared := shared) (hlookup := hlookup) have hscale := - call_constant__SCALE_MAX_direct (fuel := fuel + extra) (extra := 721) + call_constant__WAD_SCALE_direct (fuel := fuel + extra) (extra := 721) (shared := shared) (hlookup := hlookup) have hconv67 := call_convert_67_to_int256_direct (fuel := fuel + extra) (extra := 759) diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index b4c36c3af..671d1e201 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -105,21 +105,22 @@ Every documented `mulExpRay` property holds for the compiled runtime, axiom-clea | Signed bracket `0 ≤ m ≤ A ∧ A < m + 2` on the domain | `mulExpRay_run_bracket` | | `m` is `⌊A⌋` or `⌊A⌋ − 1`; `A < 1` pins `m = 0` | `mulExpRay_run_floor_membership`, `mulExpRay_run_pins_zero` | | `mulExpRay(0, x) = 0` for accepted `x` (and bracket) | `run_mul_exp_ray_evm_zero_of_guard` | -| `mulExpRay(y, 0) = y` for supported `y` (and bracket) | `run_mul_exp_ray_evm_scale_point` | +| `mulExpRay(y, 0) = y` when the guard accepts (and bracket) | `run_mul_exp_ray_evm_scale_point` | | Monotone in `x`, direction following `sign(y)` | `run_mul_exp_ray_evm_mono_x` | | Nondecreasing in `y` at a fixed `x` | `run_mul_exp_ray_evm_mono_y` | | Joint sign-aware monotonicity (three cases) | `run_mul_exp_ray_evm_mono_joint` | -| Reverts in exactly three cases, with the exemptions | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_octave`, `run_mul_exp_ray_evm_revert_int_min` | -| The accepted exponents need not form an interval | `MulExpRayValueDomain` (the exact accept set; its third disjunct is headroom-dependent) | +| Reverts exactly when magnitude, upper-fence, or closing-shift guard fails | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_magnitude_guard`, `run_mul_exp_ray_evm_revert_int_min` | +| The 127-bit magnitude guard is exact | `scaleShiftTree_le_127_iff` | +| The maximal magnitude is live at closing shift two | `scaleMax_octave_neg_two_run_bracket` | Supporting rows: the exact value/panic partition of canonical calldata (`mulExpRay_value_or_panic_of_canonical`), the guard word ↔ domain bridge -(`valueDomain_iff_guard_eq_zero`), the value path to the compiled tree +(`valueDomain_iff_guard_eq_zero`/`panicDomain_iff_guard_eq_one`), the value path to the compiled tree (`run_mul_exp_ray_evm_eq_tree`), and the zero clamp (`run_mul_exp_ray_evm_clamped`). The proof chain: the scale-symbolic per-point certificates (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) instantiate at the dynamic scale -`abs(y)·2ˢ ∈ [2¹²⁵, 10¹⁸·2⁶⁷]`; the accumulator fold (`Mul.Accum`) closes the live-region +`abs(y)·2ˢ ∈ [2¹²⁵, 2¹²⁷ − 1]`; the accumulator fold (`Mul.Accum`) closes the live-region bracket; the unit-step induction with the scaled seam doubling (`Mul.XMono`) closes the sign-directed exponent monotonicity; the headroom-step induction (`Mul.YMono`) closes the multiplier monotonicity; and the corner composition with the antitone headroom (`Mul.Joint`) @@ -132,6 +133,57 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := mulExpRay_value_or_panic_of_canonical hcanon +/-- The magnitude cap is the largest signed 127-bit value. -/ +example : scaleMax = 2 ^ 127 - 1 := scaleMax_eq + +/-- The headroom comparison accepts exactly the magnitudes at or below the cap. -/ +example {y : Nat} : + scaleShiftTree (absTree y) ≤ 127 ↔ absTree y ≤ scaleMax := + scaleShiftTree_le_127_iff (absTree_lt y) + +/-- The panic predicate is exactly the compiled guard word being one. -/ +example {y x : Nat} (hcanon : MulExpRayCanonical y x) : + MulExpRayPanicDomain y x ↔ mulExpGuardTree y x = 1 := + panicDomain_iff_guard_eq_one hcanon + +/-- The never-over certificate holds at the maximal dynamic scale. -/ +example {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : + (FormalYul.Preservation.int256 (r0ScaledTree scaleMax x) : Real) ≤ + (scaleMax : Real) * Real.exp (reducedArg x) + + 2 * 4668745981919039833 / 10000000000000000000 := + r0Scaled_real_over_within (by norm_num [scaleMax]) (le_refl _) hx hW + +/-- The deficit certificate holds at the maximal dynamic scale. -/ +example {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : + (scaleMax : Real) * Real.exp (reducedArg x) ≤ + (FormalYul.Preservation.int256 (r0ScaledTree scaleMax x) : Real) + 2993 / 1000 := + r0Scaled_real_under_within (by norm_num [scaleMax]) (le_refl _) hx hW + +/-- At the maximal magnitude, octave `-2` attains the minimum accepted closing shift and the +compiled runtime satisfies its signed bracket. -/ +theorem scaleMax_octave_neg_two_run_bracket {x : Nat} (hx : x < 2 ^ 256) + (hxhi : FormalYul.Preservation.int256 x < + FormalYul.Preservation.int256 mulExpRayHi) + (hk : FormalYul.Preservation.int256 (kTree x) = -2) : + scaleShiftTree (absTree scaleMax) = 0 ∧ + FormalYul.Preservation.int256 (mulShiftTree scaleMax x) = 2 ∧ + MulExpRayRunBracket scaleMax x := by + obtain ⟨hs, hshift, hdom⟩ := scaleMax_octave_neg_two_valueDomain hx hxhi hk + exact ⟨hs, hshift, mulExpRay_run_bracket hdom⟩ + +/-- A concrete exponent word in octave `-2` witnesses the live maximal-magnitude boundary. -/ +theorem scaleMax_concrete_neg_three_halves_run_bracket : + scaleShiftTree (absTree scaleMax) = 0 ∧ + FormalYul.Preservation.int256 + (mulShiftTree scaleMax + (2 ^ 256 - 1500000000000000000000000000)) = 2 ∧ + MulExpRayRunBracket scaleMax + (2 ^ 256 - 1500000000000000000000000000) := by + apply scaleMax_octave_neg_two_run_bracket + · norm_num + · norm_num [FormalYul.Preservation.int256, mulExpRayHi] + · decide +kernel + /-- **The signed bracket on the whole value domain.** Every accepted input returns a result whose magnitude `m` satisfies `0 ≤ m ≤ A ∧ A < m + 2` for `A = abs(y)·exp(x/10²⁷)`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : MulExpRayRunBracket y x := @@ -162,17 +214,14 @@ example {y1 y2 x1 x2 : Nat} MulExpRayRunJointMonotone y1 y2 x1 x2 := run_mul_exp_ray_evm_mono_joint h1 h2 hcond -/-- **The panic domain in the natspec's octave vocabulary**: too-large magnitude, exponent at or -beyond the unconditional fence, or a live exponent whose octave count exceeds the headroom shift -less two. -/ +/-- **The panic domain in magnitude/guard vocabulary**: too-large magnitude, exponent at or beyond +the unconditional fence, or a closing shift below two. -/ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayPanicDomain y x ↔ - scaleQ67 < absTree y ∨ + scaleMax < absTree y ∨ FormalYul.Preservation.int256 mulExpRayHi ≤ FormalYul.Preservation.int256 x ∨ - (FormalYul.Preservation.int256 x ≠ 0 ∧ - FormalYul.Preservation.int256 mulExpRayZeroMax < FormalYul.Preservation.int256 x ∧ - (scaleShiftTree (absTree y) : Int) - 2 < FormalYul.Preservation.int256 (kTree x)) := - panicDomain_iff_octave hcanon + FormalYul.Preservation.int256 (mulShiftTree y x) < 2 := + panicDomain_iff_magnitude_guard hcanon /-- **`type(int256).min` always reverts**: its magnitude word `2^255` exceeds the maximal scale. -/ @@ -231,29 +280,33 @@ example {y x : Nat} (h : MulExpRayPanicDomain y x) : run_mul_exp_ray_evm y x = .error "revert" := run_mul_exp_ray_evm_revert h -/-- The scale point returns the multiplier exactly. -/ -example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : +/-- The accepted scale point returns the multiplier exactly. -/ +example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := - run_mul_exp_ray_evm_scale_point hy habs + run_mul_exp_ray_evm_scale_point hy habs hshift /-- The scale-point result satisfies the public bracket. -/ -example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleQ67) : +example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := - mulExpRay_run_bracket_scale_point hy habs + mulExpRay_run_bracket_scale_point hy habs hshift -/-- At or below the zero cutoff, every supported magnitude returns zero. -/ +/-- At or below the zero cutoff, every accepted magnitude returns zero. -/ example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) + (habs : absTree y ≤ scaleMax) + (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : run_mul_exp_ray_evm y x = .ok 0 := - run_mul_exp_ray_evm_clamped hy hx habs hclamp + run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp /-- The clamped result satisfies the public bracket. -/ example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleQ67) + (habs : absTree y ≤ scaleMax) + (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : MulExpRayRunBracket y x := - mulExpRay_run_bracket_clamped hy hx habs hclamp + mulExpRay_run_bracket_clamped hy hx habs hshift hclamp /-- The accumulator floor and target bounds imply the public magnitude bracket. -/ example {y x m : Int} {A : Real} @@ -308,6 +361,34 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_bracket +/-- info: 'ExpYul.scaleMax_eq' depends on axioms: [propext] -/ +#guard_msgs in +#print axioms scaleMax_eq + +/-- info: 'ExpYul.scaleShiftTree_le_127_iff' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms scaleShiftTree_le_127_iff + +/-- info: 'ExpYul.panicDomain_iff_guard_eq_one' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms panicDomain_iff_guard_eq_one + +/-- info: 'ExpYul.r0Scaled_real_over_within' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms r0Scaled_real_over_within + +/-- info: 'ExpYul.r0Scaled_real_under_within' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms r0Scaled_real_under_within + +/-- info: 'ExpYul.scaleMax_octave_neg_two_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms scaleMax_octave_neg_two_run_bracket + +/-- info: 'ExpYul.scaleMax_concrete_neg_three_halves_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms scaleMax_concrete_neg_three_halves_run_bracket + /-- info: 'ExpYul.run_mul_exp_ray_evm_mono_x' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms run_mul_exp_ray_evm_mono_x @@ -328,9 +409,9 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms run_mul_exp_ray_evm_mono_joint -/-- info: 'ExpYul.panicDomain_iff_octave' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.panicDomain_iff_magnitude_guard' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms panicDomain_iff_octave +#print axioms panicDomain_iff_magnitude_guard /-- info: 'ExpYul.run_mul_exp_ray_evm_revert_int_min' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index a9794b4b0..bcdc813ea 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -72,9 +72,9 @@ def functionPrefixes : ModelKind → List String "fun_wrap_expRayToWad_", "fun_wrap_mulExpRay_", "fun_expRayToWad_", "fun_mulExpRay_", "fun__octave_", "fun__expRayKernel_", - "constant__EXP_RAY_TO_WAD_HI_", "constant__WAD_ZERO_MAX_", + "constant__EXP_RAY_TO_WAD_HI_", "constant__WAD_SCALE_", "constant__WAD_ZERO_MAX_", "constant_ARITHMETIC_OVERFLOW_", "fun_panic_", - "fun_or_", "fun_and_", "fun_clz_"] + "fun_or_", "fun_clz_"] def requiredCalls : ModelKind → List String | .sqrt => ["clz"] @@ -591,25 +591,12 @@ def uniqueNameWithPrefix | [] => .error s!"deployed Yul is missing a function with prefix {pfx}" | names => .error s!"deployed Yul prefix {pfx} is ambiguous: {commaSep names}" -def uniqueNameWithPrefixExcluding - (functions : List FunctionSource) (pfx excludedPfx : String) : Except String String := - match (namesWithPrefix functions pfx).filter fun name => !(name.startsWith excludedPfx) with - | [name] => .ok name - | [] => .error s!"deployed Yul is missing a function with prefix {pfx}" - | names => .error s!"deployed Yul prefix {pfx} is ambiguous: {commaSep names}" - def aliasByPrefix (functions : List FunctionSource) (stable pfx : String) : Except String GeneratedAlias := do let original ← uniqueNameWithPrefix functions pfx .ok { stable, original } -def aliasByPrefixExcluding - (functions : List FunctionSource) (stable pfx excludedPfx : String) : - Except String GeneratedAlias := do - let original ← uniqueNameWithPrefixExcluding functions pfx excludedPfx - .ok { stable, original } - def callWithPrefixFrom (functions : List FunctionSource) (caller pfx : String) : Except String String := do let callerFn ← findFunction functions caller @@ -767,15 +754,14 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : aliasByPrefix functions "fun__octave" "fun__octave_", aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", aliasByPrefix functions "constant__EXP_RAY_TO_WAD_HI" "constant__EXP_RAY_TO_WAD_HI_", - aliasByPrefixExcluding functions "constant__SCALE_MAX" "constant__SCALE_MAX_" "constant__SCALE_MAX_CLZ_", aliasByPrefix functions "constant__SCALE_MAX_CLZ" "constant__SCALE_MAX_CLZ_", + aliasByPrefix functions "constant__WAD_SCALE" "constant__WAD_SCALE_", aliasByPrefix functions "constant__WAD_ZERO_MAX" "constant__WAD_ZERO_MAX_", aliasByPrefix functions "constant__MUL_EXP_RAY_HI" "constant__MUL_EXP_RAY_HI_", aliasByPrefix functions "constant__MUL_EXP_RAY_ZERO_MAX" "constant__MUL_EXP_RAY_ZERO_MAX_", aliasByPrefix functions "constant_ARITHMETIC_OVERFLOW" "constant_ARITHMETIC_OVERFLOW_", aliasByPrefix functions "fun_panic" "fun_panic_", aliasByPrefix functions "fun_or" "fun_or_", - aliasByPrefix functions "fun_and" "fun_and_", aliasByPrefix functions "fun_clz" "fun_clz_" ] @@ -828,8 +814,12 @@ def validateShape (kind : ModelKind) (contract : ParsedContract) : Except String def validateInput (kind : ModelKind) (contract : ParsedContract) : Except String Unit := validateShape kind contract +example : (ModelKind.functionPrefixes .exp).contains "fun_or_" := by decide + +example : ¬(ModelKind.functionPrefixes .exp).contains "fun_and_" := by decide + def usage : String := - "usage: yul_importer --kind --output < solc-ir" + "usage: yul_importer --kind --output < solc-ir" unsafe def run (args : List String) : IO UInt32 := do let opts ← match parseArgs args {} with diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 2cfb94f70..e0589cad6 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -8,14 +8,9 @@ import {Clz} from "./Clz.sol"; library Exp { using FastLogic for bool; - // ⌊2¹²⁶⋅10¹⁹ / 5737291786393199862⌋ ≈ 1.0048⋅10¹⁸⋅2⁶⁷: the largest scale `_expRayKernel` - // accepts. The kernel's over-side error envelope Δ (see the budget below) casts an image of - // scale⋅Δ/2¹²⁶ on the output grid; this is the greatest scale at which the margin still - // dominates that image. It also keeps the kernel's dividend inside 256 bits. - uint256 private constant _SCALE_MAX = 0x6f8d071203399a4f3617495dba31eeb1; - // clz(_SCALE_MAX); must track _SCALE_MAX (paired by `testScaleMaxClzPairing`). + // With s = clz(abs(y)) - 129, the s ≤ 127 guard admits exactly magnitudes through 2¹²⁷ − 1. uint256 private constant _SCALE_MAX_CLZ = 129; - // 10¹⁸ ⋅ 2⁶⁷ ≤ _SCALE_MAX: `expRayToWad`'s scale — the wad output basis carrying 67 bits of + // 10¹⁸ ⋅ 2⁶⁷ < 2¹²⁷: `expRayToWad`'s scale — the wad output basis carrying 67 bits of // closing headroom. uint256 private constant _WAD_SCALE = 0x6f05b59d3b2000000000000000000000; // The least x whose octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, i.e. @@ -37,7 +32,7 @@ library Exp { int256 private constant _MUL_EXP_RAY_HI = 86989971160273136331862631244; // The least x whose octave count reaches -127, i.e. ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ // -127.5⋅ln(2)⋅10²⁷ ≈ -88.38⋅10²⁷. At or below it the kernel clamps `mulExpRay` to zero, - // which is within the bracket at every supported scale (_SCALE_MAX⋅exp(x/10²⁷) < 0.63); the + // which is within the bracket at every supported scale ((2¹²⁷ - 1)⋅exp(x/10²⁷) < 1); the // clamp consults only x, so it also zeroes every accepted x inside `_octave`'s negative // wraparound region (x ≲ -2¹⁵²). Above it, k ≥ -127 keeps the closing shift below 256 and // the reduced argument on the certified domain. @@ -69,8 +64,8 @@ library Exp { /// @dev Let A = abs(y) ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, except that when /// A < 1 the lower bound pins m = 0. `mulExpRay(0, x) == 0` for every accepted x, and - /// `mulExpRay(y, 0) == y` exactly whenever 4⋅abs(y) ≤ - /// 148276564793151315913207305475055546033 (larger magnitudes leave fewer than two bits + /// `mulExpRay(y, 0) == y` exactly whenever 4⋅abs(y) ≤ 2¹²⁷ - 1 = + /// 170141183460469231731687303715884105727 (larger magnitudes leave fewer than two bits /// of closing shift, so x = 0 reverts there). Among accepted inputs, the result is /// monotone in x: nondecreasing if y ≥ 0 and nonincreasing if y < 0. For a fixed x, /// among accepted inputs, the result is nondecreasing in y. Jointly, for accepted pairs @@ -78,11 +73,11 @@ library Exp { /// and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. /// /// Reverts with `Panic(17)` in exactly three cases: - /// abs(y) > 148276564793151315913207305475055546033 ≈ 1.48⋅10³⁸ (including + /// abs(y) > 2¹²⁷ - 1 = 170141183460469231731687303715884105727 ≈ 1.70⋅10³⁸ (including /// y = type(int256).min); x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ (regardless of /// y); or the octave word — `_octave`'s output, which is round(x / (10²⁷⋅ln(2))) wherever /// its product does not wrap (|x| ≲ 2¹⁵²) — exceeding s - 2, with 2ˢ the scale headroom - /// above abs(y) (the largest power of two with abs(y)⋅2ˢ within the magnitude bound; + /// above abs(y) (the largest power of two with abs(y)⋅2ˢ < 2¹²⁷; /// s = 127 at y = 0). Within the wrap-free range the accepted exponents form one /// interval that narrows as abs(y) grows, and every accepted /// x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap @@ -99,54 +94,36 @@ library Exp { } unchecked { - // The scale headroom: the largest s with ay << s ≤ _SCALE_MAX (127 at ay = 0). When - // ay > _SCALE_MAX this underflows — clz comes up short of _SCALE_MAX_CLZ, or the - // decrement below takes s = 0 to 2²⁵⁶ - 1 — leaving garbage whose int256 value is in - // [-129, -1]. Every such ay trips the first guard disjunct below (FastLogic evaluates - // all disjuncts eagerly), so the garbage s and shift are compared but never otherwise - // consumed. + // The scale headroom aligns ay's top bit with bit 126 (127 at ay = 0), keeping every + // supported pre-scale below 2¹²⁷ without a value comparison. For a 128-bit or larger + // ay, clz comes up short of _SCALE_MAX_CLZ and the subtraction + // underflows to a word whose int256 value is in [-129, -1]. The magnitude guard below + // rejects every such ay after FastLogic eagerly evaluates the garbage shift comparison. uint256 s = Clz.clz(ay) - _SCALE_MAX_CLZ; - uint256 scaleMax = _SCALE_MAX; - // Aligning ay's top bit with _SCALE_MAX's top bit can still overshoot _SCALE_MAX - // within the same bit length; correct without branching: - // s -= (ay << s) > _SCALE_MAX ? 1 : 0 - assembly ("memory-safe") { - s := sub(s, gt(shl(s, ay), scaleMax)) - } int256 k = _octave(x); int256 shift = int256(s) - k; // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: - // - abs(y) above the maximal scale; + // - abs(y) requiring at least 128 bits; // - x at or above the octave (k = 126) that exhausts the deficit envelope at even // the maximal headroom, phrased as one signed comparison against the constant // less one; its irreducible role is fencing accepted x away from `_octave`'s // positive wraparound (see `_MUL_EXP_RAY_HI`); // - fewer than two bits of closing shift: the deficit envelope - // (2972/1000 + margin)⋅2ᵏ⁻ˢ reaches one output unit at k > s - 2 (see the + // (2993/1000 + margin)⋅2ᵏ⁻ˢ reaches one output unit at k > s - 2 (see the // kernel). This also rejects x = 0 when abs(y) leaves s ≤ 1, although the pinned // result would be exact. When `_octave`'s product wraps (x ≲ -2¹⁵²) its output // stands in for k, so those exponents revert or pass as the wrapped word falls; // the kernel's clamp zeroes every accepted one. - if ((ay > _SCALE_MAX).or(x > _MUL_EXP_RAY_HI - 1).or(shift < 2)) { + if ((s > 127).or(x > _MUL_EXP_RAY_HI - 1).or(shift < 2)) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } // Monotonicity in y at a fixed accepted x: within one headroom class (fixed s) the - // magnitude is a composition of nondecreasing maps of ay. A unit step in ay can - // lower s by one in two ways, both order-preserving: - // - at a bit-length boundary (ay reaching 2ᴸ), the scale ay << s does not decrease - // while the closing shift shrinks by one, so both effects raise the result; - // - at a headroom-correction boundary (ay << s crossing _SCALE_MAX), the scale - // halves: scale′ = (scale + 2ˢ)/2. With P = scale⋅n/d, c = 2ˢ⋅n/d > 1 (s ≥ 1 and - // n/d > 1/√2 - ε), b = ⌊P⌋ mod 2, and f = frac(P), the two pre-shift numerators - // compared on the common 2ˢ⁻ᵏ grid satisfy - // (2⋅⌊(P + c)/2⌋ - 2) - (⌊P⌋ - 1) = 2⋅⌊(b + f + c)/2⌋ - b - 1, - // which is ≥ 0 when ⌊P⌋ is odd and ≥ -1 when ⌊P⌋ is even; in the -1 case - // ⌊P⌋ - 1 is odd, so losing one unit cannot cross a multiple of the closing - // modulus 2ˢ⁻ᵏ (even, since the guard keeps k ≤ s - 2), and the floored result - // is unchanged. The x = 0 pin (exact) and the zero clamp (constant) preserve - // order trivially, and the sign reapplication mirrors the argument to y < 0. + // magnitude is a composition of nondecreasing maps of ay. At a bit-length boundary + // (ay reaching 2ᴸ), the scale ay << s does not decrease while the closing shift shrinks + // by one, so both effects raise the result. The x = 0 pin and zero clamp preserve order, + // and sign reapplication mirrors the argument to y < 0. uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), _MUL_EXP_RAY_ZERO_MAX); // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale // is zero) in one branchless step: @@ -171,8 +148,8 @@ library Exp { /// @dev The rational polynomial approximation kernel, shared by `expRayToWad` /// (scale = 10¹⁸⋅2⁶⁷, shift = 67 - k) and `mulExpRay` (scale = abs(y)⋅2ˢ, shift = s - k). /// The caller must maintain: - /// - `k == _octave(x)` and `scale ≤ _SCALE_MAX`: the margin and deficit budgets below - /// are certified at exactly that cap, and smaller scales only shrink them; + /// - `k == _octave(x)` and `scale < 2¹²⁷`: the margin and deficit budgets below + /// hold throughout this range, and smaller scales only shrink them; /// - `scale == base << s` for the caller's magnitude base, with `shift == s - k`; /// - for every accepted x with `zeroCutoff` < x and x ≠ 0: `shift ≥ 2` (the deficit /// envelope reaches one output unit below that), `_octave`'s product must not wrap @@ -218,18 +195,17 @@ library Exp { // product stays inside 256 bits // dividend: Q156 the widest basis that fits in 256 bits before the single truncating // `DIV` by Q89 divisor. < 2¹²⁹ - // r: the pre-scale is at most _SCALE_MAX < 2¹²⁷ to avoid overflowing the dividend. + // r: the pre-scale is below 2¹²⁷ to avoid overflowing the dividend. // output: the closing `shr(shift, …)` is the output-rounding floor, with the 2ᵏ octave // scaling folded into the caller's scale/shift pair. // // Error budget. Let ê = N/D be the exact value of the integer rational (N = Ev + t⋅Od, D = // Ev - t⋅Od; the closing `DIV` floor is counted on the output grid below) and write its - // excess over exp(t) as Δ = (ê - exp(t))⋅2¹²⁶ (in Q126 units, one unit = 2⁻¹²⁶). Δ is the - // tightest bound the proof technique can bear, in spite of the fact that the worst-case - // error contributions do not co-occur. The budget bounds Δ ≤ 0.5737291786393199862, the sum + // excess over exp(t) as Δ = (ê - exp(t))⋅2¹²⁶ (in Q126 units, one unit = 2⁻¹²⁶). The + // budget bounds Δ ≤ 0.4668745981919039833, the sum // of four one-sided contributions: // integer Horner truncation: the shared Ev cancels to first order in the quotient, so - // its truncation barely perturbs ê; this jitter stays ≤ 0.2170557036555806152. + // its truncation barely perturbs ê; this jitter stays ≤ 0.1102011232081646123. // argument granularity: v carries t² on the Q123 grid, and its floor only lowers the // polynomials' shared argument, which lifts ê on the t > 0 half by // ≤ 0.3290521163436398582: one v-grain moves the quotient by @@ -245,23 +221,17 @@ library Exp { // grid term below 2⁻²²⁸), lifting ê by ≤ 0.0055242717280199026 (≈ √2/256). // // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid unit - // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). The scale cap is exactly - // ⌊2¹²⁶/Δ⌋ in Q126 units (its defining property), so Δ's image on the grid, scale⋅Δ/2¹²⁶, - // never exceeds one grid unit. The margin is the least integer that dominates the image: + // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale < 2¹²⁷ and + // Δ < 1/2, its image scale⋅Δ/2¹²⁶ is below one grid unit. The margin dominates the image: // 0x01, worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so // the pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is - // certified directly on the output grid, piecewise over the 32 domain pieces (per-piece - // denominator floors confine the truncation amplification): q ≥ scale⋅exp(t) - 2972/1000. - // The `DIV` floor costs one unit at any scale; the remaining, scale-proportional deficits - // are certified at 10¹⁸⋅2⁶⁷ — integer-rational ≤ 1378/1000, the `Mp` factor ≤ 2/25 (via - // ê ≤ 1.45), the under-direction reduced-argument gap ≤ 307/1000 on the t > 0 half (via - // exp(t) ≤ √2; ≤ 218/1000 on the other, where exp(t) ≤ 1 + ε), and the under-direction - // argument granularity ≤ 143/500 (the one-grain envelope with the negative-half - // denominator floor; free on the t > 0 half) — and grow by at most - // scale/(10¹⁸⋅2⁶⁷) ≤ 1005/1000 at the cap, keeping each half's proportional total within - // 1972/1000. + // certified directly on the output grid, piecewise over the 32 domain pieces: q ≥ + // scale⋅exp(t) - 2993/1000. The `DIV` floor costs one unit at any scale. On the positive + // half, the integer-rational carry is certified over the same 32 pieces used for the + // denominator floors, while the scale-dependent 2⁻¹³² and reduced-argument terms remain + // exact. On the negative half, the one-grain direction and reduced-argument bound shrink. // - // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2972/1000 + margin)⋅2ᵏ⁻ˢ. The caller + // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2993/1000 + margin)⋅2ᵏ⁻ˢ. The caller // keeps k ≤ s - 2, where this is < 1, so the floor returns ⌊E⌋ or ⌊E⌋ - 1. For the wad // specialization s = 67, the deficit envelope exceeds 1ulp at k ≥ 66. On the central octave // k = 0, the margin is 2⁻⁶⁷ ≈ 6.8⋅10⁻²¹ ulp, far below the ≈10⁻⁹ ulp gap `lnWadToRay` @@ -270,8 +240,8 @@ library Exp { // // Monotonicity: one unit step in x multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves the // pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live - // scale exceeds _SCALE_MAX/2 > 10¹⁸⋅2⁶⁶). The error - // terms above confine the accumulator to a band of width scale⋅Δ/2¹²⁶ + 2972/1000 ≈ 4.0 grid + // scale is at least 2¹²⁶ > 10¹⁸⋅2⁶⁶). The error + // terms above confine the accumulator to a band of width scale⋅Δ/2¹²⁶ + 2993/1000 < 4.0 grid // units just below E's grid image at every octave (in grid units the band is k-independent; // an octave seam rescales E and the band together), so the per-step gain exceeds any // adverse swing within the band by more than 9 orders of magnitude, and the pre-floor @@ -318,7 +288,7 @@ library Exp { // both positive. let tod := sar(0x81, mul(t, od)) - // The scaled rational: the caller keeps scale ≤ _SCALE_MAX, so one `DIV` scales, widens, + // The scaled rational: the caller keeps scale < 2¹²⁷, so one `DIV` scales, widens, // and floors at once. The numerator stays below 2¹²⁹ and scale < 2¹²⁷, so the // dividend stays inside 256 bits; the denominator > 0. r := div(mul(scale, add(ev, tod)), sub(ev, tod)) diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index b3f3772ef..474fcc167 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -7,9 +7,8 @@ import {Clz} from "src/vendor/Clz.sol"; import {Test, stdError} from "@forge-std/Test.sol"; contract ExpTest is Test { - // Mirrors Exp._SCALE_MAX: floor(2**126 * 1e19 / 5737291786393199862), the over-side - // certification ceiling of the kernel. - uint256 private constant _SCALE_MAX = 0x6f8d071203399a4f3617495dba31eeb1; + // The largest magnitude admitted by `mulExpRay`'s s <= 127 guard. + uint256 private constant _SCALE_MAX = 0x7fffffffffffffffffffffffffffffff; // First input whose octave count exceeds the supported range; `expRayToWad` reverts here. int256 private constant _TOO_BIG = 0x92b2f16cc66c5a4ae96e80d4; // First input whose octave count reaches 125: the accuracy-guard boundary at the deepest @@ -224,14 +223,23 @@ contract ExpTest is Test { this.mulExpRayExternal(-(pinMax + 1), 0); } - /// The deepest live corner at the scale cap: abs(y) = _SCALE_MAX (s = 0) at the first x of - /// octave k = -2, where the closing shift is exactly 2. The two-unit bracket must hold here. + /// At abs(y) = _SCALE_MAX (s = 0), octave k = -2 is the highest accepted octave and the + /// closing shift is exactly 2. The two-unit bracket must hold at both ends of that octave. function testMulExpRayScaleCapLive() external pure { - int256 x = -1732867951399863273543080303; // _octaveStart(-2) - int256 floorA = 26211841114070945982531467099595678267; + int256 x = _octaveStart(-2); + int256 floorA = 30076996146000563943129221579116071223; int256 r = Exp.mulExpRay(int256(_SCALE_MAX), x); assertLe(r, floorA, "overestimates"); assertGe(r, floorA - 1, "below floor minus one"); + assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), x), -r, "negative mirror"); + + x = -1039720770839917964125848183; + assertEq(x, _octaveStart(-1) - 1, "upper endpoint"); + floorA = 60153992292001127886258443070517000410; + r = Exp.mulExpRay(int256(_SCALE_MAX), x); + assertLe(r, floorA, "overestimates at upper endpoint"); + assertGe(r, floorA - 1, "below floor minus one at upper endpoint"); + assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), x), -r, "negative mirror at upper endpoint"); } /// Below the octave-wrap boundary (x < -(2**255 + 2**191)/CINV ~ -5.7e45) the wrapped octave @@ -267,11 +275,11 @@ contract ExpTest is Test { this.mulExpRayExternal(0, type(int256).max); } - /// `_SCALE_MAX_CLZ` inside the library must track `_SCALE_MAX`, and `_SCALE_MAX` must be the - /// over-side certification ceiling floor(2**126 / Delta) with Delta = 5737291786393199862/1e19, - /// the kernel's Q126 error envelope. The wad scale must sit within the cap. + /// `_SCALE_MAX_CLZ` inside the library must track the maximal sub-2**127 scale. The positive + /// Q126 over envelope remains below one half, so its image at the cap is below one unit. function testScaleMaxClzPairing() external pure { - assertEq(_SCALE_MAX, ((uint256(1) << 126) * 1e19) / 5737291786393199862, "scale cap is floor(2^126 / Delta)"); + assertEq(_SCALE_MAX, (uint256(1) << 127) - 1, "maximal 127-bit scale"); + assertLt(uint256(2 * 4668745981919039833), uint256(1e19), "over envelope below one half"); assertEq(Clz.clz(_SCALE_MAX), 129, "_SCALE_MAX_CLZ"); assertLe(uint256(1e18) << 67, _SCALE_MAX, "wad scale within the cap"); } @@ -297,6 +305,8 @@ contract ExpTest is Test { vm.expectRevert(stdError.arithmeticError); this.mulExpRayExternal(int256(_SCALE_MAX + 1), _X_LO_ZERO); vm.expectRevert(stdError.arithmeticError); + this.mulExpRayExternal(-int256(_SCALE_MAX + 1), _X_LO_ZERO); + vm.expectRevert(stdError.arithmeticError); this.mulExpRayExternal(type(int256).min, type(int256).min); } @@ -341,10 +351,8 @@ contract ExpTest is Test { assertGe(Exp.mulExpRay(y, x + 1), Exp.mulExpRay(y, x), "adjacent monotonicity"); } - /// Monotonicity in y is tightest where a unit step in abs(y) crosses a headroom-correction - /// boundary (abs(y) << s crossing _SCALE_MAX): the scale halves against a one-bit-coarser - /// output grid, and only the parity of the scaled quotient keeps the floor from slipping - /// backward. Sweep every reachable boundary at its deepest accepted octaves. + /// Sweep every bit-length boundary, where a unit magnitude step lowers the headroom by one, + /// at its deepest accepted octaves. function testMulExpRayMonotoneYHeadroomBoundaries() external pure { for (uint256 s0 = 1; s0 <= 126; ++s0) { int256 q = int256(_SCALE_MAX >> s0); @@ -359,7 +367,7 @@ contract ExpTest is Test { } } - /// Fuzz the headroom-correction boundaries across the full accepted exponent range. + /// Fuzz the bit-length headroom boundaries across the full accepted exponent range. function testFuzzMulExpRayMonotoneYHeadroom(uint256 us, int256 x) external pure { uint256 s0 = bound(us, 1, 126); int256 q = int256(_SCALE_MAX >> s0); @@ -374,7 +382,6 @@ contract ExpTest is Test { function testFuzzMulExpRayMonotoneYAdjacent(uint256 uy, int256 x) external pure { int256 y = int256(bound(uy, 1, _SCALE_MAX - 1)); uint256 s = Clz.clz(uint256(y) + 1) - 129; - if (uint256(y + 1) << s > _SCALE_MAX) --s; x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s) - 1) - 1); assertLe(Exp.mulExpRay(y, x), Exp.mulExpRay(y + 1, x), "adjacent y-monotonicity"); } From fcd8c94941799f41c162fb408f151b4fd98af0ae Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Sun, 12 Jul 2026 19:20:24 +0200 Subject: [PATCH 081/107] Generate contiguous Ln certificate lanes Co-Authored-By: OpenAI Codex --- formal/ln/LnProof/GenBranchCertHard.lean | 50 +++++++++++++++++++ formal/ln/LnProof/GenErrLit.lean | 5 +- .../LnProof/Error/Core/BranchCert.lean | 14 +----- .../Error/Core/BranchCertHardDefs.lean | 19 +++++++ .../LnProof/LnProof/Error/Core/CutDefs.lean | 1 + .../LnProof/Error/Core/PhaseCover.lean | 2 - formal/ln/README.md | 23 +++++++-- 7 files changed, 94 insertions(+), 20 deletions(-) create mode 100644 formal/ln/LnProof/GenBranchCertHard.lean create mode 100644 formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean diff --git a/formal/ln/LnProof/GenBranchCertHard.lean b/formal/ln/LnProof/GenBranchCertHard.lean new file mode 100644 index 000000000..4ea6696fb --- /dev/null +++ b/formal/ln/LnProof/GenBranchCertHard.lean @@ -0,0 +1,50 @@ +import LnProof.Error.Core.BranchCertHardDefs +import Common.GenCover + +namespace GenBranchCertHard + +open Common.GenCover + +def outDir : String := "LnProof/Cert" +def chunkSize : Nat := 16 +def caseCount : Nat := 159 + +def chunkCount : Nat := (caseCount + chunkSize - 1) / chunkSize + +def chunkImport (chunk : Nat) : String := + if chunk = 0 ∨ chunk = chunkCount / 2 then + "LnProof.Error.Core.BranchCertHardDefs" + else + s!"LnProof.Cert.HardMantissaLtGapC{pad2 (chunk - 1)}" + +def chunkText (chunk start count : Nat) : String := + s!"import {chunkImport chunk}\n\nnamespace LnFloorCert\n\nset_option maxRecDepth 100000\n\ntheorem hardMantissaLtGapBranch_chunk{pad2 chunk} :\n (List.range {count}).all (fun i => hardMantissaLtGapBranchB (i + {start})) = true := by\n decide +kernel\n\nend LnFloorCert\n" + +def aggregateText : String := + let cases := (List.range chunkCount).map fun chunk => + let offset := chunk * chunkSize + let upper := min caseCount (offset + chunkSize) + if offset = 0 then s!"i < {upper}" else s!"({offset} ≤ i ∧ i < {upper})" + let caseProofs := (List.range chunkCount).map fun chunk => + s!" · exact hardMantissaLtGapBranch_of_chunk hardMantissaLtGapBranch_chunk{pad2 chunk}\n (by omega) (by omega)" + s!"import LnProof.Cert.HardMantissaLtGapC04\nimport LnProof.Cert.HardMantissaLtGapC09\n\nnamespace LnFloorCert\n\nset_option maxRecDepth 100000\n\nprivate theorem hardMantissaLtGapBranch_of_chunk {lb}start count i : Nat{rb}\n (hchunk : (List.range count).all\n (fun j => hardMantissaLtGapBranchB (j + start)) = true)\n (hlo : start ≤ i + 1) (hhi : i + 1 < start + count) :\n hardMantissaLtGapBranchB (i + 1) = true := by\n have h := List.all_eq_true.mp hchunk (i + 1 - start)\n (List.mem_range.mpr (by omega))\n rw [show i + 1 - start + start = i + 1 by omega] at h\n exact h\n\ntheorem hardMantissaLtGapBranch_all :\n (List.range {caseCount}).all (fun i => hardMantissaLtGapBranchB (i + 1)) = true := by\n rw [List.all_eq_true]\n intro i hi\n have hlt : i < {caseCount} := List.mem_range.mp hi\n have hcases :\n {String.intercalate " ∨\n " cases} := by\n omega\n rcases hcases with {String.intercalate " | " ((List.range chunkCount).map fun _ => "h")}\n{String.intercalate "\n" caseProofs}\n\nend LnFloorCert\n" +where + lb := "{" + rb := "}" + +def expectedOutputs : List String := + "HardMantissaLtGap.lean" :: (List.range chunkCount).map fun i => + s!"HardMantissaLtGapC{pad2 i}.lean" + +def generate : IO Unit := do + reconcileOutputs outDir ["HardMantissaLtGap"] expectedOutputs + let chunkOutputs := expectedOutputs.drop 1 + for (name, chunk) in chunkOutputs.zipIdx do + let offset := chunk * chunkSize + let count := min chunkSize (caseCount - offset) + IO.FS.writeFile s!"{outDir}/{name}" (chunkText chunk (offset + 1) count) + IO.FS.writeFile s!"{outDir}/HardMantissaLtGap.lean" aggregateText + +end GenBranchCertHard + +#eval GenBranchCertHard.generate diff --git a/formal/ln/LnProof/GenErrLit.lean b/formal/ln/LnProof/GenErrLit.lean index b3b7bffbd..8d2f00144 100644 --- a/formal/ln/LnProof/GenErrLit.lean +++ b/formal/ln/LnProof/GenErrLit.lean @@ -1,4 +1,7 @@ -import LnProof.Error.Core +import LnProof.Cert.FloorCertGeLoLit +import LnProof.Cert.FloorCertLtLoLit +import LnProof.Error.Core.ExpMargin +import LnProof.Error.Core.Budget import Common.Foundation.KroneckerShift import Common.GenCover diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean index c0e8d18c5..206bfa2b5 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean @@ -8,6 +8,7 @@ import LnProof.Error.Core.Direct import LnProof.Error.Core.PhaseCover import LnProof.Error.Core.Bounds import LnProof.Error.Core.Assembly +import LnProof.Cert.HardMantissaLtGap /-! # Error bound — BranchCert @@ -77,10 +78,6 @@ def posShiftGePhaseGapDirectOkB (m c : Nat) : Bool := sumGEB 320 (posPhaseNatGe m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ (posTopX c m) (10 ^ 18) -def posShiftLtPhaseGapDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatLt m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ - (posTopX c m) (10 ^ 18) - def posShiftGeBranchCertB (m c : Nat) (r : Int) : Bool := geResidueGapOkB m c r || (posShiftGeTopBudgetIneqOkB m c || @@ -97,15 +94,6 @@ def posShiftLtBranchCertB (m c : Nat) (r : Int) : Bool := (directResidueGapOkB m c r && posShiftLtPhaseGapDirectOkB m c) ))) -def hardMantissaLtGapBranchB (c : Nat) : Bool := - directResidueGapOkB lnErrorHardMantissa c - (int256 (lnTail (evmSub 160 c) lnErrorHardMantissa)) && - posShiftLtPhaseGapDirectOkB lnErrorHardMantissa c - -theorem hardMantissaLtGapBranch_all : - (List.range 159).all (fun i => hardMantissaLtGapBranchB (i + 1)) = true := by - decide +kernel - theorem hardMantissaLtGapBranch {c : Nat} (hc1 : 1 ≤ c) (hc : c < 160) : PosShiftDirectResidueGapOk lnErrorHardMantissa c (int256 (lnTail (evmSub 160 c) lnErrorHardMantissa)) ∧ diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean new file mode 100644 index 000000000..b2aac9b32 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean @@ -0,0 +1,19 @@ +import LnProof.Error.Core.Direct + +open FormalYul +open FormalYul.Preservation + +namespace LnFloorCert + +open LnYul LnFloor + +def posShiftLtPhaseGapDirectOkB (m c : Nat) : Bool := + sumGEB 320 (posPhaseNatLt m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ + (posTopX c m) (10 ^ 18) + +def hardMantissaLtGapBranchB (c : Nat) : Bool := + directResidueGapOkB lnErrorHardMantissa c + (int256 (lnTail (evmSub 160 c) lnErrorHardMantissa)) && + posShiftLtPhaseGapDirectOkB lnErrorHardMantissa c + +end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean b/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean index d6b3d13c3..18153506f 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean @@ -72,6 +72,7 @@ def twoPow99I : Int := 2 ^ 99 def lnPhaseScaleN : Nat := 1000000000000000000000000000 def lnPhaseScaleI : Int := 1000000000000000000000000000 def lnBiasI : Int := 116873961749927929127912020551516284764321243411868 +def lnErrorHardMantissa : Nat := 39770979022059719714796403827 /-- First-order exact-wad budget with the common `10^18` and `2^99` factors cancelled out. -/ diff --git a/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean b/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean index c27f6fcc0..9ffdec361 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean @@ -161,8 +161,6 @@ theorem ltPhaseGapCell_sound {lo hi m c : Nat} def phaseSearchFuel : Nat := 128 def phaseCoverFuel : Nat := 20000 -def lnErrorHardMantissa : Nat := 39770979022059719714796403827 - def phaseSearchMax (fuel : Nat) (ok : Nat → Bool) (lo hi best : Nat) : Nat := match fuel with | 0 => best diff --git a/formal/ln/README.md b/formal/ln/README.md index cea278093..b4d1fe7f2 100644 --- a/formal/ln/README.md +++ b/formal/ln/README.md @@ -69,13 +69,28 @@ The **generated certificates** under `Cert/` (ignored) come from the in-tree generators, run from `formal/ln/LnProof`: ```bash -lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts +lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts Common.GenCover lake env lean GenFloorCertLit.lean -lake build LnProof.Cert.FloorCertLit +lake build \ + LnProof.Cert.FloorCertGeUpLit \ + LnProof.Cert.FloorCertGeLoLit \ + LnProof.Cert.FloorCertLtUpLit \ + LnProof.Cert.FloorCertLtLoLit lake env lean GenCover.lean lake env lean GenErr1.lean -lake build LnProof.Error.Core +lake build \ + LnProof.Error.Core.ExpMargin \ + LnProof.Error.Core.Budget \ + LnProof.Error.Core.BranchCertHardDefs lake env lean GenErrLit.lean +lake env lean GenBranchCertHard.lean +lake build LnProof.Cert.HardMantissaLtGap +lake build ``` -See `.github/workflows/ln-formal.yml` for the canonical CI sequence. +The hard-mantissa certificate consists of ten generated 16-case-or-smaller +kernel checks in two contiguous dependency lanes. The generated aggregate +imports the two lane tips and reconstructs the 159-case theorem from those +checked chunks. + +See `.github/workflows/formal.yml` for the canonical CI sequence. From 040ae808f19a41a1cca8e68c868e3bcc03f798e3 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Sun, 12 Jul 2026 19:21:53 +0200 Subject: [PATCH 082/107] Unify selective formal proof CI Co-Authored-By: OpenAI Codex --- .github/actions/build-cbrt-proof/action.yml | 31 + .../actions/build-cbrt512-proof/action.yml | 28 + .github/actions/build-common-proof/action.yml | 10 + .github/actions/build-exp-proof/action.yml | 49 ++ .github/actions/build-ln-proof/action.yml | 61 +- .github/actions/build-sqrt-proof/action.yml | 31 + .../actions/build-sqrt512-proof/action.yml | 28 + .../actions/cache-formal-package/action.yml | 57 ++ .../check-generated-sources/action.yml | 90 +++ .github/actions/route-formal/action.yml | 56 ++ .github/actions/route-formal/route.sh | 160 ++++ .github/actions/setup-formal/action.yml | 95 ++- .github/workflows/cbrt-formal.yml | 75 -- .github/workflows/cbrt512-formal.yml | 95 --- .github/workflows/exp-formal.yml | 97 --- .github/workflows/formal.yml | 738 ++++++++++++++++++ .github/workflows/ln-formal.yml | 62 -- .github/workflows/sqrt-formal.yml | 75 -- .github/workflows/sqrt512-formal.yml | 95 --- formal/README.md | 465 +++++------ 20 files changed, 1584 insertions(+), 814 deletions(-) create mode 100644 .github/actions/build-cbrt-proof/action.yml create mode 100644 .github/actions/build-cbrt512-proof/action.yml create mode 100644 .github/actions/build-common-proof/action.yml create mode 100644 .github/actions/build-exp-proof/action.yml create mode 100644 .github/actions/build-sqrt-proof/action.yml create mode 100644 .github/actions/build-sqrt512-proof/action.yml create mode 100644 .github/actions/cache-formal-package/action.yml create mode 100644 .github/actions/check-generated-sources/action.yml create mode 100644 .github/actions/route-formal/action.yml create mode 100644 .github/actions/route-formal/route.sh delete mode 100644 .github/workflows/cbrt-formal.yml delete mode 100644 .github/workflows/cbrt512-formal.yml delete mode 100644 .github/workflows/exp-formal.yml create mode 100644 .github/workflows/formal.yml delete mode 100644 .github/workflows/ln-formal.yml delete mode 100644 .github/workflows/sqrt-formal.yml delete mode 100644 .github/workflows/sqrt512-formal.yml diff --git a/.github/actions/build-cbrt-proof/action.yml b/.github/actions/build-cbrt-proof/action.yml new file mode 100644 index 000000000..a5da365a0 --- /dev/null +++ b/.github/actions/build-cbrt-proof/action.yml @@ -0,0 +1,31 @@ +name: Build CbrtProof +description: Generate CbrtProof sources once and build the package. + +runs: + using: composite + steps: + - name: Generate Cbrt proof sources + uses: ./.github/actions/check-generated-sources + with: + generated-paths: | + formal/cbrt/CbrtProof/CbrtProof/CbrtYulRuntime.lean + formal/cbrt/CbrtProof/CbrtProof/CbrtYulProof.lean + formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean + generator: | + ./formal/yul/generate_from_forge.sh \ + cbrt \ + src/wrappers/CbrtWrapper.sol:CbrtWrapper \ + formal/cbrt/CbrtProof/CbrtProof/CbrtYul.lean \ + 0.8.34 + python3 formal/python/cbrt/generate_cbrt_cert.py \ + --output formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean + + - name: Fetch Cbrt proof dependency cache + uses: ./.github/actions/fetch-lean-cache + with: + working-directory: formal/cbrt/CbrtProof + + - name: Build Cbrt proof package + shell: bash + working-directory: formal/cbrt/CbrtProof + run: lake build diff --git a/.github/actions/build-cbrt512-proof/action.yml b/.github/actions/build-cbrt512-proof/action.yml new file mode 100644 index 000000000..386bc39ad --- /dev/null +++ b/.github/actions/build-cbrt512-proof/action.yml @@ -0,0 +1,28 @@ +name: Build Cbrt512Proof +description: Generate Cbrt512Proof sources once and build the package. + +runs: + using: composite + steps: + - name: Generate Cbrt512 EVMYulLean artifacts + uses: ./.github/actions/check-generated-sources + with: + generated-paths: | + formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512YulRuntime.lean + formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512YulProof.lean + generator: | + ./formal/yul/generate_from_forge.sh \ + cbrt512 \ + src/wrappers/Cbrt512Wrapper.sol:Cbrt512Wrapper \ + formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Yul.lean \ + 0.8.34 + + - name: Fetch Cbrt512 proof dependency cache + uses: ./.github/actions/fetch-lean-cache + with: + working-directory: formal/cbrt/Cbrt512Proof + + - name: Build Cbrt512 proof package + shell: bash + working-directory: formal/cbrt/Cbrt512Proof + run: lake build diff --git a/.github/actions/build-common-proof/action.yml b/.github/actions/build-common-proof/action.yml new file mode 100644 index 000000000..31c11c21b --- /dev/null +++ b/.github/actions/build-common-proof/action.yml @@ -0,0 +1,10 @@ +name: Build Common +description: Build the shared formal proof package. + +runs: + using: composite + steps: + - name: Build Common package + shell: bash + working-directory: formal/common + run: lake build diff --git a/.github/actions/build-exp-proof/action.yml b/.github/actions/build-exp-proof/action.yml new file mode 100644 index 000000000..03167f068 --- /dev/null +++ b/.github/actions/build-exp-proof/action.yml @@ -0,0 +1,49 @@ +name: Build ExpProof +description: Generate ExpProof sources once and build the package. + +runs: + using: composite + steps: + - name: Generate Exp EVMYulLean artifacts + uses: ./.github/actions/check-generated-sources + with: + generated-paths: | + formal/exp/ExpProof/ExpProof/ExpYulRuntime.lean + formal/exp/ExpProof/ExpProof/ExpYulProof.lean + generator: | + ./formal/yul/generate_from_forge.sh \ + exp \ + src/wrappers/ExpWrapper.sol:ExpWrapper \ + formal/exp/ExpProof/ExpProof/ExpYul.lean \ + 0.8.34 + + - name: Fetch Exp proof dependency cache + uses: ./.github/actions/fetch-lean-cache + with: + working-directory: formal/exp/ExpProof + + - name: Generate Exp certificates + uses: ./.github/actions/check-generated-sources + with: + working-directory: formal/exp/ExpProof + generated-paths: ExpProof/Cert + generator: | + for path in .lake/build/lib/lean/ExpProof/Cert .lake/build/ir/ExpProof/Cert; do + if [[ -e "$path" ]]; then + rm -r -- "$path" + fi + done + lake build \ + ExpProof.Floor.CertDefsV \ + ExpProof.Floor.GranPieces \ + ExpProof.Floor.UnderCarryDefs \ + Common.Foundation.KroneckerShift \ + Common.GenCover \ + Common.GenBernstein + lake env lean GenExpVLit.lean + lake env lean GenExpUnderCarry.lean + + - name: Build Exp proof package + shell: bash + working-directory: formal/exp/ExpProof + run: lake build diff --git a/.github/actions/build-ln-proof/action.yml b/.github/actions/build-ln-proof/action.yml index 949a6bcd6..2e0dde4a0 100644 --- a/.github/actions/build-ln-proof/action.yml +++ b/.github/actions/build-ln-proof/action.yml @@ -7,33 +7,54 @@ description: >- runs: using: composite steps: - - name: Generate EVMYulLean artifacts from compiled LnWrapper Yul IR - shell: bash - run: | - ./formal/yul/generate_from_forge.sh \ - ln \ - src/wrappers/LnWrapper.sol:LnWrapper \ - formal/ln/LnProof/LnProof/LnYul.lean \ - 0.8.34 + - name: Generate Ln EVMYulLean artifacts + uses: ./.github/actions/check-generated-sources + with: + generated-paths: | + formal/ln/LnProof/LnProof/LnYulRuntime.lean + formal/ln/LnProof/LnProof/LnYulProof.lean + generator: | + ./formal/yul/generate_from_forge.sh \ + ln \ + src/wrappers/LnWrapper.sol:LnWrapper \ + formal/ln/LnProof/LnProof/LnYul.lean \ + 0.8.34 - name: Fetch Ln proof dependency cache uses: ./.github/actions/fetch-lean-cache with: working-directory: formal/ln/LnProof - - name: Generate Ln certificate artifacts - shell: bash - working-directory: formal/ln/LnProof - run: | - lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts Common.GenCover - lake env lean GenFloorCertLit.lean - lake build LnProof.Cert.FloorCertLit - lake env lean GenCover.lean - lake env lean GenErr1.lean - lake build LnProof.Error.Core - lake env lean GenErrLit.lean + - name: Generate Ln certificates + uses: ./.github/actions/check-generated-sources + with: + working-directory: formal/ln/LnProof + generated-paths: LnProof/Cert + generator: | + for path in .lake/build/lib/lean/LnProof/Cert .lake/build/ir/LnProof/Cert; do + if [[ -e "$path" ]]; then + rm -r -- "$path" + fi + done + lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts Common.GenCover + lake env lean GenFloorCertLit.lean + lake build \ + LnProof.Cert.FloorCertGeUpLit \ + LnProof.Cert.FloorCertGeLoLit \ + LnProof.Cert.FloorCertLtUpLit \ + LnProof.Cert.FloorCertLtLoLit + lake env lean GenCover.lean + lake env lean GenErr1.lean + lake build \ + LnProof.Error.Core.ExpMargin \ + LnProof.Error.Core.Budget \ + LnProof.Error.Core.BranchCertHardDefs + lake env lean GenErrLit.lean + lake env lean GenBranchCertHard.lean - name: Build Ln proof package shell: bash working-directory: formal/ln/LnProof - run: lake build + run: | + lake build LnProof.Cert.HardMantissaLtGap + lake build diff --git a/.github/actions/build-sqrt-proof/action.yml b/.github/actions/build-sqrt-proof/action.yml new file mode 100644 index 000000000..80455c6b4 --- /dev/null +++ b/.github/actions/build-sqrt-proof/action.yml @@ -0,0 +1,31 @@ +name: Build SqrtProof +description: Generate SqrtProof sources once and build the package. + +runs: + using: composite + steps: + - name: Generate Sqrt proof sources + uses: ./.github/actions/check-generated-sources + with: + generated-paths: | + formal/sqrt/SqrtProof/SqrtProof/SqrtYulRuntime.lean + formal/sqrt/SqrtProof/SqrtProof/SqrtYulProof.lean + formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean + generator: | + ./formal/yul/generate_from_forge.sh \ + sqrt \ + src/wrappers/SqrtWrapper.sol:SqrtWrapper \ + formal/sqrt/SqrtProof/SqrtProof/SqrtYul.lean \ + 0.8.34 + python3 formal/python/sqrt/generate_sqrt_cert.py \ + --output formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean + + - name: Fetch Sqrt proof dependency cache + uses: ./.github/actions/fetch-lean-cache + with: + working-directory: formal/sqrt/SqrtProof + + - name: Build Sqrt proof package + shell: bash + working-directory: formal/sqrt/SqrtProof + run: lake build diff --git a/.github/actions/build-sqrt512-proof/action.yml b/.github/actions/build-sqrt512-proof/action.yml new file mode 100644 index 000000000..89e1dc72f --- /dev/null +++ b/.github/actions/build-sqrt512-proof/action.yml @@ -0,0 +1,28 @@ +name: Build Sqrt512Proof +description: Generate Sqrt512Proof sources once and build the package. + +runs: + using: composite + steps: + - name: Generate Sqrt512 EVMYulLean artifacts + uses: ./.github/actions/check-generated-sources + with: + generated-paths: | + formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulRuntime.lean + formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulProof.lean + generator: | + ./formal/yul/generate_from_forge.sh \ + sqrt512 \ + src/wrappers/Sqrt512Wrapper.sol:Sqrt512Wrapper \ + formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512Yul.lean \ + 0.8.34 + + - name: Fetch Sqrt512 proof dependency cache + uses: ./.github/actions/fetch-lean-cache + with: + working-directory: formal/sqrt/Sqrt512Proof + + - name: Build Sqrt512 proof package + shell: bash + working-directory: formal/sqrt/Sqrt512Proof + run: lake build diff --git a/.github/actions/cache-formal-package/action.yml b/.github/actions/cache-formal-package/action.yml new file mode 100644 index 000000000..697c975c8 --- /dev/null +++ b/.github/actions/cache-formal-package/action.yml @@ -0,0 +1,57 @@ +name: Cache formal package +description: >- + Restore one Lean proof package under a key that includes its direct + dependency sources and its own sources. Restore-only consumers require the + exact cache produced by their ordered publisher. + +inputs: + cache-name: + description: Stable package name used only by this package's cache. + required: true + cache-path: + description: Newline-separated package build and generated-source paths. + required: true + dependency-hash-globs: + description: Newline-separated hashFiles patterns for direct dependencies. + required: true + source-hash-globs: + description: Newline-separated hashFiles patterns for the package inputs. + required: true + publish: + description: Save a cache miss after the job completes. + required: false + default: "true" + +outputs: + cache-hit: + description: Whether an exact cache entry was restored. + value: ${{ steps.cache.outputs.cache-hit || steps.restore.outputs.cache-hit }} + +runs: + using: composite + steps: + - name: Restore and publish ${{ inputs.cache-name }} cache + id: cache + if: inputs.publish == 'true' + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: ${{ inputs.cache-path }} + key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} + restore-keys: | + ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}- + ${{ runner.os }}-formal-${{ inputs.cache-name }}- + + - name: Restore ${{ inputs.cache-name }} cache without publishing + id: restore + if: inputs.publish != 'true' + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: ${{ inputs.cache-path }} + key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} + + - name: Require exact ${{ inputs.cache-name }} cache from its publisher + if: inputs.publish != 'true' && steps.restore.outputs.cache-hit != 'true' + shell: bash + run: | + echo "exact ${{ inputs.cache-name }} cache is unavailable after its publisher completed" >&2 + exit 1 diff --git a/.github/actions/check-generated-sources/action.yml b/.github/actions/check-generated-sources/action.yml new file mode 100644 index 000000000..0408513f2 --- /dev/null +++ b/.github/actions/check-generated-sources/action.yml @@ -0,0 +1,90 @@ +name: Generate declared Lean sources +description: >- + Clean each declared output surface, generate it once, and require nonempty + outputs without modifying tracked sources. + +inputs: + working-directory: + description: Directory from which to run the generator and resolve paths. + required: false + default: . + generated-paths: + description: >- + Newline-separated generated files or generated-only directories. A + directory may contain a tracked .gitkeep file. + required: true + generator: + description: Generator command to run from a clean output set. + required: true + +runs: + using: composite + steps: + - name: Generate declared sources + shell: bash + working-directory: ${{ inputs.working-directory }} + env: + GENERATED_PATHS: ${{ inputs.generated-paths }} + GENERATOR: ${{ inputs.generator }} + run: | + set -euo pipefail + git diff --exit-code + git diff --cached --exit-code + + validate_path() { + case "$1" in + ''|/*|..|../*|*/..|*/../*) + echo "generated path must stay within the working directory: $1" >&2 + exit 2 + ;; + esac + } + + paths=() + while IFS= read -r path; do + [[ -n "$path" ]] || continue + validate_path "$path" + paths+=("$path") + done <<< "$GENERATED_PATHS" + + [[ ${#paths[@]} -gt 0 ]] || { + echo "at least one generated path is required" >&2 + exit 2 + } + + clean_surfaces() { + local path file + for path in "${paths[@]}"; do + if [[ -d "$path" ]]; then + while IFS= read -r -d '' file; do + rm -- "$file" + done < <(find "$path" -type f ! -name .gitkeep -print0) + find "$path" -depth -type d -empty ! -path "$path" -delete + elif [[ -e "$path" ]]; then + rm -- "$path" + fi + done + } + + require_outputs() { + local path + for path in "${paths[@]}"; do + if [[ -d "$path" ]]; then + if ! find "$path" -type f ! -name .gitkeep -print -quit | grep -q .; then + echo "generated directory is empty: $path" >&2 + exit 1 + fi + elif [[ -s "$path" ]]; then + continue + else + echo "generated file is missing or empty: $path" >&2 + exit 1 + fi + done + } + + clean_surfaces + bash -e -u -o pipefail -c "$GENERATOR" + require_outputs + git diff --exit-code + git diff --cached --exit-code diff --git a/.github/actions/route-formal/action.yml b/.github/actions/route-formal/action.yml new file mode 100644 index 000000000..aa486ad81 --- /dev/null +++ b/.github/actions/route-formal/action.yml @@ -0,0 +1,56 @@ +name: Route formal checks +description: Select the formal proof jobs affected by the current change. + +inputs: + event-name: + description: GitHub event name. + required: true + before-sha: + description: Push event predecessor commit. + required: false + base-sha: + description: Pull request base commit. + required: false + head-sha: + description: Commit containing the proposed changes. + required: true + +outputs: + any: + description: Whether any formal package is affected. + value: ${{ steps.route.outputs.any }} + common: + description: Whether Common is required. + value: ${{ steps.route.outputs.common }} + cbrt: + description: Whether CbrtProof is required. + value: ${{ steps.route.outputs.cbrt }} + cbrt512: + description: Whether Cbrt512Proof is required. + value: ${{ steps.route.outputs.cbrt512 }} + sqrt: + description: Whether SqrtProof is required. + value: ${{ steps.route.outputs.sqrt }} + sqrt512: + description: Whether Sqrt512Proof is required. + value: ${{ steps.route.outputs.sqrt512 }} + ln: + description: Whether LnProof is required. + value: ${{ steps.route.outputs.ln }} + exp: + description: Whether ExpProof is required. + value: ${{ steps.route.outputs.exp }} + +runs: + using: composite + steps: + - name: Select affected formal packages + id: route + shell: bash + env: + EVENT_NAME: ${{ inputs.event-name }} + BEFORE_SHA: ${{ inputs.before-sha }} + BASE_SHA: ${{ inputs.base-sha }} + HEAD_SHA: ${{ inputs.head-sha }} + ROUTER: ${{ github.action_path }}/route.sh + run: bash "$ROUTER" diff --git a/.github/actions/route-formal/route.sh b/.github/actions/route-formal/route.sh new file mode 100644 index 000000000..e120e609a --- /dev/null +++ b/.github/actions/route-formal/route.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${GITHUB_OUTPUT:?}" +: "${EVENT_NAME:?}" +: "${HEAD_SHA:?}" + +changed_paths="$(mktemp)" +trap 'rm "$changed_paths"' EXIT +route_all=false + +case "$EVENT_NAME" in + pull_request) + : "${BASE_SHA:?}" + git diff --name-only --no-renames "$BASE_SHA...$HEAD_SHA" > "$changed_paths" + ;; + push) + zero_sha='0000000000000000000000000000000000000000' + if [[ -z "${BEFORE_SHA:-}" || "$BEFORE_SHA" == "$zero_sha" ]]; then + route_all=true + else + git diff --name-only --no-renames "$BEFORE_SHA" "$HEAD_SHA" > "$changed_paths" + fi + ;; + *) + echo "unsupported formal routing event: $EVENT_NAME" >&2 + exit 2 + ;; +esac + +common=false +cbrt=false +cbrt512=false +sqrt=false +sqrt512=false +ln=false +exp=false + +select_all() { + common=true + cbrt=true + cbrt512=true + sqrt=true + sqrt512=true + ln=true + exp=true +} + +if [[ "$route_all" == true ]]; then + select_all +fi + +while IFS= read -r path; do + case "$path" in + .github/workflows/formal.yml | \ + .github/actions/route-formal/* | \ + .github/actions/setup-formal/* | \ + .github/actions/cache-formal-package/* | \ + .github/actions/check-generated-sources/* | \ + .github/actions/fetch-lean-cache/* | \ + formal/yul/* | \ + foundry.toml | remappings.txt | .gitmodules | lib/EVMYulLean) + select_all + ;; + .github/actions/build-cbrt-proof/* | formal/cbrt/* | formal/python/cbrt/*) + cbrt=true + cbrt512=true + ;; + .github/actions/build-cbrt512-proof/* | src/wrappers/Cbrt512Wrapper.sol) + cbrt512=true + ;; + .github/actions/build-sqrt-proof/* | formal/sqrt/* | formal/python/sqrt/*) + sqrt=true + sqrt512=true + ;; + .github/actions/build-sqrt512-proof/* | src/wrappers/Sqrt512Wrapper.sol) + sqrt512=true + ;; + .github/actions/build-common-proof/* | .github/actions/build-ln-proof/* | \ + formal/common/* | formal/ln/* | \ + src/vendor/Ln.sol | src/wrappers/LnWrapper.sol) + common=true + ln=true + exp=true + ;; + .github/actions/build-exp-proof/* | formal/exp/* | src/vendor/Exp.sol | \ + src/wrappers/ExpWrapper.sol) + exp=true + ;; + src/wrappers/CbrtWrapper.sol) + cbrt=true + cbrt512=true + ;; + src/wrappers/SqrtWrapper.sol) + sqrt=true + sqrt512=true + ;; + src/vendor/Cbrt.sol) + cbrt=true + cbrt512=true + sqrt512=true + ;; + src/vendor/Sqrt.sol) + cbrt512=true + sqrt=true + sqrt512=true + ;; + src/vendor/Clz.sol) + cbrt512=true + sqrt512=true + exp=true + ;; + src/utils/FastLogic.sol) + cbrt512=true + sqrt512=true + exp=true + ;; + src/utils/Panic.sol) + cbrt512=true + sqrt512=true + ln=true + exp=true + ;; + src/utils/512Math.sol | src/utils/Ternary.sol | src/utils/UnsafeMath.sol | lib/forge-std) + cbrt512=true + sqrt512=true + ;; + esac +done < "$changed_paths" + +if [[ "$cbrt512" == true ]]; then + cbrt=true +fi +if [[ "$sqrt512" == true ]]; then + sqrt=true +fi +if [[ "$exp" == true ]]; then + common=true + ln=true +fi +if [[ "$ln" == true ]]; then + common=true +fi + +any=false +if [[ "$common" == true || "$cbrt" == true || "$cbrt512" == true || \ + "$sqrt" == true || "$sqrt512" == true || "$ln" == true || "$exp" == true ]]; then + any=true +fi + +{ + printf 'any=%s\n' "$any" + printf 'common=%s\n' "$common" + printf 'cbrt=%s\n' "$cbrt" + printf 'cbrt512=%s\n' "$cbrt512" + printf 'sqrt=%s\n' "$sqrt" + printf 'sqrt512=%s\n' "$sqrt512" + printf 'ln=%s\n' "$ln" + printf 'exp=%s\n' "$exp" +} >> "$GITHUB_OUTPUT" diff --git a/.github/actions/setup-formal/action.yml b/.github/actions/setup-formal/action.yml index c40e40033..594c33b9c 100644 --- a/.github/actions/setup-formal/action.yml +++ b/.github/actions/setup-formal/action.yml @@ -1,9 +1,8 @@ name: Set up the formal toolchain description: >- - The shared prefix of every *-formal workflow: install Foundry and the pinned - Lean toolchain, restore the Lean build cache, install solc 0.8.34, fetch the - Yul importer's Mathlib cache, and build the Yul importer. Requires the - repository (with submodules) to be checked out first. + Install Foundry and the pinned Lean toolchain, restore separate dependency + and formal-tool caches, install solc 0.8.34, fetch the Yul importer's + Mathlib cache, and build the Yul importer. Proof packages cache separately. inputs: lean-toolchain-files: @@ -11,26 +10,24 @@ inputs: Newline-separated lean-toolchain file paths. The first names the toolchain to install; every subsequent file must pin the same toolchain. required: true - cache-name: - description: Per-proof segment of the Lean build cache key (e.g. exp-formal). - required: true - cache-paths: - description: >- - Newline-separated proof-package build directories to cache, in addition - to the Yul importer's and EVMYulLean's. - required: true - cache-hash-globs: - description: >- - Newline-separated hashFiles patterns covering the proof packages' lake - configuration and Lean sources, hashed into the cache key alongside the - Yul importer's and EVMYulLean's. - required: true + publish: + description: Save dependency and formal-tool cache misses after the job completes. + required: false + default: "true" + +outputs: + dependency-cache-hit: + description: Whether the exact formal dependency cache was restored. + value: ${{ steps.dependency-cache.outputs.cache-hit || steps.dependency-restore.outputs.cache-hit }} + tool-cache-hit: + description: Whether the exact formal-tool cache was restored. + value: ${{ steps.tool-cache.outputs.cache-hit || steps.tool-restore.outputs.cache-hit }} runs: using: composite steps: - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1 with: version: v1.5.1 @@ -39,7 +36,9 @@ runs: env: LEAN_TOOLCHAIN_FILES: ${{ inputs.lean-toolchain-files }} run: | - curl https://raw.githubusercontent.com/leanprover/elan/917c18d0ad52f649c2603dc8b973f5b9fa5f8f43/elan-init.sh -sSf | sh -s -- -y --default-toolchain none + curl --silent --show-error --fail-with-body \ + https://raw.githubusercontent.com/leanprover/elan/917c18d0ad52f649c2603dc8b973f5b9fa5f8f43/elan-init.sh \ + | sh -s -- -y --default-toolchain none echo "$HOME/.elan/bin" >> "$GITHUB_PATH" LEAN_TOOLCHAIN='' while IFS= read -r file; do @@ -53,18 +52,60 @@ runs: "$HOME/.elan/bin/elan" toolchain install "$LEAN_TOOLCHAIN" "$HOME/.elan/bin/elan" default "$LEAN_TOOLCHAIN" - - name: Restore Lean build cache - uses: actions/cache@v4 + - name: Restore and publish formal dependency cache + id: dependency-cache + if: inputs.publish == 'true' + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: formal/yul/.lake/packages/*/.lake/build + key: ${{ runner.os }}-formal-dependencies-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} + restore-keys: | + ${{ runner.os }}-formal-dependencies- + + - name: Restore formal dependency cache without publishing + id: dependency-restore + if: inputs.publish != 'true' + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: formal/yul/.lake/packages/*/.lake/build + key: ${{ runner.os }}-formal-dependencies-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} + + - name: Require exact formal dependency cache from its publisher + if: inputs.publish != 'true' && steps.dependency-restore.outputs.cache-hit != 'true' + shell: bash + run: | + echo "exact formal dependency cache is unavailable after its publisher completed" >&2 + exit 1 + + - name: Restore and publish formal tool cache + id: tool-cache + if: inputs.publish == 'true' + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | formal/yul/.lake/build - formal/yul/.lake/packages/*/.lake/build lib/EVMYulLean/.lake/build - ${{ inputs.cache-paths }} - key: ${{ runner.os }}-${{ inputs.cache-name }}-lean-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'formal/yul/FormalYul/**/*.lean', 'lib/EVMYulLean/**/*.lean') }}-${{ hashFiles(inputs.cache-hash-globs) }} + key: ${{ runner.os }}-formal-tools-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }}-${{ hashFiles('formal/yul/FormalYul.lean', 'formal/yul/YulImporter.lean', 'formal/yul/FormalYul/**/*.lean', 'lib/EVMYulLean/**/*.lean', 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }} restore-keys: | - ${{ runner.os }}-${{ inputs.cache-name }}-lean- - ${{ runner.os }}-formal-lean- + ${{ runner.os }}-formal-tools-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }}- + ${{ runner.os }}-formal-tools- + + - name: Restore formal tool cache without publishing + id: tool-restore + if: inputs.publish != 'true' + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: | + formal/yul/.lake/build + lib/EVMYulLean/.lake/build + key: ${{ runner.os }}-formal-tools-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }}-${{ hashFiles('formal/yul/FormalYul.lean', 'formal/yul/YulImporter.lean', 'formal/yul/FormalYul/**/*.lean', 'lib/EVMYulLean/**/*.lean', 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }} + + - name: Require exact formal tool cache from its publisher + if: inputs.publish != 'true' && steps.tool-restore.outputs.cache-hit != 'true' + shell: bash + run: | + echo "exact formal tool cache is unavailable after its publisher completed" >&2 + exit 1 - name: Install solc 0.8.34 shell: bash diff --git a/.github/workflows/cbrt-formal.yml b/.github/workflows/cbrt-formal.yml deleted file mode 100644 index 7790a1aec..000000000 --- a/.github/workflows/cbrt-formal.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Cbrt.sol Formal Check - -on: - push: - branches: - - master - paths: - - src/vendor/Cbrt.sol - - src/wrappers/CbrtWrapper.sol - - formal/cbrt/** - - formal/python/cbrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/cbrt-formal.yml - pull_request: - paths: - - src/vendor/Cbrt.sol - - src/wrappers/CbrtWrapper.sol - - formal/cbrt/** - - formal/python/cbrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/cbrt-formal.yml - -jobs: - cbrt-formal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Set up the formal toolchain - uses: ./.github/actions/setup-formal - with: - lean-toolchain-files: formal/cbrt/CbrtProof/lean-toolchain - cache-name: cbrt-formal - cache-paths: | - formal/cbrt/CbrtProof/.lake/build - cache-hash-globs: | - formal/cbrt/CbrtProof/lakefile.toml - formal/cbrt/CbrtProof/lake-manifest.json - formal/cbrt/CbrtProof/**/*.lean - - - name: Generate EVMYulLean artifacts from compiled CbrtWrapper Yul IR - run: | - ./formal/yul/generate_from_forge.sh \ - cbrt \ - src/wrappers/CbrtWrapper.sol:CbrtWrapper \ - formal/cbrt/CbrtProof/CbrtProof/CbrtYul.lean \ - 0.8.34 - - - name: Generate finite certificate from Python generator - run: | - python3 formal/python/cbrt/generate_cbrt_cert.py \ - --output formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean - - - name: Fetch proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/cbrt/CbrtProof - - - name: Build Cbrt proof package - working-directory: formal/cbrt/CbrtProof - run: lake build diff --git a/.github/workflows/cbrt512-formal.yml b/.github/workflows/cbrt512-formal.yml deleted file mode 100644 index 848d18f4f..000000000 --- a/.github/workflows/cbrt512-formal.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: 512Math cbrt Formal Check - -on: - push: - branches: - - master - paths: - - src/utils/512Math.sol - - src/utils/FastLogic.sol - - src/utils/Panic.sol - - src/utils/Ternary.sol - - src/utils/UnsafeMath.sol - - src/vendor/Clz.sol - - src/vendor/Cbrt.sol - - src/vendor/Sqrt.sol - - src/wrappers/Cbrt512Wrapper.sol - - formal/cbrt/** - - formal/python/cbrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/cbrt512-formal.yml - pull_request: - paths: - - src/utils/512Math.sol - - src/utils/FastLogic.sol - - src/utils/Panic.sol - - src/utils/Ternary.sol - - src/utils/UnsafeMath.sol - - src/vendor/Clz.sol - - src/vendor/Cbrt.sol - - src/vendor/Sqrt.sol - - src/wrappers/Cbrt512Wrapper.sol - - formal/cbrt/** - - formal/python/cbrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/cbrt512-formal.yml - -jobs: - cbrt512-formal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Set up the formal toolchain - uses: ./.github/actions/setup-formal - with: - lean-toolchain-files: | - formal/cbrt/Cbrt512Proof/lean-toolchain - formal/cbrt/CbrtProof/lean-toolchain - cache-name: cbrt512-formal - cache-paths: | - formal/cbrt/CbrtProof/.lake/build - formal/cbrt/Cbrt512Proof/.lake/build - cache-hash-globs: | - formal/cbrt/CbrtProof/lakefile.toml - formal/cbrt/CbrtProof/lake-manifest.json - formal/cbrt/Cbrt512Proof/lakefile.toml - formal/cbrt/Cbrt512Proof/lake-manifest.json - formal/cbrt/CbrtProof/**/*.lean - formal/cbrt/Cbrt512Proof/**/*.lean - - - name: Generate 512-bit EVMYulLean artifacts from compiled Cbrt512Wrapper Yul IR - run: | - ./formal/yul/generate_from_forge.sh \ - cbrt512 \ - src/wrappers/Cbrt512Wrapper.sol:Cbrt512Wrapper \ - formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Yul.lean \ - 0.8.34 - - - name: Generate 256-bit cbrt finite certificate (CbrtProof dependency) from Python generator - run: | - python3 formal/python/cbrt/generate_cbrt_cert.py \ - --output formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean - - - name: Fetch proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/cbrt/Cbrt512Proof - - - name: Build Cbrt512 proof package - working-directory: formal/cbrt/Cbrt512Proof - run: lake build diff --git a/.github/workflows/exp-formal.yml b/.github/workflows/exp-formal.yml deleted file mode 100644 index abab71aae..000000000 --- a/.github/workflows/exp-formal.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: Exp.sol Formal Check - -on: - push: - branches: - - master - paths: - - src/utils/Panic.sol - - src/vendor/Exp.sol - - src/vendor/Ln.sol - - src/wrappers/ExpWrapper.sol - - src/wrappers/LnWrapper.sol - - formal/exp/** - - formal/ln/** - - formal/common/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/exp-formal.yml - - .github/actions/build-ln-proof/action.yml - pull_request: - paths: - - src/utils/Panic.sol - - src/vendor/Exp.sol - - src/vendor/Ln.sol - - src/wrappers/ExpWrapper.sol - - src/wrappers/LnWrapper.sol - - formal/exp/** - - formal/ln/** - - formal/common/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/exp-formal.yml - - .github/actions/build-ln-proof/action.yml - -jobs: - exp-formal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Set up the formal toolchain - uses: ./.github/actions/setup-formal - with: - lean-toolchain-files: formal/exp/ExpProof/lean-toolchain - cache-name: exp-formal - cache-paths: | - formal/common/.lake/build - formal/ln/LnProof/.lake/build - formal/exp/ExpProof/.lake/build - cache-hash-globs: | - formal/common/lakefile.toml - formal/common/lake-manifest.json - formal/common/**/*.lean - formal/ln/LnProof/lakefile.toml - formal/ln/LnProof/lake-manifest.json - formal/ln/LnProof/**/*.lean - formal/exp/ExpProof/lakefile.toml - formal/exp/ExpProof/lake-manifest.json - formal/exp/ExpProof/**/*.lean - - - name: Generate EVMYulLean artifacts from compiled ExpWrapper Yul IR - run: | - ./formal/yul/generate_from_forge.sh \ - exp \ - src/wrappers/ExpWrapper.sol:ExpWrapper \ - formal/exp/ExpProof/ExpProof/ExpYul.lean \ - 0.8.34 - - - name: Build Ln proof dependency - uses: ./.github/actions/build-ln-proof - - - name: Fetch proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/exp/ExpProof - - - name: Generate Lean certificate artifacts - working-directory: formal/exp/ExpProof - run: | - lake build ExpProof.Floor.CertDefsV ExpProof.Floor.GranPieces Common.Foundation.KroneckerShift Common.GenCover - lake env lean GenExpVLit.lean - - - name: Build Exp proof package - working-directory: formal/exp/ExpProof - run: lake build diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml new file mode 100644 index 000000000..b86660c47 --- /dev/null +++ b/.github/workflows/formal.yml @@ -0,0 +1,738 @@ +name: Formal Checks + +on: + push: + branches: + - master + pull_request: + +permissions: + contents: read + +jobs: + route: + name: Select formal checks + runs-on: ubuntu-latest + outputs: + any: ${{ steps.route.outputs.any }} + common: ${{ steps.route.outputs.common }} + cbrt: ${{ steps.route.outputs.cbrt }} + cbrt512: ${{ steps.route.outputs.cbrt512 }} + sqrt: ${{ steps.route.outputs.sqrt }} + sqrt512: ${{ steps.route.outputs.sqrt512 }} + ln: ${{ steps.route.outputs.ln }} + exp: ${{ steps.route.outputs.exp }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Select affected formal packages + id: route + uses: ./.github/actions/route-formal + with: + event-name: ${{ github.event_name }} + before-sha: ${{ github.event.before }} + base-sha: ${{ github.event.pull_request.base.sha }} + head-sha: ${{ github.event.pull_request.head.sha || github.sha }} + + base: + name: Publish formal base caches + needs: route + if: needs.route.outputs.any == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Build and publish the formal base + uses: ./.github/actions/setup-formal + with: + publish: "true" + lean-toolchain-files: | + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + formal/common/lean-toolchain + formal/ln/LnProof/lean-toolchain + formal/exp/ExpProof/lean-toolchain + formal/cbrt/CbrtProof/lean-toolchain + formal/cbrt/Cbrt512Proof/lean-toolchain + formal/sqrt/SqrtProof/lean-toolchain + formal/sqrt/Sqrt512Proof/lean-toolchain + + common: + name: Common formal check + needs: + - route + - base + if: needs.route.outputs.common == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/common/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Common package cache + id: common-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: common + publish: "true" + cache-path: formal/common/.lake/build + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/common/lean-toolchain + formal/common/lakefile.toml + formal/common/lake-manifest.json + formal/common/Common.lean + formal/common/Common/**/*.lean + .github/actions/build-common-proof/** + + - name: Build Common package after a cache miss + if: steps.common-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-common-proof + + cbrt: + name: Cbrt.sol formal check + needs: + - route + - base + if: needs.route.outputs.cbrt == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/cbrt/CbrtProof/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Cbrt package cache + id: cbrt-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: cbrt + publish: "true" + cache-path: | + formal/cbrt/CbrtProof/.lake/build + formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean + formal/cbrt/CbrtProof/CbrtProof/CbrtYulRuntime.lean + formal/cbrt/CbrtProof/CbrtProof/CbrtYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/cbrt/CbrtProof/lean-toolchain + formal/cbrt/CbrtProof/lakefile.toml + formal/cbrt/CbrtProof/lake-manifest.json + formal/cbrt/CbrtProof/**/*.lean + formal/python/cbrt/**/*.py + src/vendor/Cbrt.sol + src/wrappers/CbrtWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-cbrt-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Build Cbrt proof package after a cache miss + if: steps.cbrt-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-cbrt-proof + + sqrt: + name: Sqrt.sol formal check + needs: + - route + - base + if: needs.route.outputs.sqrt == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/sqrt/SqrtProof/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Sqrt package cache + id: sqrt-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: sqrt + publish: "true" + cache-path: | + formal/sqrt/SqrtProof/.lake/build + formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean + formal/sqrt/SqrtProof/SqrtProof/SqrtYulRuntime.lean + formal/sqrt/SqrtProof/SqrtProof/SqrtYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/sqrt/SqrtProof/lean-toolchain + formal/sqrt/SqrtProof/lakefile.toml + formal/sqrt/SqrtProof/lake-manifest.json + formal/sqrt/SqrtProof/**/*.lean + formal/python/sqrt/**/*.py + src/vendor/Sqrt.sol + src/wrappers/SqrtWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-sqrt-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Build Sqrt proof package after a cache miss + if: steps.sqrt-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-sqrt-proof + + cbrt512: + name: 512Math cbrt formal check + needs: + - route + - base + - cbrt + if: needs.route.outputs.cbrt512 == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/cbrt/Cbrt512Proof/lean-toolchain + formal/cbrt/CbrtProof/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Cbrt dependency cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: cbrt + publish: "false" + cache-path: | + formal/cbrt/CbrtProof/.lake/build + formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean + formal/cbrt/CbrtProof/CbrtProof/CbrtYulRuntime.lean + formal/cbrt/CbrtProof/CbrtProof/CbrtYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/cbrt/CbrtProof/lean-toolchain + formal/cbrt/CbrtProof/lakefile.toml + formal/cbrt/CbrtProof/lake-manifest.json + formal/cbrt/CbrtProof/**/*.lean + formal/python/cbrt/**/*.py + src/vendor/Cbrt.sol + src/wrappers/CbrtWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-cbrt-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Restore Cbrt512 package cache + id: cbrt512-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: cbrt512 + publish: "true" + cache-path: | + formal/cbrt/Cbrt512Proof/.lake/build + formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512YulRuntime.lean + formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512YulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + formal/cbrt/CbrtProof/lean-toolchain + formal/cbrt/CbrtProof/lakefile.toml + formal/cbrt/CbrtProof/lake-manifest.json + formal/cbrt/CbrtProof/**/*.lean + formal/python/cbrt/**/*.py + src/vendor/Cbrt.sol + src/wrappers/CbrtWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-cbrt-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + source-hash-globs: | + formal/cbrt/Cbrt512Proof/lean-toolchain + formal/cbrt/Cbrt512Proof/lakefile.toml + formal/cbrt/Cbrt512Proof/lake-manifest.json + formal/cbrt/Cbrt512Proof/**/*.lean + src/utils/512Math.sol + src/utils/FastLogic.sol + src/utils/Panic.sol + src/utils/Ternary.sol + src/utils/UnsafeMath.sol + src/vendor/Clz.sol + src/vendor/Cbrt.sol + src/vendor/Sqrt.sol + src/wrappers/Cbrt512Wrapper.sol + lib/forge-std/src/interfaces/IERC20.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-cbrt512-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Build Cbrt512 proof package after a cache miss + if: steps.cbrt512-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-cbrt512-proof + + sqrt512: + name: 512Math sqrt formal check + needs: + - route + - base + - sqrt + if: needs.route.outputs.sqrt512 == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/sqrt/Sqrt512Proof/lean-toolchain + formal/sqrt/SqrtProof/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Sqrt dependency cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: sqrt + publish: "false" + cache-path: | + formal/sqrt/SqrtProof/.lake/build + formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean + formal/sqrt/SqrtProof/SqrtProof/SqrtYulRuntime.lean + formal/sqrt/SqrtProof/SqrtProof/SqrtYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/sqrt/SqrtProof/lean-toolchain + formal/sqrt/SqrtProof/lakefile.toml + formal/sqrt/SqrtProof/lake-manifest.json + formal/sqrt/SqrtProof/**/*.lean + formal/python/sqrt/**/*.py + src/vendor/Sqrt.sol + src/wrappers/SqrtWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-sqrt-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Restore Sqrt512 package cache + id: sqrt512-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: sqrt512 + publish: "true" + cache-path: | + formal/sqrt/Sqrt512Proof/.lake/build + formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulRuntime.lean + formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + formal/sqrt/SqrtProof/lean-toolchain + formal/sqrt/SqrtProof/lakefile.toml + formal/sqrt/SqrtProof/lake-manifest.json + formal/sqrt/SqrtProof/**/*.lean + formal/python/sqrt/**/*.py + src/vendor/Sqrt.sol + src/wrappers/SqrtWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-sqrt-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + source-hash-globs: | + formal/sqrt/Sqrt512Proof/lean-toolchain + formal/sqrt/Sqrt512Proof/lakefile.toml + formal/sqrt/Sqrt512Proof/lake-manifest.json + formal/sqrt/Sqrt512Proof/**/*.lean + src/utils/512Math.sol + src/utils/FastLogic.sol + src/utils/Panic.sol + src/utils/Ternary.sol + src/utils/UnsafeMath.sol + src/vendor/Clz.sol + src/vendor/Cbrt.sol + src/vendor/Sqrt.sol + src/wrappers/Sqrt512Wrapper.sol + lib/forge-std/src/interfaces/IERC20.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-sqrt512-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Build Sqrt512 proof package after a cache miss + if: steps.sqrt512-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-sqrt512-proof + + ln: + name: Ln.sol formal check + needs: + - route + - base + - common + if: needs.route.outputs.ln == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/ln/LnProof/lean-toolchain + formal/common/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Common dependency cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: common + publish: "false" + cache-path: formal/common/.lake/build + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/common/lean-toolchain + formal/common/lakefile.toml + formal/common/lake-manifest.json + formal/common/Common.lean + formal/common/Common/**/*.lean + .github/actions/build-common-proof/** + + - name: Restore Ln package cache + id: ln-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: ln + publish: "true" + cache-path: | + formal/ln/LnProof/.lake/build + formal/ln/LnProof/LnProof/Cert + formal/ln/LnProof/LnProof/LnYulRuntime.lean + formal/ln/LnProof/LnProof/LnYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + formal/common/lean-toolchain + formal/common/lakefile.toml + formal/common/lake-manifest.json + formal/common/Common.lean + formal/common/Common/**/*.lean + source-hash-globs: | + formal/ln/LnProof/lean-toolchain + formal/ln/LnProof/lakefile.toml + formal/ln/LnProof/lake-manifest.json + formal/ln/LnProof/**/*.lean + src/vendor/Ln.sol + src/utils/Panic.sol + src/wrappers/LnWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-ln-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Build Ln proof package after a cache miss + if: steps.ln-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-ln-proof + + exp: + name: Exp.sol formal check + needs: + - route + - base + - common + - ln + if: needs.route.outputs.exp == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + persist-credentials: false + + - name: Restore the formal base + uses: ./.github/actions/setup-formal + with: + publish: "false" + lean-toolchain-files: | + formal/exp/ExpProof/lean-toolchain + formal/ln/LnProof/lean-toolchain + formal/common/lean-toolchain + formal/yul/lean-toolchain + lib/EVMYulLean/lean-toolchain + + - name: Restore Common dependency cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: common + publish: "false" + cache-path: formal/common/.lake/build + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + source-hash-globs: | + formal/common/lean-toolchain + formal/common/lakefile.toml + formal/common/lake-manifest.json + formal/common/Common.lean + formal/common/Common/**/*.lean + .github/actions/build-common-proof/** + + - name: Restore Ln dependency cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: ln + publish: "false" + cache-path: | + formal/ln/LnProof/.lake/build + formal/ln/LnProof/LnProof/Cert + formal/ln/LnProof/LnProof/LnYulRuntime.lean + formal/ln/LnProof/LnProof/LnYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + formal/common/lean-toolchain + formal/common/lakefile.toml + formal/common/lake-manifest.json + formal/common/Common.lean + formal/common/Common/**/*.lean + source-hash-globs: | + formal/ln/LnProof/lean-toolchain + formal/ln/LnProof/lakefile.toml + formal/ln/LnProof/lake-manifest.json + formal/ln/LnProof/**/*.lean + src/vendor/Ln.sol + src/utils/Panic.sol + src/wrappers/LnWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-ln-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Restore Exp package cache + id: exp-cache + uses: ./.github/actions/cache-formal-package + with: + cache-name: exp + publish: "true" + cache-path: | + formal/exp/ExpProof/.lake/build + formal/exp/ExpProof/ExpProof/Cert + formal/exp/ExpProof/ExpProof/ExpYulRuntime.lean + formal/exp/ExpProof/ExpProof/ExpYulProof.lean + dependency-hash-globs: | + formal/yul/lean-toolchain + formal/yul/lakefile.toml + formal/yul/lake-manifest.json + formal/yul/FormalYul.lean + formal/yul/YulImporter.lean + formal/yul/FormalYul/**/*.lean + lib/EVMYulLean/lean-toolchain + lib/EVMYulLean/lakefile.lean + lib/EVMYulLean/lake-manifest.json + lib/EVMYulLean/**/*.lean + formal/common/lean-toolchain + formal/common/lakefile.toml + formal/common/lake-manifest.json + formal/common/Common.lean + formal/common/Common/**/*.lean + formal/ln/LnProof/lean-toolchain + formal/ln/LnProof/lakefile.toml + formal/ln/LnProof/lake-manifest.json + formal/ln/LnProof/**/*.lean + src/vendor/Ln.sol + src/utils/Panic.sol + src/wrappers/LnWrapper.sol + .github/actions/build-ln-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + source-hash-globs: | + formal/exp/ExpProof/lean-toolchain + formal/exp/ExpProof/lakefile.toml + formal/exp/ExpProof/lake-manifest.json + formal/exp/ExpProof/**/*.lean + src/vendor/Exp.sol + src/vendor/Clz.sol + src/utils/FastLogic.sol + src/utils/Panic.sol + src/wrappers/ExpWrapper.sol + formal/yul/generate_from_forge.sh + foundry.toml + remappings.txt + .gitmodules + .github/actions/build-exp-proof/** + .github/actions/check-generated-sources/** + .github/actions/fetch-lean-cache/** + + - name: Build Exp proof package after a cache miss + if: steps.exp-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/build-exp-proof diff --git a/.github/workflows/ln-formal.yml b/.github/workflows/ln-formal.yml deleted file mode 100644 index 2d5b1e611..000000000 --- a/.github/workflows/ln-formal.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Ln.sol Formal Check - -on: - push: - branches: - - master - paths: - - src/vendor/Ln.sol - - src/wrappers/LnWrapper.sol - - formal/ln/** - - formal/common/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/ln-formal.yml - - .github/actions/build-ln-proof/action.yml - pull_request: - paths: - - src/vendor/Ln.sol - - src/wrappers/LnWrapper.sol - - formal/ln/** - - formal/common/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/ln-formal.yml - - .github/actions/build-ln-proof/action.yml - -jobs: - ln-formal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Set up the formal toolchain - uses: ./.github/actions/setup-formal - with: - lean-toolchain-files: formal/ln/LnProof/lean-toolchain - cache-name: ln-formal - cache-paths: | - formal/common/.lake/build - formal/ln/LnProof/.lake/build - cache-hash-globs: | - formal/common/lakefile.toml - formal/common/lake-manifest.json - formal/common/**/*.lean - formal/ln/LnProof/lakefile.toml - formal/ln/LnProof/lake-manifest.json - formal/ln/LnProof/**/*.lean - - - name: Build Ln proof package - uses: ./.github/actions/build-ln-proof diff --git a/.github/workflows/sqrt-formal.yml b/.github/workflows/sqrt-formal.yml deleted file mode 100644 index 961f0666f..000000000 --- a/.github/workflows/sqrt-formal.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Sqrt.sol Formal Check - -on: - push: - branches: - - master - paths: - - src/vendor/Sqrt.sol - - src/wrappers/SqrtWrapper.sol - - formal/sqrt/** - - formal/python/sqrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/sqrt-formal.yml - pull_request: - paths: - - src/vendor/Sqrt.sol - - src/wrappers/SqrtWrapper.sol - - formal/sqrt/** - - formal/python/sqrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/sqrt-formal.yml - -jobs: - sqrt-formal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Set up the formal toolchain - uses: ./.github/actions/setup-formal - with: - lean-toolchain-files: formal/sqrt/SqrtProof/lean-toolchain - cache-name: sqrt-formal - cache-paths: | - formal/sqrt/SqrtProof/.lake/build - cache-hash-globs: | - formal/sqrt/SqrtProof/lakefile.toml - formal/sqrt/SqrtProof/lake-manifest.json - formal/sqrt/SqrtProof/**/*.lean - - - name: Generate EVMYulLean artifacts from compiled SqrtWrapper Yul IR - run: | - ./formal/yul/generate_from_forge.sh \ - sqrt \ - src/wrappers/SqrtWrapper.sol:SqrtWrapper \ - formal/sqrt/SqrtProof/SqrtProof/SqrtYul.lean \ - 0.8.34 - - - name: Generate finite certificate from Python generator - run: | - python3 formal/python/sqrt/generate_sqrt_cert.py \ - --output formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean - - - name: Fetch proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/sqrt/SqrtProof - - - name: Build Sqrt proof package - working-directory: formal/sqrt/SqrtProof - run: lake build diff --git a/.github/workflows/sqrt512-formal.yml b/.github/workflows/sqrt512-formal.yml deleted file mode 100644 index 98d5e798b..000000000 --- a/.github/workflows/sqrt512-formal.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: 512Math sqrt Formal Check - -on: - push: - branches: - - master - paths: - - src/utils/512Math.sol - - src/utils/FastLogic.sol - - src/utils/Panic.sol - - src/utils/Ternary.sol - - src/utils/UnsafeMath.sol - - src/vendor/Clz.sol - - src/vendor/Cbrt.sol - - src/vendor/Sqrt.sol - - src/wrappers/Sqrt512Wrapper.sol - - formal/sqrt/** - - formal/python/sqrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/sqrt512-formal.yml - pull_request: - paths: - - src/utils/512Math.sol - - src/utils/FastLogic.sol - - src/utils/Panic.sol - - src/utils/Ternary.sol - - src/utils/UnsafeMath.sol - - src/vendor/Clz.sol - - src/vendor/Cbrt.sol - - src/vendor/Sqrt.sol - - src/wrappers/Sqrt512Wrapper.sol - - formal/sqrt/** - - formal/python/sqrt/** - - formal/yul/** - - foundry.toml - - remappings.txt - - .gitmodules - - lib/EVMYulLean - - .github/actions/setup-formal/** - - .github/actions/fetch-lean-cache/** - - .github/workflows/sqrt512-formal.yml - -jobs: - sqrt512-formal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Set up the formal toolchain - uses: ./.github/actions/setup-formal - with: - lean-toolchain-files: | - formal/sqrt/Sqrt512Proof/lean-toolchain - formal/sqrt/SqrtProof/lean-toolchain - cache-name: sqrt512-formal - cache-paths: | - formal/sqrt/SqrtProof/.lake/build - formal/sqrt/Sqrt512Proof/.lake/build - cache-hash-globs: | - formal/sqrt/SqrtProof/lakefile.toml - formal/sqrt/SqrtProof/lake-manifest.json - formal/sqrt/Sqrt512Proof/lakefile.toml - formal/sqrt/Sqrt512Proof/lake-manifest.json - formal/sqrt/SqrtProof/**/*.lean - formal/sqrt/Sqrt512Proof/**/*.lean - - - name: Generate 512-bit EVMYulLean artifacts from compiled Sqrt512Wrapper Yul IR - run: | - ./formal/yul/generate_from_forge.sh \ - sqrt512 \ - src/wrappers/Sqrt512Wrapper.sol:Sqrt512Wrapper \ - formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512Yul.lean \ - 0.8.34 - - - name: Generate 256-bit sqrt finite certificate (SqrtProof dependency) from Python generator - run: | - python3 formal/python/sqrt/generate_sqrt_cert.py \ - --output formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean - - - name: Fetch proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/sqrt/Sqrt512Proof - - - name: Build Sqrt512 proof package - working-directory: formal/sqrt/Sqrt512Proof - run: lake build diff --git a/formal/README.md b/formal/README.md index 9c76dcf44..9f607accd 100644 --- a/formal/README.md +++ b/formal/README.md @@ -1,273 +1,202 @@ # Formal Verification -Machine-checked Lean 4 correctness proofs for root math libraries in 0x Settler. The public runtime correctness theorem surface is pinned to Lean's standard axioms `propext`, `Classical.choice`, and `Quot.sound`. This is enforced in CI by a `#guard_msgs` axiom gate (in each proof's `AxiomCheck.lean`, or `Theorems.lean` for `ln` and `exp`); the build fails if any gated theorem's axiom set changes. - -## Scope - -| Proof | Solidity source | What is proved | -|-------|----------------|----------------| -| `sqrt/SqrtProof` | `src/vendor/Sqrt.sol` | `_sqrt`, `sqrt`, `sqrtUp` correct on uint256 | -| `sqrt/Sqrt512Proof` | `src/utils/512Math.sol` | `_sqrt` (512-bit) correct: `sqrt(x_hi * 2^256 + x_lo) = natSqrt(x)` | -| `cbrt/CbrtProof` | `src/vendor/Cbrt.sol` | `_cbrt`, `cbrt`, `cbrtUp` correct on uint256 | -| `cbrt/Cbrt512Proof` | `src/utils/512Math.sol` | `_cbrt` (512-bit) correct: `cbrt(x_hi * 2^256 + x_lo) = icbrt(x)` | -| `ln/LnProof` | `src/vendor/Ln.sol` | `lnWadToRay`, `lnWad` correct vs. `Real.log`, monotone, with a 1.6986-ulp error bound | -| `exp/ExpProof` | `src/vendor/Exp.sol` | `expRayToWad` correct vs. `Real.exp`: never over, floor-or-one-less, monotone, and the central `lnWadToRay` round trip. `mulExpRay` correct vs. `abs(y)·Real.exp(x/10²⁷)`: exact accept/revert domains (also stated in octave vocabulary), value path to the compiled tree, the signed two-unit bracket with floor membership over the whole accepted domain, and monotonicity in each argument and jointly | - -## Method - -1. **Algebraic lemmas** prove one-step safety and correction logic (Babylonian / Newton-Raphson steps). -2. **Finite domain certificates** (auto-generated by Lean and Python scripts) cover all uint256 octaves with `by decide` proofs. -3. **The `formal/yul` Lake importer** consumes `forge inspect ... ir` output and emits ignored EVMYulLean runtime/proof modules. -4. **Runtime bridge modules** execute ABI calls through EVMYulLean against the Yul emitted by solc. The implementation is Solidity; Lean proof machinery consumes the generated Yul artifacts rather than a second hand-maintained model. - -## Tactic discipline over the runtime trees - -The runtime normal forms (`evTree`, `r0MulTree`, `mulShiftTree`, …) are deeply nested `evm*` -application terms whose subterms repeat: each Horner stage mentions its argument several times, -the squared argument mentions the reduced argument twice, and so on. In memory these are shared -DAGs, but any procedure that reduces or re-traverses them without sharing sees a syntactic -expansion exponential in nesting depth. Tactic preprocessing that sends atoms through `whnf` or -rebuilds them — `omega`'s atom collection, `positivity`, `nlinarith`'s ring normalization — -crashes the elaborator or kernel with a stack overflow or "deep recursion detected" when a -tree-valued term is in scope, even on goals that are trivially linear in the tree atoms. A -tree-valued `Nat` in the exponent of a `pow` fed to such a tactic fails the same way. - -The mitigation is opacification: name every tree-valued word before doing arithmetic near it — -`set w := … with hw` followed by `clear_value w` — so the atom is an opaque local with no value -to unfold, or close the goal with term-level lemmas (`lt_of_le_of_lt`, `Nat.add_le_add`, -`mul_le_mul_of_nonneg_left`, `linarith` with an explicit hypothesis list) instead of the -whnf-hungry tactics. Facts that need a tree's definition (an `rfl` unfolding, an `evmDiv`/`evmMul` -transport) must be established *before* the `clear_value`; everything downstream works on the -opaque name. The `Mul/*` modules and the scale-symbolic `Floor` lemmas follow this discipline -throughout; `omega` on opaque locals and on literals remains safe and is used freely. - -## Deriving the fixed-point rational coefficients - -The polynomial/rational coefficients in `Ln.sol` and `Exp.sol` (and their error margins) -come from a three-step pipeline. Exact minimax fitting alone is not enough: rounding an -optimal real-coefficient rational at the mixed fixed-point staircase bases re-rolls ten -independent quantization residuals and typically triples the realized error, so the -integer low bits are re-optimized jointly after rounding. - -1. **Converged weighted rational Remez** ([Bloemen's scheme](https://xn--2-umb.com/22/approximation/)): - fit the target under the weight that the consumer's error metric induces. For - `expRayToWad`, `Od(v)/Ev(v) ≈ tanh(√v/2)/√v` on `v ∈ [0, (ln2/2)²]` under - `w(v) = 2√v·cosh²(√v/2)`, the pushforward of the relative error of - `(Ev + t·Od)/(Ev − t·Od)` against `exp(t)`. Each iteration solves the linearized - equioscillation system at the current alternation nodes, closing on the level `e` - with a root find: - - ```python - # nodes x[i], signs s[i], weights w[i]; unknowns: p, q (q0 = 1), level e - # p(x_i) − (f(x_i) + s_i·e/w_i)·(q(x_i) − 1) = f(x_i) + s_i·e/w_i - e = findroot(lambda e: solve_linear(e)[2] - e, e0) # e_out = e_in at the optimum - ``` - - Iterate node exchange until the *coefficients* converge, not merely the level: the - leading coefficient lies along a near-null direction of the objective (its monomial - contributes ~`4e-17` of the polynomial's value on the domain) and settles orders of - magnitude later than `e`. - -2. **Staircase quantization**: round each real coefficient to nearest at its staircase - basis — the widest basis whose literal fits the chosen byte width, with the leading - (monic-stage) coefficient carried at `v`'s own basis so that stage needs no - renormalizing shift. - -3. **Joint low-bit refinement**: the realized error is linear in per-coefficient grain - offsets `n_i`, so precompute the base error curve and one sensitivity curve per - coefficient once in high precision, then search the integer offsets in fast float - arithmetic: - - ```python - err(t; n) = base(t) + Σ_i n_i·φ_i(t), φ_i(t) = ∂ê/∂c_i · 2^(126−b_i) # Q126 ulps - minimize over n ∈ ℤ^10: max(max_t err, −min_t err) # coordinate + pair descent - ``` - - Low-degree coefficients dominate (one grain of a Q87 constant term moves the quotient - by ~0.3–0.8 ulp); the descent needs paired moves because single-coefficient steps are - too coarse near the optimum. The refined ensemble equioscillates in the max metric — - for `Exp.sol`, at ±0.019 ulp against plain rounding's ~0.35 — which is what lets the - certificate's dyadic nudge (and with it the subtracted output margin) tighten. - -Every step is re-verified against the exact target at ≥60 digits on a dense grid, and -the resulting envelope must clear the proof's cut-certificate nudge with slack before -the margin constant is derived from the error budget. - -## Widening the certified range: measure, attribute, rebalance - -The supported range of a fixed-point kernel ends at the octave where the deficit envelope -(the certified worst-case underestimation of the pre-floor accumulator, doubling per octave) -reaches one output ulp. When a target octave misses by a few tens of percent, the -coefficients are usually not the lever. The procedure that closes the gap, in order: - -1. **Measure the true envelope.** Run the integer kernel beside its exact-rational shadow - (the same Horner evaluation with every renormalizing floor replaced by exact rational - arithmetic) over adversarial sweeps — every octave seam ±2 plus large random samples — - and compare the supremum against the certified bound. This splits the certified envelope - into real error versus derivational padding. For `expRayToWad` the split is 5.18 true - against 6.21 certified (2⁶⁸-grid units): the bound is nearly tight, so no re-derivation - alone closes a 30% gap — and neither does a coefficient refit, because with ~2¹²¹ - reachable grid arguments, near-worst alignment of the per-stage floor residuals exists - for essentially any choice of coefficient low bits, and re-centering the residuals only - trades under-side deficit for over-side margin one-for-one against an integer-quantized - margin. - -2. **Attribute per truncation site.** Re-run the shadow with each floor exactified one at a - time. The deficit is rarely uniform: in `expRayToWad`, the odd chain's closing stage and - the `t·Od` shift own nearly the whole supremum (5.0 and 4.0 of the 5.18) because odd-side - errors enter the numerator and denominator antisymmetrically and are amplified by - ~2t/den, while the even chain contributes ≤ 1 unit per site and every early stage is - negligible — the staircase already carries more precision there than the closing stages - consume. - -3. **Rebalance bases toward the dominant sites.** The 256-bit fits (the dividend, `t·Od`, - `t²`, and the monic leading stage) form a closed budget of bits; move them from where the - attribution says they are cheap to where they are dear. For `expRayToWad`, one bit moves - from the output grid into the closing bases — numerator at Q89, scale 10¹⁸·2⁶⁷, `t` at - Q129 in the freed `t·Od` headroom — with every coefficient unchanged except the even - closing constant doubling exactly (preserving `Ev(0) = 2·Od(0)`). The true envelope drops - 2.5× and the margin requantizes from 3/16 to 1/4 ulp at the edge octave, at identical - runtime gas: this is what extends the supported range through k = 65. - -4. **Certify piecewise where global worst-cases refuse.** The residual derivational padding - lives in co-occurrence assumptions — the worst floor fraction, the largest |t|, and the - smallest denominator cannot coincide, but a domain-global bound must pretend they do. The - certificate machinery that already bounds the granularity piecewise (`Common.GenCover` - walks over the 32-piece `v` table) extends to the truncation envelope: add per-piece caps - for the amplification factors (|t|, the denominator floor, the even accumulator) and - aggregate the per-stage residuals with per-piece weights. - -The order matters: measurement before design (step 1 rules out the tempting-but-useless -refit), attribution before rebalancing (step 2 finds the bit that buys 2.5× rather than one -that buys nothing), and rebalancing before certification (step 4's piecewise machinery is -only worth building once the true envelope actually fits under the target). - -## Settling the negative: the same instruments prove a kernel optimal - -The procedure pays off equally when the answer is "leave it alone" — but only if the -negative is driven to an exact floor, so it stays settled. `lnWadToRay` is the worked -example: approximation-dominated on both budget sides, no amplified truncation site, and -already certified per exponent. Five instruments close it: - -1. **Fit the constrained ideal, not the unconstrained one.** The minimax floor must carry - every structural pin the bytecode does. `Ln.sol`'s (4,5) rational shares its constant - term between numerator and denominator (one 13-byte literal serves both, `p(0) = −q(0)`); - the unconstrained minimax on its domain and weight is 0.2735 ulp, but with the shared - constant pinned it is 0.32346 — and the deployed integer staircase measures 0.32366, - 0.0002 above the floor with its over-side peak on it. A deployed-vs-unconstrained gap - read as "harvestable quantization" can be, as here, the deliberate bytecode price of the - structure. - -2. **Price shorter forms by the decay law.** Adjacent coefficient counts fit on a geometric - decay (~534× per coefficient for this family: 0.2735 → 146 → 7.8·10⁴ for (4,5) → (4,4) → - (3,4)), so measuring two types prices every type — "would a shorter rational fit?" - becomes arithmetic against the freeable budget instead of a fitting project. - -3. **Search the lattice under the deliverable's objective.** Two-sided fit width is the - wrong objective for a floored, margined kernel: what the documented bound consumes is - over-side need plus under-side need at a fixed margin word, and octave-dependent terms - (the mantissa-truncation gap, k > 0 only) attach to wherever the under-peak sits. A - width-optimal coefficient neighbor can worsen the real bound by migrating the under-peak - into the worst octave. Joint optimality is established when multi-start coordinate - descent under the correct objective returns the deployed lattice point exactly. - -4. **Solve the certificate floor where the constant enters linearly.** An envelope constant - that appears linearly in the cover-cell certificates has an exactly computable per-cell - feasibility minimum. In `LnProof`, the floor-side envelope constant sits at that minimum - to the unit — one unit lower and the certificate polynomial goes negative on a plateau - spanning the whole [2⁹⁵, 2⁹⁵ + 2⁶⁰] edge of the mantissa domain — so the margin word is - pinned to the band it occupies, and no cover refinement can move it: the polynomial - fails, not the cover. - -5. **Treat sweep suprema as lower bounds.** Over a plateau of 2⁶⁰ mantissas no sweep is - exhaustive; the true supremum creeps toward the certificate's worst-case truncation - model. The ~0.010-ulp gap between the sampled over-side peak (0.32797) and the - certificate floor (0.3382) is the price of the global truncation model, not padding — - the mirror of step 1's alignment argument: with astronomically many reachable arguments, - near-worst residual alignment exists. - -When the binding constraint is architectural — here, the global per-stage slop model, whose -replacement by per-stage truncation windows would buy a few thousandths of a ulp for a full -re-derivation of the floor proof's bracket and assembly layers — the deliverable is the -recorded reopening condition, not the change. - -## Build - -Generated EVMYulLean artifacts (`*YulRuntime.lean`, `*YulProof.lean`) are `.gitignore`d and regenerated in CI. See `.github/workflows/*-formal.yml` for the canonical build steps. - -Build the shared importer once before generating runtime/proof modules: - -```bash -lake -d formal/yul build yul_importer +The `formal` tree contains Lean 4 proofs for the fixed-point and wide-integer +math libraries used by Settler. Solidity is the implementation source of +truth. Runtime proofs consume Yul emitted from the Solidity build; they do not +maintain a second executable implementation in Lean. + +## Verified interfaces + +| Proof package | Solidity source | Verified surface | +|---|---|---| +| `sqrt/SqrtProof` | `src/vendor/Sqrt.sol` | `_sqrt`, `sqrt`, and `sqrtUp` on `uint256` | +| `sqrt/Sqrt512Proof` | `src/utils/512Math.sol` | 512-bit square root against `Nat.sqrt` | +| `cbrt/CbrtProof` | `src/vendor/Cbrt.sol` | `_cbrt`, `cbrt`, and `cbrtUp` on `uint256` | +| `cbrt/Cbrt512Proof` | `src/utils/512Math.sol` | 512-bit cube root against the integer cube-root specification | +| `ln/LnProof` | `src/vendor/Ln.sol` | `lnWadToRay` and `lnWad` against `Real.log`, including domains, error, and monotonicity | +| `exp/ExpProof` | `src/vendor/Exp.sol` | `expRayToWad` and `mulExpRay` against `Real.exp`, including domains, error brackets, monotonicity, and the central logarithm round trip | + +## Package architecture + +The transitive reduction of the shared and proof-specific package graph is: + +```text +EVMYulLean ──> FormalYul ──> Common ──> LnProof ──> ExpProof + │ + ├───────────────> SqrtProof ──> Sqrt512Proof + │ + └───────────────> CbrtProof ──> Cbrt512Proof ``` -```bash -# --- 256-bit sqrt --- -./formal/yul/generate_from_forge.sh \ - sqrt \ - src/wrappers/SqrtWrapper.sol:SqrtWrapper \ - formal/sqrt/SqrtProof/SqrtProof/SqrtYul.lean - -cd formal/sqrt/SqrtProof && \ - lake build SqrtProof.SqrtYulRuntime SqrtProof.SqrtYulProof - -# --- 512-bit sqrt --- -./formal/yul/generate_from_forge.sh \ - sqrt512 \ - src/wrappers/Sqrt512Wrapper.sol:Sqrt512Wrapper \ - formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512Yul.lean \ - 0.8.34 - -cd formal/sqrt/Sqrt512Proof && \ - lake build Sqrt512Proof.Sqrt512YulRuntime Sqrt512Proof.Sqrt512YulProof - -# --- cbrt --- -./formal/yul/generate_from_forge.sh \ - cbrt \ - src/wrappers/CbrtWrapper.sol:CbrtWrapper \ - formal/cbrt/CbrtProof/CbrtProof/CbrtYul.lean - -cd formal/cbrt/CbrtProof && \ - lake build CbrtProof.CbrtYulRuntime CbrtProof.CbrtYulProof - -# --- 512-bit cbrt --- -./formal/yul/generate_from_forge.sh \ - cbrt512 \ - src/wrappers/Cbrt512Wrapper.sol:Cbrt512Wrapper \ - formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Yul.lean \ - 0.8.34 - -cd formal/cbrt/Cbrt512Proof && \ - lake build Cbrt512Proof.Cbrt512YulRuntime Cbrt512Proof.Cbrt512YulProof - -# --- ln --- -./formal/yul/generate_from_forge.sh \ - ln \ - src/wrappers/LnWrapper.sol:LnWrapper \ - formal/ln/LnProof/LnProof/LnYul.lean \ - 0.8.34 - -cd formal/ln/LnProof && \ - lake build LnProof.LnYulRuntime LnProof.LnYulProof && \ - lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts Common.GenCover && \ - lake env lean GenFloorCertLit.lean && \ - lake build LnProof.Cert.FloorCertLit && \ - lake env lean GenCover.lean && \ - lake env lean GenErr1.lean && \ - lake build LnProof.Error.Core && \ - lake env lean GenErrLit.lean && \ - lake build - -# --- exp (requires a fully built LnProof for the round trip: run the ln block first) --- -./formal/yul/generate_from_forge.sh \ - exp \ - src/wrappers/ExpWrapper.sol:ExpWrapper \ - formal/exp/ExpProof/ExpProof/ExpYul.lean \ - 0.8.34 - -cd formal/exp/ExpProof && \ - lake build ExpProof.ExpYulRuntime ExpProof.ExpYulProof && \ - lake build ExpProof.Floor.CertDefsV ExpProof.Floor.GranPieces Common.Foundation.KroneckerShift Common.GenCover && \ - lake env lean GenExpVLit.lean && \ - lake build +`FormalYul` supplies the generated-Yul runtime model, interpreter bridges, and +preservation lemmas. `Common` contains proof infrastructure shared by the +transcendental packages, including exact polynomial evaluation and finite +interval certificate checkers. `ExpProof` imports `LnProof` because its public +surface includes a round-trip theorem. + +Each runtime proof follows the same data flow: + +1. Forge asks the pinned solc version for the wrapper contract's Yul IR. +2. The Yul importer emits `*YulRuntime.lean` and `*YulProof.lean` modules. +3. Arithmetic modules relate the emitted word-level program to integer and + real-number specifications. +4. The package root imports the public theorems and checks their axiom sets. + +Generated runtime modules and generated certificate modules are ignored by +Git. On a package-cache miss, CI clears their declared output surfaces, +regenerates them once, and builds the package. Exact package-cache hits skip +generation and the package build. Package caches contain the generated sources +beside their Lake outputs, so a dependent job receives the source corresponding +to each cached `.olean` file. + +## Trust model + +The public theorem surface is accepted by the Lean kernel under the standard +axioms `propext`, `Classical.choice`, and `Quot.sound`. Each package has an +axiom gate in `AxiomCheck.lean` or `Theorems.lean`; the build fails if a gated +theorem acquires another axiom. + +The trusted path consists of: + +- the Lean kernel and the definitions of the mathematical specifications; +- the EVM/Yul semantics used by EVMYulLean and the bridge from emitted Yul to + those semantics; +- the pinned Solidity compiler and Forge used to obtain Yul IR from Solidity + source; +- the GitHub Actions runner, action implementations, artifact and cache + services, and Mathlib cache distribution used by CI. + +Certificate generators, interval splitters, Python scripts, and coefficient +search programs are proof producers, not trusted proof checkers. Their output +contains literals, interval endpoints, or algebraic witnesses. Lean recomputes +the relevant polynomial identities, range conditions, and sign checks in the +kernel. A malformed certificate therefore fails to elaborate or fails its +theorem. + +On a cache miss or non-exact prefix restore, CI removes each declared generated +file and the contents of each declared generated-only directory. It runs the +generator once, requires every declared output to be nonempty, requires tracked +sources to remain unchanged, and then builds the package. A malformed +certificate fails when Lean consumes it. + +Exact package-cache hits are trusted proof artifacts: CI does not rerun their +generators or Lean package builds. Build caches and the cache service are +therefore part of the CI supply chain. Cache keys cover the package's semantic +inputs, while Lake hashes module sources, options, imports, and imported +outputs when producing a fresh artifact. + +When its ignored source directories are absent, EVMYulLean's Lake build clones +the default branches of `sha-2` and `SHA3IUF`. Their resolved commits are not +part of the formal-tool cache key. A cold publisher therefore resolves those +branches, and subsequent jobs trust the formal-tool artifact it publishes. + +## CI and cache boundaries + +The unified formal workflow keeps the large Mathlib and Lake dependency outputs +in a cache keyed only by the pinned toolchain and dependency manifests. A +separate formal-tool cache contains `FormalYul` and EVMYulLean outputs and is +keyed by their sources as well as that dependency configuration. Every proof +package has a separate cache. A package's exact key includes: + +- the source hash of each direct dependency; +- its Lake configuration and Lean sources; +- the Solidity, wrapper, and Forge inputs that determine its emitted Yul; +- the package-local composite action that contains its generator invocations, + plus the shared setup, package-cache, generation, and dependency-cache + actions involved in its build. + +One base job owns the dependency and formal-tool cache keys. Each proof package +job is the sole publisher of its package key. A publisher may restore an older +prefix, regenerate on the resulting non-exact hit, and save the exact key after +a successful build. Downstream jobs start through `needs`, restore only the +exact key produced by their publisher, and fail if it is unavailable. + +The checked-in path router selects affected packages and closes the package +dependencies before jobs start. Thus an Exp change schedules `Common`, +`LnProof`, and `ExpProof`; a 512-bit proof schedules its 256-bit dependency. +Unchanged exact package keys skip their package work. Changes to shared formal +tooling schedule every package. + +The 512-bit generation keys include the exact forge-std `IERC20` interface +pulled into the compiled source closure through `Ternary.sol`. + +The canonical job graph and pinned compiler versions are in +`.github/workflows/formal.yml` and the composite actions under +`.github/actions/`. Local runs should execute the same generation steps before +`lake build`. + +## Current certificate domain + +The shared finite-cover machinery proves nonnegativity of an integer +polynomial on a compact integer interval. Rational inequalities use it after +clearing a denominator whose sign has been proved separately. Transcendental +inequalities use rational Taylor bounds to reduce the remaining obligation to +polynomial signs. Piecewise proofs partition the compact domain and check each +cell independently. + +### Certificate backend interface + +Every polynomial-sign backend exports the same proposition: + +```lean +def NonnegOn (cs : List Int) (lo hi : Int) : Prop := + ∀ x : Int, lo ≤ x → x ≤ hi → 0 ≤ evalPoly cs x ``` + +The interval-Horner/Kronecker backend shifts the polynomial to each cell's +left endpoint, packs the candidate shifted coefficients at radix `2^B`, and +checks coefficient bounds plus one exact evaluation identity. Interval Horner +then proves the packed shifted polynomial nonnegative throughout the cell. +`checkCoverK_nonnegOn` turns an accepted cell walk into `NonnegOn` for the +original polynomial. + +The Bernstein backend represents the degree-scaled polynomial as a sum of +Bernstein basis polynomials. `checkBernsteinKWithWitness` checks that the +weights are nonnegative, both polynomial coefficient norms fit below the +chosen radix, and one exact evaluation identity establishes equality of the +two integer polynomials. `checkBernsteinKWithWitness_nonnegOn` turns an +accepted witness into the same `NonnegOn` proposition. Consumers therefore do +not depend on which checker produced a cell theorem. + +A new backend integrates through four concrete pieces: + +1. Define a Boolean checker whose inputs contain every untrusted witness. +2. Prove that a `true` checker result implies `NonnegOn` without adding an + axiom or trusting the witness producer. +3. Provide a `CellEmitter` and a generator that emit the checker theorem and + its `NonnegOn` consequence for each cell. +4. Add an executable example showing that at least one malformed witness is + rejected. `Common.CertificateExamples` contains the corresponding + Bernstein examples for missing weights, a reversed interval, and an + insufficient identity width. + +This machinery directly covers: + +- univariate integer or rational-polynomial inequalities on closed intervals; +- finite piecewise envelopes with exact rational endpoints; +- transcendental bounds after an explicit polynomial remainder theorem; +- word-level algorithms after floors, divisions, and signed-word operations + have been bridged to suitable integer inequalities. + +It does not by itself retain correlations among several variables, quotient +remainders, modular residues, or successive floor errors. Those relations must +be preserved in the theorem statement or discharged by another certificate +system. + +## Runtime-tree elaboration discipline + +Runtime normal forms such as `evTree`, `r0MulTree`, and `mulShiftTree` are +shared DAGs represented by deeply nested `evm*` terms. Tactics that repeatedly +normalize those terms can traverse an exponentially larger syntax tree. + +Arithmetic proofs name a tree-valued word before invoking such tactics: + +```lean +set w := runtimeTree x with hw +clear_value w +``` + +Facts requiring the definition are established before `clear_value`; later +steps reason about the opaque local. Term-level order lemmas or tactics with an +explicit, small hypothesis set are used where general preprocessing would +unfold the runtime tree. From 2b89728ddc30af17953c26da8348025710c32a9f Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 01:40:31 +0200 Subject: [PATCH 083/107] Narrow mulExpRay multiplier to int128 Canonicalize the multiplier before assembly reads and carry the int128 ABI domain through generated-Yul proofs and tests. Co-Authored-By: OpenAI Codex --- formal/exp/ExpProof/ExpProof/Mul.lean | 9 +- formal/exp/ExpProof/ExpProof/Mul/Accum.lean | 2 +- formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 19 ++- formal/exp/ExpProof/ExpProof/Mul/Joint.lean | 37 +++--- formal/exp/ExpProof/ExpProof/Mul/Shell.lean | 20 ++-- .../exp/ExpProof/ExpProof/Mul/Transport.lean | 3 +- formal/exp/ExpProof/ExpProof/Mul/XMono.lean | 39 ++++--- formal/exp/ExpProof/ExpProof/Mul/YMono.lean | 42 ++++--- .../ExpProof/ExpProof/Seam/Dispatcher.lean | 109 ++++++++++++------ .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 42 +++++++ .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 27 +++-- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 41 ++++--- formal/exp/ExpProof/ExpProof/Theorems.lean | 27 ++--- formal/yul/YulImporter.lean | 4 +- formal/yul/generate_from_forge.sh | 2 +- src/vendor/Exp.sol | 8 +- src/wrappers/ExpWrapper.sol | 2 +- test/0.8.34/Exp.t.sol | 62 ++++++---- 18 files changed, 321 insertions(+), 174 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index 8b2e8a889..2246a82c0 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -60,7 +60,8 @@ theorem mulExpRay_run_bracket_zero_of_run {x : Nat} theorem run_mul_exp_ray_evm_zero_of_guard (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : run_mul_exp_ray_evm 0 x = .ok 0 := by - simpa [mulExpTree_zero] using run_mul_exp_ray_evm_eq_tree_of_guard 0 x hguard + simpa [mulExpTree_zero] using + run_mul_exp_ray_evm_eq_tree_of_guard 0 x int128CalldataWord_zero.2 hguard /-- The compiled runtime satisfies the public bracket spec at zero magnitude whenever the guard accepts. -/ @@ -71,12 +72,14 @@ theorem mulExpRay_run_bracket_zero (x : Nat) (hguard : mulExpGuardTree 0 x = 0) /-- **Value path on the domain.** Accepted inputs return the compiled arithmetic tree. -/ theorem run_mul_exp_ray_evm_eq_tree {y x : Nat} (h : MulExpRayValueDomain y x) : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := - run_mul_exp_ray_evm_eq_tree_of_guard y x ((valueDomain_iff_guard_eq_zero h.1).mp h) + run_mul_exp_ray_evm_eq_tree_of_guard y x h.1.1.2 + ((valueDomain_iff_guard_eq_zero h.1).mp h) /-- **Panic revert.** Rejected inputs revert. -/ theorem run_mul_exp_ray_evm_revert {y x : Nat} (h : MulExpRayPanicDomain y x) : run_mul_exp_ray_evm y x = .error "revert" := - run_mul_exp_ray_evm_revert_of_guard y x ((panicDomain_iff_guard_eq_one h.1).mp h) + run_mul_exp_ray_evm_revert_of_guard y x h.1.1.2 + ((panicDomain_iff_guard_eq_one h.1).mp h) /-- The `y = 10^18` magnitude target is the existing `expRayToWad` target. -/ theorem mulExpRayMagnitudeTarget_wad (x : Int) : diff --git a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean index 04c78e676..d038e75b5 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean @@ -292,7 +292,7 @@ theorem mulExpRay_run_bracket {y x : Nat} (h : MulExpRayValueDomain y x) : have hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ exact ⟨mulExpTree y x, hrun, - mulExpTree_bracket_live hy hx (by omega) habs hx0 hWx hlive⟩ + mulExpTree_bracket_live hy.1 hx (by omega) habs hx0 hWx hlive⟩ /-! ## Floor membership and the small-target pin -/ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean index d4f1b446d..ed3990c1a 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -18,9 +18,26 @@ open FormalYul.Preservation set_option maxRecDepth 100000 +/-- A canonical ABI word for an `int128` argument. -/ +def Int128CalldataWord (y : Nat) : Prop := + y < 2 ^ 256 ∧ + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y + +theorem int128CalldataWord_zero : Int128CalldataWord 0 := by + unfold Int128CalldataWord + decide + +theorem int128CalldataWord_scaleMax : Int128CalldataWord scaleMax := by + unfold Int128CalldataWord + decide + +theorem int128CalldataWord_min : Int128CalldataWord (2 ^ 256 - 2 ^ 127) := by + unfold Int128CalldataWord + decide + /-- ABI words transported into this proof layer. -/ def MulExpRayCanonical (y x : Nat) : Prop := - y < 2 ^ 256 ∧ x < 2 ^ 256 + Int128CalldataWord y ∧ x < 2 ^ 256 /-- The exact successful-input domain induced by the implementation guard. -/ def MulExpRayValueDomain (y x : Nat) : Prop := diff --git a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean index bc15ba8c0..446cfbddb 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean @@ -39,7 +39,7 @@ theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleMax) : · exact scaleShift_antitone hpos hab hb /-- Shrinking the magnitude keeps an accepted input accepted: the headroom shift only grows. -/ -theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : y1 < 2 ^ 256) +theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : Int128CalldataWord y1) (h2 : MulExpRayValueDomain y2 x) (hab : absTree y1 ≤ absTree y2) : MulExpRayValueDomain y1 x := by obtain ⟨⟨_, hx⟩, hscale2, hxhi, hlv2⟩ := h2 @@ -75,11 +75,11 @@ theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) by_cases hx0 : int256 x = 0 · have hxz : x = 0 := (int256_zero_iff_of_canonical hx).1 hx0 subst hxz - rw [mulExpTree_scale_point hy habs, int256_of_lt hyw] + rw [mulExpTree_scale_point hy.1 habs, int256_of_lt hyw] exact Int.natCast_nonneg y · have hW : WideRegion x := ⟨by omega, hxhi⟩ obtain ⟨hm0, _, _, _⟩ := - mulMagnitude_bracket_live hy hx (by omega) habs hx0 hW hlv + mulMagnitude_bracket_live hy.1 hx (by omega) habs hx0 hW hlv rw [int256_tree_pos hpos hyw] exact hm0 @@ -102,13 +102,13 @@ theorem mulExpTree_result_nonpos {y x : Nat} (h : MulExpRayValueDomain y x) by_cases hx0 : int256 x = 0 · have hxz : x = 0 := (int256_zero_iff_of_canonical hx).1 hx0 subst hxz - rw [mulExpTree_scale_point hy habs] + rw [mulExpTree_scale_point hy.1 habs] exact hyneg · have hW : WideRegion x := ⟨by omega, hxhi⟩ obtain ⟨hm0, _, _, _⟩ := - mulMagnitude_bracket_live hy hx (by omega) habs hx0 hW hlv - have hm255 := mag_word_small hy (by omega) hx habs hx0 hW hlv - rw [int256_tree_neg hybig hy hm255] + mulMagnitude_bracket_live hy.1 hx (by omega) habs hx0 hW hlv + have hm255 := mag_word_small hy.1 (by omega) hx habs hx0 hW hlv + rw [int256_tree_neg hybig hy.1 hm255] linarith [hm0] /-! ## The joint statement -/ @@ -134,8 +134,8 @@ theorem run_mul_exp_ray_evm_mono_joint {y1 y2 x1 x2 : Nat} have hrun2 : run_mul_exp_ray_evm y2 x2 = .ok (mulExpTree y2 x2) := run_mul_exp_ray_evm_eq_tree h2 refine ⟨mulExpTree y1 x1, mulExpTree y2 x2, hrun1, hrun2, hcond, ?_⟩ - have hy1w : y1 < 2 ^ 256 := h1.1.1 - have hy2w : y2 < 2 ^ 256 := h2.1.1 + have hy1w : y1 < 2 ^ 256 := h1.1.1.1 + have hy2w : y2 < 2 ^ 256 := h2.1.1.1 rcases hcond with ⟨hy1nn, hy12, hx12⟩ | ⟨hy12, hy2np, hx21⟩ | ⟨hy1np, hy2nn⟩ · -- both nonnegative, exponents rising: route through (y1, x2) have hy1small : y1 < 2 ^ 255 := by @@ -150,7 +150,7 @@ theorem run_mul_exp_ray_evm_mono_joint {y1 y2 x1 x2 : Nat} rw [absTree_nonneg hy1small, absTree_nonneg hy2small] rw [int256_of_lt hy1small, int256_of_lt hy2small] at hy12 exact_mod_cast hy12 - have h12 : MulExpRayValueDomain y1 x2 := valueDomain_of_abs_le hy1w h2 hab + have h12 : MulExpRayValueDomain y1 x2 := valueDomain_of_abs_le h1.1.1 h2 hab obtain ⟨r1, r2, hr1, hr2, _, hordx⟩ := run_mul_exp_ray_evm_mono_x h1 h12 hx12 obtain ⟨r3, r4, hr3, hr4, _, hordy⟩ := run_mul_exp_ray_evm_mono_y h12 h2 hy12 have e1 := tree_of_run hrun1 hr1 @@ -184,7 +184,7 @@ theorem run_mul_exp_ray_evm_mono_joint {y1 y2 x1 x2 : Nat} rw [ha, hb] at hy12 have h1 : (absTree y2 : Int) ≤ (absTree y1 : Int) := by linarith [hy12] exact_mod_cast h1 - have h21 : MulExpRayValueDomain y2 x1 := valueDomain_of_abs_le hy2w h1 hab + have h21 : MulExpRayValueDomain y2 x1 := valueDomain_of_abs_le h2.1.1 h1 hab obtain ⟨r1, r2, hr1, hr2, _, hordy⟩ := run_mul_exp_ray_evm_mono_y h1 h21 hy12 obtain ⟨r3, r4, hr3, hr4, _, hordx⟩ := run_mul_exp_ray_evm_mono_x h2 h21 hx21 have e1 := tree_of_run hrun1 hr1 @@ -247,16 +247,17 @@ theorem panicDomain_iff_magnitude_guard {y x : Nat} (hcanon : MulExpRayCanonical · exact ⟨⟨hy, hx⟩, Or.inr (Or.inl h)⟩ · exact ⟨⟨hy, hx⟩, Or.inr (Or.inr h)⟩ -/-- **The `type(int256).min` multiplier always reverts**: its magnitude word is `2^255`, above +/-- **The `type(int128).min` multiplier always reverts**: its magnitude is `2^127`, above the maximal scale. -/ -theorem run_mul_exp_ray_evm_revert_int_min {x : Nat} (hx : x < 2 ^ 256) : - run_mul_exp_ray_evm (2 ^ 255) x = .error "revert" := by +theorem run_mul_exp_ray_evm_revert_int128_min {x : Nat} (hx : x < 2 ^ 256) : + run_mul_exp_ray_evm (2 ^ 256 - 2 ^ 127) x = .error "revert" := by apply run_mul_exp_ray_evm_revert - refine ⟨⟨by norm_num, hx⟩, Or.inl ?_⟩ - have hiff := scaleShiftTree_le_127_iff (absTree_lt (2 ^ 255)) + refine ⟨⟨int128CalldataWord_min, hx⟩, Or.inl ?_⟩ + have hiff := scaleShiftTree_le_127_iff (absTree_lt (2 ^ 256 - 2 ^ 127)) by_contra hshift - have hcap := hiff.mp (by omega : scaleShiftTree (absTree (2 ^ 255)) ≤ 127) - rw [absTree_neg (le_refl _) (by norm_num)] at hcap + have hcap := hiff.mp + (by omega : scaleShiftTree (absTree (2 ^ 256 - 2 ^ 127)) ≤ 127) + rw [absTree_neg (by norm_num) (by norm_num)] at hcap unfold scaleMax at hcap norm_num at hcap diff --git a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean index 6aceec1c9..5eaa4507c 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean @@ -407,31 +407,31 @@ theorem mulExpTree_clamped {y x : Nat} (hx : x < 2 ^ 256) private theorem int256_zero_word : int256 (0 : Nat) = 0 := by unfold int256; norm_num /-- **Scale point.** `mulExpRay(y, 0)` returns `y` whenever the two-bit closing-shift guard accepts. -/ -theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : y < 2 ^ 256) +theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : Int128CalldataWord y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := by - obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy habs + obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy.1 habs have hguard : mulExpGuardTree y 0 = 0 := by rw [mulExpGuardTree_eq_zero_iff (by norm_num)] refine ⟨hs127, ?_, hshift⟩ rw [int256_mulExpRayHi, int256_zero_word] norm_num - have h := run_mul_exp_ray_evm_eq_tree_of_guard y 0 hguard - rwa [mulExpTree_scale_point hy habs] at h + have h := run_mul_exp_ray_evm_eq_tree_of_guard y 0 hy.2 hguard + rwa [mulExpTree_scale_point hy.1 habs] at h /-- **Clamp.** An accepted `mulExpRay(y, x)` returns zero at or below the zero cutoff. -/ -theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) +theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : run_mul_exp_ray_evm y x = .ok 0 := by - obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy habs + obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy.1 habs have hguard : mulExpGuardTree y x = 0 := by rw [mulExpGuardTree_eq_zero_iff hx] refine ⟨hs127, ?_, hshift⟩ rw [int256_mulExpRayHi] rw [int256_mulExpRayZeroMax] at hclamp omega - have h := run_mul_exp_ray_evm_eq_tree_of_guard y x hguard + have h := run_mul_exp_ray_evm_eq_tree_of_guard y x hy.2 hguard rwa [mulExpTree_clamped hx hclamp] at h /-! ## Shell brackets -/ @@ -439,7 +439,7 @@ theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ noncomputable section /-- **Scale-point bracket.** The exact result `y` satisfies the public bracket at `x = 0`. -/ -theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : y < 2 ^ 256) +theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : Int128CalldataWord y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := by refine ⟨y, run_mul_exp_ray_evm_scale_point hy habs hshift, ?_⟩ @@ -505,13 +505,13 @@ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) _ < 1 := hexp1 /-- **Clamp bracket.** The zero result satisfies the public bracket at or below the cutoff. -/ -theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) +theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : MulExpRayRunBracket y x := by refine ⟨0, run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp, ?_⟩ rw [int256_zero_word] - have hlt := clamped_target_lt_one hy hx habs hclamp + have hlt := clamped_target_lt_one hy.1 hx habs hclamp have hnn := mulExpRayMagnitudeTarget_nonneg (int256 y) (int256 x) unfold MulExpRayBracket split_ifs <;> diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean index 0946de217..f264b828a 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -236,7 +236,8 @@ theorem scaleMax_octave_neg_two_valueDomain {x : Nat} (hx : x < 2 ^ 256) have hshift : int256 (mulShiftTree scaleMax x) = 2 := by rw [mulShiftTree_transport_global hcap, hs, hk] norm_num - exact ⟨hs, hshift, ⟨⟨hy, hx⟩, by rw [hs]; norm_num, hxhi, by omega⟩⟩ + exact ⟨hs, hshift, + ⟨⟨int128CalldataWord_scaleMax, hx⟩, by rw [hs]; norm_num, hxhi, by omega⟩⟩ /-- The closing-shift word carries the signed difference `S − k` on the wide region. -/ theorem mulShiftTree_transport {y x : Nat} (_hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) diff --git a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean index c543c605b..d7d01611a 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean @@ -649,19 +649,19 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} split <;> exact le_refl _ -- (clamp, pin) · subst hp2 - rw [mulExpTree_clamped hx1w hc1, mulExpTree_scale_point hy habs, int256_zero_word'] + rw [mulExpTree_clamped hx1w hc1, mulExpTree_scale_point hy.1 habs, int256_zero_word'] split_ifs with hneg · exact le_of_lt hneg · exact not_lt.mp hneg -- (clamp, live) · rw [mulExpTree_clamped hx1w hc1, int256_zero_word'] have hW2 : WideRegion x2 := ⟨hzm2, hxhi2⟩ - obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy hx2w hy0 habs hx20 hW2 hlv2 - have hm255 := mag_word_small hy hy0 hx2w habs hx20 hW2 hlv2 + obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy.1 hx2w hy0 habs hx20 hW2 hlv2 + have hm255 := mag_word_small hy.1 hy0 hx2w habs hx20 hW2 hlv2 by_cases hneg : y < 2 ^ 255 · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg] exact hm0 - · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255] + · rw [if_pos (int256_y_neg (by omega) hy.1), int256_tree_neg (by omega) hy.1 hm255] linarith [hm0] -- (pin, clamp): impossible, the scale point is above the clamp · exfalso @@ -679,14 +679,14 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} have hx2pos : 0 < int256 x2 := by rw [int256_zero_word'] at hle omega - have hge := mulMagnitude_ge_abs_of_pos hy hy0 hx2w habs hW2 hx2pos hlv2 - have hm255 := mag_word_small hy hy0 hx2w habs hx20 hW2 hlv2 - rw [mulExpTree_scale_point hy habs] + have hge := mulMagnitude_ge_abs_of_pos hy.1 hy0 hx2w habs hW2 hx2pos hlv2 + have hm255 := mag_word_small hy.1 hy0 hx2w habs hx20 hW2 hlv2 + rw [mulExpTree_scale_point hy.1 habs] by_cases hneg : y < 2 ^ 255 · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg, int256_pos_eq_abs hneg] exact hge - · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255, - int256_neg_eq_abs (by omega) hy] + · rw [if_pos (int256_y_neg (by omega) hy.1), int256_tree_neg (by omega) hy.1 hm255, + int256_neg_eq_abs (by omega) hy.1] linarith [hge] -- (live, clamp): impossible · exfalso @@ -698,27 +698,28 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} have hx1neg : int256 x1 < 0 := by rw [int256_zero_word'] at hle omega - have hlt := mulMagnitude_le_abs_of_neg hy hy0 hx1w habs hW1 hx1neg hlv1 - have hm255 := mag_word_small hy hy0 hx1w habs hx10 hW1 hlv1 - rw [mulExpTree_scale_point hy habs] + have hlt := mulMagnitude_le_abs_of_neg hy.1 hy0 hx1w habs hW1 hx1neg hlv1 + have hm255 := mag_word_small hy.1 hy0 hx1w habs hx10 hW1 hlv1 + rw [mulExpTree_scale_point hy.1 habs] by_cases hneg : y < 2 ^ 255 · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg, int256_pos_eq_abs hneg] exact hlt - · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255, - int256_neg_eq_abs (by omega) hy] + · rw [if_pos (int256_y_neg (by omega) hy.1), int256_tree_neg (by omega) hy.1 hm255, + int256_neg_eq_abs (by omega) hy.1] linarith [hlt] -- (live, live) · have hW1 : WideRegion x1 := ⟨hzm1, hxhi1⟩ have hW2 : WideRegion x2 := ⟨hzm2, hxhi2⟩ - have hmono := mulMagnitude_mono_pair hy hy0 hx1w hx2w habs hW1 hW2 hx10 hx20 hlv1 hlv2 hle - have hm255a := mag_word_small hy hy0 hx1w habs hx10 hW1 hlv1 - have hm255b := mag_word_small hy hy0 hx2w habs hx20 hW2 hlv2 + have hmono := + mulMagnitude_mono_pair hy.1 hy0 hx1w hx2w habs hW1 hW2 hx10 hx20 hlv1 hlv2 hle + have hm255a := mag_word_small hy.1 hy0 hx1w habs hx10 hW1 hlv1 + have hm255b := mag_word_small hy.1 hy0 hx2w habs hx20 hW2 hlv2 by_cases hneg : y < 2 ^ 255 · rw [if_neg (int256_y_nonneg hneg), int256_tree_pos hypos hneg, int256_tree_pos hypos hneg] exact hmono - · rw [if_pos (int256_y_neg (by omega) hy), int256_tree_neg (by omega) hy hm255a, - int256_tree_neg (by omega) hy hm255b] + · rw [if_pos (int256_y_neg (by omega) hy.1), int256_tree_neg (by omega) hy.1 hm255a, + int256_tree_neg (by omega) hy.1 hm255b] linarith [hmono] end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean index 7fc693b33..7acccdd12 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean @@ -566,7 +566,7 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} by_cases hx0 : int256 x = 0 · have hxz : x = 0 := (int256_zero_iff_of_canonical hxw).1 hx0 subst hxz - rw [mulExpTree_scale_point hy1 habs1, mulExpTree_scale_point hy2 habs2] + rw [mulExpTree_scale_point hy1.1 habs1, mulExpTree_scale_point hy2.1 habs2] exact hle -- the live region have hW : WideRegion x := ⟨by omega, hxhi⟩ @@ -585,9 +585,10 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} rw [h0] at hle have hy2small : y2 < 2 ^ 255 := by by_contra hbig - have := int256_y_neg (by omega) hy2 + have := int256_y_neg (by omega) hy2.1 omega - obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy2 hxw (by omega) habs2 hx0 hW hlv2 + obtain ⟨hm0, _, _, _⟩ := + mulMagnitude_bracket_live hy2.1 hxw (by omega) habs2 hx0 hW hlv2 rw [int256_tree_pos hp2 hy2small] exact hm0 rcases Nat.eq_zero_or_pos y2 with hz2 | hp2 @@ -601,16 +602,17 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} rw [h1] at hle have : y1 = 0 := by exact_mod_cast le_antisymm (by exact_mod_cast hle) (Nat.zero_le y1) omega - have hm255 := mag_word_small hy1 (by omega) hxw habs1 hx0 hW hlv1 - obtain ⟨hm0, _, _, _⟩ := mulMagnitude_bracket_live hy1 hxw (by omega) habs1 hx0 hW hlv1 - rw [int256_tree_neg hy1big hy1 hm255] + have hm255 := mag_word_small hy1.1 (by omega) hxw habs1 hx0 hW hlv1 + obtain ⟨hm0, _, _, _⟩ := + mulMagnitude_bracket_live hy1.1 hxw (by omega) habs1 hx0 hW hlv1 + rw [int256_tree_neg hy1big hy1.1 hm255] linarith [hm0] -- both multipliers nonzero by_cases hneg1 : y1 < 2 ^ 255 · -- y1 on the nonnegative-word side, hence so is y2 have hy2small : y2 < 2 ^ 255 := by by_contra hbig - have hn := int256_y_neg (by omega) hy2 + have hn := int256_y_neg (by omega) hy2.1 have hp := int256_of_lt hneg1 rw [hp] at hle have : (0:Int) ≤ (y1 : Int) := Int.natCast_nonneg y1 @@ -629,32 +631,34 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} have hy1big : 2 ^ 255 ≤ y1 := by omega by_cases hneg2 : y2 < 2 ^ 255 · -- signs differ: a nonpositive result against a nonnegative one - have hm255a := mag_word_small hy1 (by omega) hxw habs1 hx0 hW hlv1 - obtain ⟨hm0a, _, _, _⟩ := mulMagnitude_bracket_live hy1 hxw (by omega) habs1 hx0 hW hlv1 - obtain ⟨hm0b, _, _, _⟩ := mulMagnitude_bracket_live hy2 hxw (by omega) habs2 hx0 hW hlv2 - rw [int256_tree_neg hy1big hy1 hm255a, int256_tree_pos hp2 hneg2] + have hm255a := mag_word_small hy1.1 (by omega) hxw habs1 hx0 hW hlv1 + obtain ⟨hm0a, _, _, _⟩ := + mulMagnitude_bracket_live hy1.1 hxw (by omega) habs1 hx0 hW hlv1 + obtain ⟨hm0b, _, _, _⟩ := + mulMagnitude_bracket_live hy2.1 hxw (by omega) habs2 hx0 hW hlv2 + rw [int256_tree_neg hy1big hy1.1 hm255a, int256_tree_pos hp2 hneg2] linarith [hm0a, hm0b] · -- both negative: magnitudes reverse have hy2big : 2 ^ 255 ≤ y2 := by omega - have haa1 : absTree y1 = 2 ^ 256 - y1 := absTree_neg hy1big hy1 - have haa2 : absTree y2 = 2 ^ 256 - y2 := absTree_neg hy2big hy2 + have haa1 : absTree y1 = 2 ^ 256 - y1 := absTree_neg hy1big hy1.1 + have haa2 : absTree y2 = 2 ^ 256 - y2 := absTree_neg hy2big hy2.1 have h21 : absTree y2 ≤ absTree y1 := by rw [haa1, haa2] - have ha := int256_neg_eq_abs hy1big hy1 - have hb := int256_neg_eq_abs hy2big hy2 + have ha := int256_neg_eq_abs hy1big hy1.1 + have hb := int256_neg_eq_abs hy2big hy2.1 rw [ha, hb, haa1, haa2] at hle have h1 : ((2 ^ 256 - y2 : Nat) : Int) ≤ ((2 ^ 256 - y1 : Nat) : Int) := by omega exact_mod_cast h1 have hmag : int256 (mulMagnitudeTree (absTree y2) x) ≤ int256 (mulMagnitudeTree (absTree y1) x) := by refine mulMagnitudeY_region_mono ?_ h21 habs1 hxw hW hx0 ?_ - · have : 1 ≤ absTree y2 := absTree_pos hy2 (by omega) + · have : 1 ≤ absTree y2 := absTree_pos hy2.1 (by omega) omega · rw [← mulShift_abs_norm habs1] exact hlv1 - have hm255a := mag_word_small hy1 (by omega) hxw habs1 hx0 hW hlv1 - have hm255b := mag_word_small hy2 (by omega) hxw habs2 hx0 hW hlv2 - rw [int256_tree_neg hy1big hy1 hm255a, int256_tree_neg hy2big hy2 hm255b, + have hm255a := mag_word_small hy1.1 (by omega) hxw habs1 hx0 hW hlv1 + have hm255b := mag_word_small hy2.1 (by omega) hxw habs2 hx0 hW hlv2 + rw [int256_tree_neg hy1big hy1.1 hm255a, int256_tree_neg hy2big hy2.1 hm255b, mulMagnitude_abs_norm habs1, mulMagnitude_abs_norm habs2] linarith [hmag] diff --git a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean index d3498308e..fea6343d2 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean @@ -111,7 +111,7 @@ theorem calldataload_mulExpRay_arg0_of_calldata (EvmYul.Yul.State.Ok shared store).toState (FormalYul.word 4) = FormalYul.word y := by exact FormalYul.Preservation.calldataload_two_args_first_of_calldata - 0x79 0xab 0xc0 0x89 y x shared store (by simpa [selector_mulExpRay] using hdata) + 0x0d 0xbb 0x6b 0xb9 y x shared store (by simpa [selector_mulExpRay] using hdata) @[simp] theorem calldataload_mulExpRay_arg1_of_calldata @@ -121,7 +121,7 @@ theorem calldataload_mulExpRay_arg1_of_calldata (EvmYul.Yul.State.Ok shared store).toState (FormalYul.word 36) = FormalYul.word x := by exact FormalYul.Preservation.calldataload_two_args_second_of_calldata - 0x79 0xab 0xc0 0x89 y x shared store (by simpa [selector_mulExpRay] using hdata) + 0x0d 0xbb 0x6b 0xb9 y x shared store (by simpa [selector_mulExpRay] using hdata) /-- `validator_revert_t_int256(value)` does `if iszero(eq(value, cleanup_t_int256(value))) {revert}`; since `cleanup_t_int256` is the identity the equality always holds, so it never reverts. -/ @@ -153,6 +153,39 @@ theorem call_validator_revert_t_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, FormalYul.word, hcleanup] +/-- `validator_revert_t_int128(value)` accepts exactly the words unchanged by +`cleanup_t_int128`. -/ +theorem call_validator_revert_t_int128_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word v) = + FormalYul.word v) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word v] (.some "validator_revert_t_int128") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, []) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_validator_revert_t_int128] + simp only [yulFunction_validator_revert_t_int128, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hcleanup := + call_cleanup_t_int128_direct (v := v) (fuel := fuel + extra) (extra := 51) + (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hcleanup + simp only [FormalYul.word] at hclean + simp +decide [EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + FormalYul.word, hcleanup, hclean] + /-- `abi_decode_t_int256(offset, end) := calldataload(offset); validator(value)` — for the `expRayToWad` calldata at offset 4 it reads `x` and validates (no revert). -/ theorem call_abi_decode_t_int256_of_calldata @@ -222,26 +255,28 @@ theorem call_abi_decode_tuple_t_int256_of_calldata EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, hdecode] -theorem call_abi_decode_t_int256_mul_arg0_of_calldata +theorem call_abi_decode_t_int128_mul_arg0_of_calldata (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) - (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) : EvmYul.Yul.call (fuel + (extra + 200)) [FormalYul.word 4, FormalYul.word 68] - (.some "abi_decode_t_int256") (.some yulContract) + (.some "abi_decode_t_int128") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word y]) := by rw [show fuel + (extra + 200) = (fuel + extra) + 200 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_abi_decode_t_int256] - simp only [yulFunction_abi_decode_t_int256, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_abi_decode_t_int128] + simp only [yulFunction_abi_decode_t_int128, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hvalidator := - call_validator_revert_t_int256_direct (v := y) (fuel := fuel + extra) (extra := 115) - (shared := shared) (hlookup := hlookup) + call_validator_revert_t_int128_direct (v := y) (fuel := fuel + extra) (extra := 115) + (shared := shared) (hlookup := hlookup) (hclean := hclean) simp only [Nat.reduceAdd, FormalYul.word] at hvalidator have hload := calldataload_mulExpRay_arg0_of_calldata y x shared @@ -294,34 +329,36 @@ theorem call_abi_decode_t_int256_mul_arg1_of_calldata EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, hload, hvalidator] -/-- `abi_decode_tuple_t_int256t_int256(headStart, dataEnd)` decodes `(y, x)`. -/ -theorem call_abi_decode_tuple_t_int256t_int256_of_mul_calldata +/-- `abi_decode_tuple_t_int128t_int256(headStart, dataEnd)` decodes `(y, x)`. -/ +theorem call_abi_decode_tuple_t_int128t_int256_of_mul_calldata (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) - (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) : + (hdata : shared.executionEnv.calldata = selector_mulExpRay ++ FormalYul.encodeWords [y, x]) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) : EvmYul.Yul.call (fuel + (extra + 520)) [FormalYul.word 4, FormalYul.word 68] - (.some "abi_decode_tuple_t_int256t_int256") (.some yulContract) + (.some "abi_decode_tuple_t_int128t_int256") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word y, FormalYul.word x]) := by rw [show fuel + (extra + 520) = (fuel + extra) + 520 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_abi_decode_tuple_t_int256t_int256] - simp only [yulFunction_abi_decode_tuple_t_int256t_int256, + lookup_abi_decode_tuple_t_int128t_int256] + simp only [yulFunction_abi_decode_tuple_t_int128t_int256, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hdecode0 := - call_abi_decode_t_int256_mul_arg0_of_calldata (y := y) (x := x) + call_abi_decode_t_int128_mul_arg0_of_calldata (y := y) (x := x) (fuel := fuel + extra) (extra := 313) (shared := shared) (store := Finmap.insert "offset" (FormalYul.word 0) (Finmap.insert "headStart" (FormalYul.word 4) (Finmap.insert "dataEnd" (FormalYul.word 68) (Inhabited.default : EvmYul.Yul.VarStore)))) - (hlookup := hlookup) (hdata := hdata) + (hlookup := hlookup) (hdata := hdata) (hclean := hclean) have hdecode1 := call_abi_decode_t_int256_mul_arg1_of_calldata (y := y) (x := x) (fuel := fuel + extra) (extra := 312) @@ -543,12 +580,12 @@ theorem selectSwitchCase_expRayToWad_sharedFor_mk (x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore)).toState (FormalYul.word 0)) (FormalYul.word 224)) - [(FormalYul.word 1099384363, + [(FormalYul.word 230386617, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), - (FormalYul.word 2041299081, + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])]), + (FormalYul.word 1099384363, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])])] = some [EvmYul.Yul.Ast.Stmt.ExprStmtCall (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])] := by @@ -569,12 +606,12 @@ theorem selectSwitchCase_expRayToWad_sharedFor_mk_raw (x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) - [(EvmYul.UInt256.ofNat 1099384363, + [(EvmYul.UInt256.ofNat 230386617, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), - (EvmYul.UInt256.ofNat 2041299081, + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])]), + (EvmYul.UInt256.ofNat 1099384363, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])])] = some [EvmYul.Yul.Ast.Stmt.ExprStmtCall (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])] := by @@ -608,12 +645,12 @@ theorem mulExpRay_selector_afterFreePtr (y x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore)).toState (FormalYul.word 0)) (FormalYul.word 224) = - FormalYul.word 2041299081 := by + FormalYul.word 230386617 := by have hselector := FormalYul.Preservation.shiftRight_calldataload_selector_two_args_of_calldata (shared := mulExpSharedAfterFreePtr y x) (store := (Inhabited.default : EvmYul.Yul.VarStore)) - (a := 0x79) (b := 0xab) (c := 0xc0) (d := 0x89) (x := y) (y := x) + (a := 0x0d) (b := 0xbb) (c := 0x6b) (d := 0xb9) (x := y) (y := x) (by simp [selector_mulExpRay]) simpa [EvmYul.fromBytesBigEndian, EvmYul.fromBytes', FormalYul.word] using hselector @@ -631,7 +668,7 @@ theorem mulExpRay_selector_sharedFor_mk (y x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore)).toState (FormalYul.word 0)) (FormalYul.word 224) = - FormalYul.word 2041299081 := by + FormalYul.word 230386617 := by rw [sharedFor_inherited_mstore_mk_eq_mulExpSharedAfterFreePtr] exact mulExpRay_selector_afterFreePtr y x @@ -650,12 +687,12 @@ theorem selectSwitchCase_mulExpRay_sharedFor_mk (y x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore)).toState (FormalYul.word 0)) (FormalYul.word 224)) - [(FormalYul.word 1099384363, + [(FormalYul.word 230386617, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), - (FormalYul.word 2041299081, + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])]), + (FormalYul.word 1099384363, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])])] = some [EvmYul.Yul.Ast.Stmt.ExprStmtCall (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])] := by @@ -676,12 +713,12 @@ theorem selectSwitchCase_mulExpRay_sharedFor_mk_raw (y x : Nat) : (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) - [(EvmYul.UInt256.ofNat 1099384363, + [(EvmYul.UInt256.ofNat 230386617, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])]), - (EvmYul.UInt256.ofNat 2041299081, + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])]), + (EvmYul.UInt256.ofNat 1099384363, [EvmYul.Yul.Ast.Stmt.ExprStmtCall - (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])])] = + (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_expRayToWad) [])])] = some [EvmYul.Yul.Ast.Stmt.ExprStmtCall (EvmYul.Yul.Ast.Expr.Call (Sum.inr yulName_external_fun_wrap_mulExpRay) [])] := by diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index d714d2c7a..25133cc0e 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -88,6 +88,48 @@ theorem call_cleanup_t_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +/-- A Yul `signextend(a, b)` primitive call returns the sign-extended word. -/ +theorem primCall_signextend_yul (fuel : Nat) (s : EvmYul.Yul.State) + (a b : EvmYul.UInt256) : + EvmYul.Yul.primCall (fuel + 1) s + (EvmYul.Operation.StopArith EvmYul.Operation.SAOp.SIGNEXTEND : EvmYul.Operation .Yul) + [a, b] = + .ok (s, [EvmYul.UInt256.signextend a b]) := by + rw [EvmYul.Yul.primCall.eq_def] + simp only [List.mem_cons, List.not_mem_nil, Bool.not_eq_true, reduceCtorEq, or_self, and_false, if_false, + EvmYul.step.eq_def] + rfl + +/-- `cleanup_t_int128(value) -> cleaned { cleaned := signextend(15, value) }`. -/ +theorem call_cleanup_t_int128_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] (.some "cleanup_t_int128") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word v)]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_cleanup_t_int128] + simp only [yulFunction_cleanup_t_int128, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hsign := primCall_signextend_yul (fuel + extra + 16) + (EvmYul.Yul.State.Ok shared + (Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore))) + (FormalYul.word 15) (FormalYul.word v) + simp only [FormalYul.word] at hsign + simp +decide [EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hsign] + theorem call_identity_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index 152103054..c77452058 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -28,6 +28,8 @@ theorem call_fun_mulExpRay_revert_direct (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 1) : EvmYul.Yul.call (fuel + (extra + 2200)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = @@ -40,6 +42,7 @@ theorem call_fun_mulExpRay_revert_direct FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp only [FormalYul.word] at hclean let sign := signTree y let ay := absTree y let s := evmSub (evmClz ay) scaleMaxClz @@ -162,7 +165,7 @@ theorem call_fun_mulExpRay_revert_direct EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.setStore, - FormalYul.word, + FormalYul.word, primCall_signextend_yul, hguardUnfold, hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS, hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, @@ -175,7 +178,7 @@ theorem call_fun_mulExpRay_revert_direct Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, uint256_ofNat_sgt_eq_word_evmSgt, - scaleMaxClz] + scaleMaxClz, hclean] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay` forwards the revert. -/ @@ -183,6 +186,8 @@ theorem call_fun_wrap_mulExpRay_revert_direct (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 1) : EvmYul.Yul.call (fuel + (extra + 2300)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = @@ -197,7 +202,7 @@ theorem call_fun_wrap_mulExpRay_revert_direct EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hinner := call_fun_mulExpRay_revert_direct (y := y) (x := x) (fuel := fuel + extra) (extra := 89) - (shared := shared) (hlookup := hlookup) (hguard := hguard) + (shared := shared) (hlookup := hlookup) (hclean := hclean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_mulExpRay] at hinner simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', @@ -213,6 +218,8 @@ set_option maxHeartbeats 12000000 in /-- The external `mulExpRay` entrypoint forwards the revert. -/ theorem external_fun_wrap_mulExpRay_calldata_revert (y x : Nat) (store : EvmYul.Yul.VarStore) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 1) : EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok (mulExpSharedAfterFreePtr y x) store) = @@ -226,12 +233,12 @@ theorem external_fun_wrap_mulExpRay_calldata_revert FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hdecode := - call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := y) (x := x) + call_abi_decode_tuple_t_int128t_int256_of_mul_calldata (y := y) (x := x) (fuel := 0) (extra := 999464) (shared := mulExpSharedAfterFreePtr y x) (store := (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := mulExpSharedAfterFreePtr_lookup y x) - (hdata := mulExpSharedAfterFreePtr_calldata y x) + (hdata := mulExpSharedAfterFreePtr_calldata y x) (hclean := hclean) simp only [Nat.reduceAdd, FormalYul.word] at hdecode have hwrap := call_fun_wrap_mulExpRay_revert_direct (y := y) (x := x) (fuel := 0) (extra := 997683) @@ -239,7 +246,7 @@ theorem external_fun_wrap_mulExpRay_calldata_revert (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hguard := hguard) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, @@ -259,6 +266,8 @@ set_option maxHeartbeats 12000000 in /-- The revert from the exact dispatcher-handed state. -/ theorem external_fun_wrap_mulExpRay_dispatcher_state_revert (y x : Nat) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 1) : EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok @@ -293,11 +302,13 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_revert (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) - hguard + hclean hguard set_option maxHeartbeats 12000000 in /-- **Guard revert.** When the guard word is one, the compiled runtime reverts. -/ theorem run_mul_exp_ray_evm_revert_of_guard (y x : Nat) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 1) : run_mul_exp_ray_evm y x = .error "revert" := by have hexec : @@ -313,7 +324,7 @@ theorem run_mul_exp_ray_evm_revert_of_guard (y x : Nat) EvmYul.Yul.State.executionEnv, EvmYul.Yul.State.toMachineState, FormalYul.word, call_shift_right_224_unsigned_direct] rw [selectSwitchCase_mulExpRay_sharedFor_mk_raw y x] - simp +decide [external_fun_wrap_mulExpRay_dispatcher_state_revert y x hguard, + simp +decide [external_fun_wrap_mulExpRay_dispatcher_state_revert y x hclean hguard, EvmYul.Yul.exec.eq_def, EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.multifill'] have hrun : diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 918be7dbf..0bbf00c6a 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -28,6 +28,8 @@ theorem call_fun_mulExpRay_direct (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : EvmYul.Yul.call (fuel + (extra + 2200)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = @@ -40,6 +42,7 @@ theorem call_fun_mulExpRay_direct FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp only [FormalYul.word] at hclean let sign := signTree y let ay := absTree y let s := evmSub (evmClz ay) scaleMaxClz @@ -183,7 +186,7 @@ theorem call_fun_mulExpRay_direct EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, + Finmap.lookup_insert, FormalYul.word, primCall_signextend_yul, hguardUnfold, hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS, hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, @@ -206,7 +209,7 @@ theorem call_fun_mulExpRay_direct od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, todShift, marginWord, scaleShiftTree, absTree, signTree, kTree, - scaleMaxClz, mulExpRayZeroMax] + scaleMaxClz, mulExpRayZeroMax, hclean] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay(y, x)` forwards to the value path. -/ @@ -214,6 +217,8 @@ theorem call_fun_wrap_mulExpRay_direct (y x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : EvmYul.Yul.call (fuel + (extra + 2300)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = @@ -228,7 +233,7 @@ theorem call_fun_wrap_mulExpRay_direct EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hinner := call_fun_mulExpRay_direct (y := y) (x := x) (fuel := fuel + extra) (extra := 89) - (shared := shared) (hlookup := hlookup) (hguard := hguard) + (shared := shared) (hlookup := hlookup) (hclean := hclean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_mulExpRay] at hinner simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', @@ -246,6 +251,8 @@ set_option maxHeartbeats 12000000 in /-- The external `mulExpRay` entrypoint ABI-encodes and returns the value tree. -/ theorem external_fun_wrap_mulExpRay_calldata_result (y x : Nat) (store : EvmYul.Yul.VarStore) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -280,12 +287,12 @@ theorem external_fun_wrap_mulExpRay_calldata_result (FormalYul.word 64)).2 } let encStore := Finmap.insert "memPos" memPos baseStore have hdecode := - call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := y) (x := x) + call_abi_decode_tuple_t_int128t_int256_of_mul_calldata (y := y) (x := x) (fuel := 0) (extra := 999464) (shared := mulExpSharedAfterFreePtr y x) (store := (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := mulExpSharedAfterFreePtr_lookup y x) - (hdata := mulExpSharedAfterFreePtr_calldata y x) + (hdata := mulExpSharedAfterFreePtr_calldata y x) (hclean := hclean) simp only [Nat.reduceAdd, FormalYul.word] at hdecode have hwrap := call_fun_wrap_mulExpRay_direct (y := y) (x := x) (fuel := 0) (extra := 997683) @@ -293,7 +300,7 @@ theorem external_fun_wrap_mulExpRay_calldata_result (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hguard := hguard) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap have halloc := call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr y x) @@ -340,6 +347,8 @@ set_option maxHeartbeats 12000000 in /-- The external `mulExpRay` entrypoint on the value path halts (returns). -/ theorem external_fun_wrap_mulExpRay_calldata_halts (y x : Nat) (store : EvmYul.Yul.VarStore) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -368,12 +377,12 @@ theorem external_fun_wrap_mulExpRay_calldata_halts (FormalYul.word 64)).2 } let encStore := Finmap.insert "memPos" memPos baseStore have hdecode := - call_abi_decode_tuple_t_int256t_int256_of_mul_calldata (y := y) (x := x) + call_abi_decode_tuple_t_int128t_int256_of_mul_calldata (y := y) (x := x) (fuel := 0) (extra := 999464) (shared := mulExpSharedAfterFreePtr y x) (store := (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := mulExpSharedAfterFreePtr_lookup y x) - (hdata := mulExpSharedAfterFreePtr_calldata y x) + (hdata := mulExpSharedAfterFreePtr_calldata y x) (hclean := hclean) simp only [Nat.reduceAdd, FormalYul.word] at hdecode have hwrap := call_fun_wrap_mulExpRay_direct (y := y) (x := x) (fuel := 0) (extra := 997683) @@ -381,7 +390,7 @@ theorem external_fun_wrap_mulExpRay_calldata_halts (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hguard := hguard) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap have halloc := call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr y x) @@ -413,6 +422,8 @@ set_option maxHeartbeats 12000000 in function. -/ theorem external_fun_wrap_mulExpRay_dispatcher_state_result (y x : Nat) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -454,13 +465,15 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_result (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) - hguard + hclean hguard set_option maxHeartbeats 12000000 in /-- Halt, starting from the exact state the dispatcher hands the external `mulExpRay` function. -/ theorem external_fun_wrap_mulExpRay_dispatcher_state_halts (y x : Nat) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -496,17 +509,19 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_halts (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) - hguard + hclean hguard set_option maxHeartbeats 12000000 in /-- **Value path.** When the guard word is zero, the compiled runtime returns the signed dynamic-scale arithmetic tree — for every multiplier, including zero. -/ theorem run_mul_exp_ray_evm_eq_tree_of_guard (y x : Nat) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = + FormalYul.word y) (hguard : mulExpGuardTree y x = 0) : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := by obtain ⟨haltState, _haltValue, hhalt⟩ := - external_fun_wrap_mulExpRay_dispatcher_state_halts y x hguard - have hresult := external_fun_wrap_mulExpRay_dispatcher_state_result y x hguard + external_fun_wrap_mulExpRay_dispatcher_state_halts y x hclean hguard + have hresult := external_fun_wrap_mulExpRay_dispatcher_state_result y x hclean hguard rw [hhalt] at hresult have hReturn : FormalYul.Preservation.DispatcherReturn yulContract diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 671d1e201..613ae2358 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -109,7 +109,7 @@ Every documented `mulExpRay` property holds for the compiled runtime, axiom-clea | Monotone in `x`, direction following `sign(y)` | `run_mul_exp_ray_evm_mono_x` | | Nondecreasing in `y` at a fixed `x` | `run_mul_exp_ray_evm_mono_y` | | Joint sign-aware monotonicity (three cases) | `run_mul_exp_ray_evm_mono_joint` | -| Reverts exactly when magnitude, upper-fence, or closing-shift guard fails | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_magnitude_guard`, `run_mul_exp_ray_evm_revert_int_min` | +| Reverts exactly when magnitude, upper-fence, or closing-shift guard fails | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_magnitude_guard`, `run_mul_exp_ray_evm_revert_int128_min` | | The 127-bit magnitude guard is exact | `scaleShiftTree_le_127_iff` | | The maximal magnitude is live at closing shift two | `scaleMax_octave_neg_two_run_bracket` | @@ -223,11 +223,11 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : FormalYul.Preservation.int256 (mulShiftTree y x) < 2 := panicDomain_iff_magnitude_guard hcanon -/-- **`type(int256).min` always reverts**: its magnitude word `2^255` exceeds the maximal +/-- **`type(int128).min` always reverts**: its magnitude `2^127` exceeds the maximal scale. -/ example {x : Nat} (hx : x < 2 ^ 256) : - run_mul_exp_ray_evm (2 ^ 255) x = .error "revert" := - run_mul_exp_ray_evm_revert_int_min hx + run_mul_exp_ray_evm (2 ^ 256 - 2 ^ 127) x = .error "revert" := + run_mul_exp_ray_evm_revert_int128_min hx /-- **Floor membership.** Every accepted input's result magnitude is `⌊A⌋` or `⌊A⌋ − 1`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : @@ -251,10 +251,11 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := mulExpRayBracket_zero_result x -/-- The value path returns the compiled arithmetic tree whenever the guard word is zero. -/ -example (y x : Nat) (hguard : mulExpGuardTree y x = 0) : +/-- The value path returns the compiled arithmetic tree whenever the ABI word is canonical and the +guard word is zero. -/ +example (y x : Nat) (hy : Int128CalldataWord y) (hguard : mulExpGuardTree y x = 0) : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := - run_mul_exp_ray_evm_eq_tree_of_guard y x hguard + run_mul_exp_ray_evm_eq_tree_of_guard y x hy.2 hguard /-- The compiled runtime returns zero for a zero multiplier whenever the guard accepts. -/ example (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : run_mul_exp_ray_evm 0 x = .ok 0 := @@ -281,19 +282,19 @@ example {y x : Nat} (h : MulExpRayPanicDomain y x) : run_mul_exp_ray_evm_revert h /-- The accepted scale point returns the multiplier exactly. -/ -example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) +example {y : Nat} (hy : Int128CalldataWord y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := run_mul_exp_ray_evm_scale_point hy habs hshift /-- The scale-point result satisfies the public bracket. -/ -example {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) +example {y : Nat} (hy : Int128CalldataWord y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := mulExpRay_run_bracket_scale_point hy habs hshift /-- At or below the zero cutoff, every accepted magnitude returns zero. -/ -example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) +example {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : @@ -301,7 +302,7 @@ example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp /-- The clamped result satisfies the public bracket. -/ -example {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) +example {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : @@ -413,9 +414,9 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms panicDomain_iff_magnitude_guard -/-- info: 'ExpYul.run_mul_exp_ray_evm_revert_int_min' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.run_mul_exp_ray_evm_revert_int128_min' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms run_mul_exp_ray_evm_revert_int_min +#print axioms run_mul_exp_ray_evm_revert_int128_min /-- info: 'ExpYul.mulExpRay_value_or_panic_of_canonical' depends on axioms: [propext, Quot.sound] -/ #guard_msgs in diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index bcdc813ea..eafaebbe8 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -40,7 +40,7 @@ def selectorCases : ModelKind → List String | .cbrt => ["0x56df2b56", "0x29f2f4f1"] | .cbrt512 => ["0xa83a5c08", "0x7c0352fc"] | .ln => ["0xef102248", "0x31d42abd"] - | .exp => ["0x4187462b", "0x79abc089"] + | .exp => ["0x0dbb6bb9", "0x4187462b"] def functionPrefixes : ModelKind → List String | .sqrt => @@ -511,7 +511,7 @@ def selector_expRayToWad : ByteArray := FormalYul.bytes [0x41, 0x87, 0x46, 0x2b] def selector_mulExpRay : ByteArray := - FormalYul.bytes [0x79, 0xab, 0xc0, 0x89] + FormalYul.bytes [0x0d, 0xbb, 0x6b, 0xb9] def run_exp_ray_to_wad_evm (x : Nat) : Except String Nat := FormalYul.callWord yulContract selector_expRayToWad [x] diff --git a/formal/yul/generate_from_forge.sh b/formal/yul/generate_from_forge.sh index eee3d1d2f..34953acc1 100755 --- a/formal/yul/generate_from_forge.sh +++ b/formal/yul/generate_from_forge.sh @@ -21,7 +21,7 @@ case "$kind" in cbrt) expected="29f2f4f1 56df2b56" ;; cbrt512) expected="7c0352fc a83a5c08" ;; ln) expected="31d42abd ef102248" ;; - exp) expected="4187462b 79abc089" ;; + exp) expected="0dbb6bb9 4187462b" ;; *) echo "unknown kind: $kind" >&2; exit 2 ;; esac diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index e0589cad6..4376599cb 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -73,8 +73,7 @@ library Exp { /// and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. /// /// Reverts with `Panic(17)` in exactly three cases: - /// abs(y) > 2¹²⁷ - 1 = 170141183460469231731687303715884105727 ≈ 1.70⋅10³⁸ (including - /// y = type(int256).min); x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ (regardless of + /// y = type(int128).min; x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ (regardless of /// y); or the octave word — `_octave`'s output, which is round(x / (10²⁷⋅ln(2))) wherever /// its product does not wrap (|x| ≲ 2¹⁵²) — exceeding s - 2, with 2ˢ the scale headroom /// above abs(y) (the largest power of two with abs(y)⋅2ˢ < 2¹²⁷; @@ -83,12 +82,13 @@ library Exp { /// x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap /// boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to /// zero, either of which is sound (A < 1 there at every supported magnitude). - function mulExpRay(int256 y, int256 x) internal pure returns (int256) { + function mulExpRay(int128 y, int256 x) internal pure returns (int256) { uint256 ay; uint256 sign; - // Split y into a sign mask and a magnitude without negating `type(int256).min`: + // Split y into a sign mask and a magnitude without negating `type(int128).min`: // sign = y >> 255; ay = (y ^ sign) - sign assembly ("memory-safe") { + y := signextend(0x0f, y) sign := sar(0xff, y) ay := sub(xor(y, sign), sign) } diff --git a/src/wrappers/ExpWrapper.sol b/src/wrappers/ExpWrapper.sol index deabe86da..3187cfd77 100644 --- a/src/wrappers/ExpWrapper.sol +++ b/src/wrappers/ExpWrapper.sol @@ -11,7 +11,7 @@ contract ExpWrapper { return Exp.expRayToWad(x); } - function wrap_mulExpRay(int256 y, int256 x) external pure returns (int256) { + function wrap_mulExpRay(int128 y, int256 x) external pure returns (int256) { return Exp.mulExpRay(y, x); } } diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index 474fcc167..c69a2cf49 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -9,6 +9,7 @@ import {Test, stdError} from "@forge-std/Test.sol"; contract ExpTest is Test { // The largest magnitude admitted by `mulExpRay`'s s <= 127 guard. uint256 private constant _SCALE_MAX = 0x7fffffffffffffffffffffffffffffff; + int128 private constant _Y_MAX = type(int128).max; // First input whose octave count exceeds the supported range; `expRayToWad` reverts here. int256 private constant _TOO_BIG = 0x92b2f16cc66c5a4ae96e80d4; // First input whose octave count reaches 125: the accuracy-guard boundary at the deepest @@ -28,7 +29,17 @@ contract ExpTest is Test { return Exp.expRayToWad(x); } - function mulExpRayExternal(int256 y, int256 x) external pure returns (int256) { + function mulExpRayExternal(int128 y, int256 x) external pure returns (int256) { + return Exp.mulExpRay(y, x); + } + + function mulExpRayDirtyY(uint256 dirtyY, int256 x) public pure returns (int256) { + int128 y; + // Solidity cannot construct a narrow signed value with dirty upper bits. + // Equivalent value: y = int128(uint128(dirtyY)). + assembly ("memory-safe") { + y := dirtyY + } return Exp.mulExpRay(y, x); } @@ -214,7 +225,7 @@ contract ExpTest is Test { function testMulExpRayScalePoint() external { assertEq(Exp.mulExpRay(1, 0), 1, "one"); assertEq(Exp.mulExpRay(-1, 0), -1, "minus one"); - int256 pinMax = int256(_SCALE_MAX >> 2); + int128 pinMax = _Y_MAX / 4; assertEq(Exp.mulExpRay(pinMax, 0), pinMax, "deepest pinned magnitude"); assertEq(Exp.mulExpRay(-pinMax, 0), -pinMax, "negative mirror"); vm.expectRevert(stdError.arithmeticError); @@ -228,18 +239,18 @@ contract ExpTest is Test { function testMulExpRayScaleCapLive() external pure { int256 x = _octaveStart(-2); int256 floorA = 30076996146000563943129221579116071223; - int256 r = Exp.mulExpRay(int256(_SCALE_MAX), x); + int256 r = Exp.mulExpRay(_Y_MAX, x); assertLe(r, floorA, "overestimates"); assertGe(r, floorA - 1, "below floor minus one"); - assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), x), -r, "negative mirror"); + assertEq(Exp.mulExpRay(-_Y_MAX, x), -r, "negative mirror"); x = -1039720770839917964125848183; assertEq(x, _octaveStart(-1) - 1, "upper endpoint"); floorA = 60153992292001127886258443070517000410; - r = Exp.mulExpRay(int256(_SCALE_MAX), x); + r = Exp.mulExpRay(_Y_MAX, x); assertLe(r, floorA, "overestimates at upper endpoint"); assertGe(r, floorA - 1, "below floor minus one at upper endpoint"); - assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), x), -r, "negative mirror at upper endpoint"); + assertEq(Exp.mulExpRay(-_Y_MAX, x), -r, "negative mirror at upper endpoint"); } /// Below the octave-wrap boundary (x < -(2**255 + 2**191)/CINV ~ -5.7e45) the wrapped octave @@ -286,28 +297,31 @@ contract ExpTest is Test { function testMulExpRayLowerZero() external pure { assertEq(Exp.mulExpRay(1, _X_LO_ZERO), 0, "one at boundary"); - assertEq(Exp.mulExpRay(int256(_SCALE_MAX), _X_LO_ZERO), 0, "scale max at boundary"); - assertEq(Exp.mulExpRay(-int256(_SCALE_MAX), _X_LO_ZERO - 1), 0, "negative below boundary"); + assertEq(Exp.mulExpRay(_Y_MAX, _X_LO_ZERO), 0, "scale max at boundary"); + assertEq(Exp.mulExpRay(-_Y_MAX, _X_LO_ZERO - 1), 0, "negative below boundary"); } function testMulExpRayNegativeSignSymmetry() external pure { int256 x = 3e27; - int256 y = 123456789012345678901234567; + int128 y = 123456789012345678901234567; assertEq(Exp.mulExpRay(-y, x), -Exp.mulExpRay(y, x), "positive exponent"); assertEq(Exp.mulExpRay(-y, -x), -Exp.mulExpRay(y, -x), "negative exponent"); } - function testMulExpRayOverScaleReverts() external { - vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(int256(_SCALE_MAX + 1), 0); - vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(type(int256).min, 0); + function testMulExpRayClearsDirtyYBits() external pure { + uint256 positive = (type(uint256).max << 128) | uint256(uint128(1e18)); + uint256 negative = uint256(uint128(-int128(1e18))); + assertEq(mulExpRayDirtyY(positive, 1e27), Exp.mulExpRay(1e18, 1e27), "dirty positive"); + assertEq(mulExpRayDirtyY(negative, 1e27), Exp.mulExpRay(-1e18, 1e27), "dirty negative"); + } + + function testMulExpRayMinReverts() external { vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(int256(_SCALE_MAX + 1), _X_LO_ZERO); + this.mulExpRayExternal(type(int128).min, 0); vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(-int256(_SCALE_MAX + 1), _X_LO_ZERO); + this.mulExpRayExternal(type(int128).min, _X_LO_ZERO); vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(type(int256).min, type(int256).min); + this.mulExpRayExternal(type(int128).min, type(int256).min); } function testMulExpRayHighGuardReverts() external { @@ -325,7 +339,7 @@ contract ExpTest is Test { vm.expectRevert(stdError.arithmeticError); this.mulExpRayExternal(1e18, _TOO_BIG); vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(int256(_SCALE_MAX), _octaveStart(-1)); + this.mulExpRayExternal(_Y_MAX, _octaveStart(-1)); } function testMulExpRaySmallMagnitudeHighOctave() external { @@ -340,13 +354,13 @@ contract ExpTest is Test { } function testFuzzMulExpRaySignSymmetry(uint256 uy, int256 x) external pure { - int256 y = int256(bound(uy, 1, 1e18)); + int128 y = int128(uint128(bound(uy, 1, 1e18))); x = bound(x, _X_LO_ZERO + 1, _TOO_BIG - 1); assertEq(Exp.mulExpRay(-y, x), -Exp.mulExpRay(y, x), "sign symmetry"); } function testFuzzMulExpRayMonotoneMagnitude(uint256 uy, int256 x) external pure { - int256 y = int256(bound(uy, 1, 1e18)); + int128 y = int128(uint128(bound(uy, 1, 1e18))); x = bound(x, _X_LO_ZERO + 1, _TOO_BIG - 2); assertGe(Exp.mulExpRay(y, x + 1), Exp.mulExpRay(y, x), "adjacent monotonicity"); } @@ -355,7 +369,7 @@ contract ExpTest is Test { /// at its deepest accepted octaves. function testMulExpRayMonotoneYHeadroomBoundaries() external pure { for (uint256 s0 = 1; s0 <= 126; ++s0) { - int256 q = int256(_SCALE_MAX >> s0); + int128 q = int128(uint128(_SCALE_MAX >> s0)); int256 kmax = int256(s0) - 3; for (int256 k = kmax; k >= kmax - 2 && k >= -60; --k) { int256 xb = _octaveStart(k); @@ -370,7 +384,7 @@ contract ExpTest is Test { /// Fuzz the bit-length headroom boundaries across the full accepted exponent range. function testFuzzMulExpRayMonotoneYHeadroom(uint256 us, int256 x) external pure { uint256 s0 = bound(us, 1, 126); - int256 q = int256(_SCALE_MAX >> s0); + int128 q = int128(uint128(_SCALE_MAX >> s0)); // The deepest x accepted by both magnitudes: octave count at most s0 - 3. x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s0) - 2) - 1); assertLe(Exp.mulExpRay(q, x), Exp.mulExpRay(q + 1, x), "y-monotonicity across headroom"); @@ -380,8 +394,8 @@ contract ExpTest is Test { /// Adjacent multipliers anywhere in the supported range, with the exponent bounded to the /// octaves both headrooms accept. function testFuzzMulExpRayMonotoneYAdjacent(uint256 uy, int256 x) external pure { - int256 y = int256(bound(uy, 1, _SCALE_MAX - 1)); - uint256 s = Clz.clz(uint256(y) + 1) - 129; + int128 y = int128(uint128(bound(uy, 1, _SCALE_MAX - 1))); + uint256 s = Clz.clz(uint256(uint128(y)) + 1) - 129; x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s) - 1) - 1); assertLe(Exp.mulExpRay(y, x), Exp.mulExpRay(y + 1, x), "adjacent y-monotonicity"); } From 7c82ba6c47f2eb223895ad40a50a1a672955a6dc Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 15:45:08 +0200 Subject: [PATCH 084/107] Narrow Exp return values to int128 Certify both generated-Yul return paths fit signed 128-bit words and model the compiler's int128 cleanup and ABI encoding. Co-Authored-By: OpenAI Codex --- .../ExpProof/ExpProof/Floor/PublicUncond.lean | 7 +- .../exp/ExpProof/ExpProof/Floor/R0Bound.lean | 2 +- .../ExpProof/ExpProof/Floor/R0BoundHolds.lean | 8 +- formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean | 12 +- .../ExpProof/ExpProof/Floor/RoundTrip.lean | 23 +- formal/exp/ExpProof/ExpProof/Mono/Quot.lean | 76 ++--- .../ExpProof/ExpProof/Mono/RangeNonneg.lean | 71 ++--- .../exp/ExpProof/ExpProof/Mono/RunBridge.lean | 13 +- formal/exp/ExpProof/ExpProof/Mono/Seam.lean | 4 +- formal/exp/ExpProof/ExpProof/Mono/Top.lean | 46 ++- formal/exp/ExpProof/ExpProof/Mul.lean | 13 +- formal/exp/ExpProof/ExpProof/Mul/Accum.lean | 105 ++++++- formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 22 +- formal/exp/ExpProof/ExpProof/Mul/Joint.lean | 4 +- formal/exp/ExpProof/ExpProof/Mul/Shell.lean | 22 +- .../exp/ExpProof/ExpProof/Mul/Transport.lean | 24 +- .../exp/ExpProof/ExpProof/Mul/WordBridge.lean | 152 +++++++++- formal/exp/ExpProof/ExpProof/Mul/XMono.lean | 12 +- .../ExpProof/ExpProof/Seam/Dispatcher.lean | 34 ++- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 63 ++++ .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 4 +- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 63 ++-- formal/exp/ExpProof/ExpProof/Seam/Revert.lean | 4 +- formal/exp/ExpProof/ExpProof/Seam/Value.lean | 284 +++++++++++++++--- formal/exp/ExpProof/ExpProof/Theorems.lean | 19 +- src/vendor/Exp.sol | 8 +- src/wrappers/ExpWrapper.sol | 4 +- test/0.8.34/Exp.t.sol | 14 +- 28 files changed, 859 insertions(+), 254 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/PublicUncond.lean b/formal/exp/ExpProof/ExpProof/Floor/PublicUncond.lean index b90bcec8b..47afdfb38 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/PublicUncond.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/PublicUncond.lean @@ -50,13 +50,16 @@ threshold the runtime result `r` satisfies the 2-wide never-over bracket `r ≤ theorem run_exp_ray_to_wad_evm_floorOrOneLess_uncond (x : Nat) (hx : x < 2 ^ 256) (hC0 : int256 x < int256 C0thresh) : ∃ r, run_exp_ray_to_wad_evm x = .ok r ∧ FloorOrOneLessBracket (int256 x) (int256 r) := by - refine ⟨expTree x, run_exp_ray_to_wad_evm_eq_expTree x (domain_of_below_C0 hx hC0), ?_⟩ + refine ⟨expTree x, + run_exp_ray_to_wad_evm_eq_expTree x (domain_of_below_C0 hx hC0) + (expTree_int128_word hx hC0), ?_⟩ by_cases hC : int256 Cmask < int256 x · by_cases hz : x = 0 · subst hz have he : expTree 0 = 1000000000000000000 := by have := run_exp_ray_to_wad_evm_zero - rw [run_exp_ray_to_wad_evm_eq_expTree 0 (domain_of_below_C0 hx hC0)] at this + rw [run_exp_ray_to_wad_evm_eq_expTree 0 (domain_of_below_C0 hx hC0) + (expTree_int128_word hx hC0)] at this exact Except.ok.inj this.symm rw [he] have h0 : int256 (1000000000000000000 : Nat) = (10 ^ 18 : Int) := by diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Bound.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Bound.lean index 4dacf1728..d798416aa 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Bound.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Bound.lean @@ -10,7 +10,7 @@ import Mathlib.Data.Complex.ExponentialBounds # Discharging the runtime `r0` bound The public floor brackets need the scaled quotient `r0Tree x` bracketed against the target -`E = 10¹⁸·exp(int256 x / 10²⁷)` across the octave shift `2^(68 − k)`. This file builds two +`E = 10¹⁸·exp(int256 x / 10²⁷)` across the octave shift `2^(67 − k)`. This file builds two ingredients of that discharge: * the **Horner-truncation bridge** for the even/odd accumulators — the runtime `evTree x`/`odTree x`, diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean b/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean index 7889737b8..88720ea76 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0BoundHolds.lean @@ -64,11 +64,11 @@ theorem accumReal_under (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 ((int256 (r0Tree x) : Real) - 1) + (2 ^ s : Real) := by rw [hfold] have hwad : (WAD : Real) = (10 ^ 18 : Real) := by unfold WAD; norm_num - have hs4 : (2 : Int) ≤ (s : Int) := by rw [hsint]; linarith [hkhi] - have hs4n : 2 ≤ s := by exact_mod_cast hs4 - have hpow : (2 ^ 2 : Real) ≤ (2 ^ s : Real) := pow_le_pow_right₀ (by norm_num) hs4n + have hs2 : (2 : Int) ≤ (s : Int) := by rw [hsint]; linarith [hkhi] + have hs2n : 2 ≤ s := by exact_mod_cast hs2 + have hpow : (2 ^ 2 : Real) ≤ (2 ^ s : Real) := pow_le_pow_right₀ (by norm_num) hs2n rw [hwad] - -- U + MARGIN < 2⁴ + -- U + MARGIN < 2² have hbudget : (2993 / 1000 : Real) + 1 < (2 ^ 2 : Real) := by norm_num linarith [hunder, hbudget, hpow] diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean index 8f4792c79..c7d32ce03 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean @@ -266,15 +266,15 @@ theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scal set Op := (odNumV (vTree x) : Int) with hOpdef have hr0m : (0:Int) ≤ r0 - (scale : Int) := by linarith [hr0ge] have hr0p : (0:Int) ≤ r0 + (scale : Int) := by linarith [hr0ge] - -- Ep·2^110·(r0−2^126) ≤ (2^637·ev + Wev·2^590)·(r0−2^126) + -- Ep·2^111·(r0−scale) ≤ (2^637·ev + Wev·2^591)·(r0−scale) have hterm1 : Ep * 2 ^ 111 * (r0 - (scale : Int)) ≤ (2 ^ 637 * ev + 72572599271425 * 2 ^ 591) * (r0 - (scale : Int)) := by apply mul_le_mul_of_nonneg_right _ hr0m nlinarith [hEp_hi] - -- −(t·Op)·(r0+2^126) ≤ −(2^637·tod)·(r0+2^126) + -- −(t·Op)·(r0+scale) ≤ −(2^637·tod)·(r0+scale) have hterm2 : 2 ^ 637 * tod * (r0 + (scale : Int)) ≤ t * Op * (r0 + (scale : Int)) := mul_le_mul_of_nonneg_right (by linarith [htOp_lo]) hr0p - -- floor: r0·den − 2^126·num ≤ 0, scaled by 2^637 + -- floor: r0·den − scale·num ≤ 0, scaled by 2^637 have hfloor : r0 * (ev - tod) - (scale : Int) * (ev + tod) ≤ 0 := by linarith [hfloor_lo] have hfloor638 : (2:Int) ^ 637 * (r0 * (ev - tod) - (scale : Int) * (ev + tod)) ≤ 0 := mul_nonpos_of_nonneg_of_nonpos (by positivity) hfloor @@ -1197,12 +1197,12 @@ theorem r0_real_over_within {x : Nat} (hx : x < 2 ^ 256) 2 * 4668745981919039833 / 10000000000000000000 := r0_real_over_within_wide hx (wideRegion_of_wad hC hC0) -/-! ## The octave real identity `E·2^(68−k) = WAD·2⁶⁸·exp(rt)` +/-! ## The octave real identity `E·2^(67−k) = WAD·2⁶⁷·exp(rt)` The target `E = WAD·exp(X/RAY)`. With `rt = X/RAY − k·ln2` the reduced argument, `exp(X/RAY) = -exp(rt)·2^k`, so the closing-shift fold `E·2^(68−k) = WAD·2⁶⁸·exp(rt)` (and `WAD·2⁶⁸ = scaleQ67`, +exp(rt)·2^k`, so the closing-shift fold `E·2^(67−k) = WAD·2⁶⁷·exp(rt)` (and `WAD·2⁶⁷ = scaleQ67`, the quotient's own scale). This collapses the never-over/deficit inequalities (stated against -`E·2^s`, `s = 68 − k`) onto the clean octave-independent relation `r0 ≈ scaleQ67·exp(rt)`. -/ +`E·2^s`, `s = 67 − k`) onto the clean octave-independent relation `r0 ≈ scaleQ67·exp(rt)`. -/ /-- `exp(X/RAY) = exp(rt)·2^k` (`k = int256 (kTree x)`, possibly negative; `2^k` is a real `zpow`). -/ theorem exp_X_over_RAY (x : Nat) : diff --git a/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean b/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean index cf45567c6..76e035b39 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/RoundTrip.lean @@ -60,7 +60,7 @@ theorem accumReal_over_strict (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < /-- **Accumulator deficit, region-uniform.** On the region the accumulator is below the target by strictly less than `39931/40000`: `E − 39931/40000 < accumReal x`. The deficit `r0 ≥ scaleQ67·exp(rt) − U` (`U = 2993/1000`) and the octave fold give -`accumReal x ≥ E − (U + MARGIN)/2^s` with `s = 68 − k ≥ 4`, and `(U + MARGIN)/2² ≈ 0.998 < 39931/40000`. +`accumReal x ≥ E − (U + MARGIN)/2^s` with `s = 67 − k ≥ 2`, and `(U + MARGIN)/2² ≈ 0.998 < 39931/40000`. The tightness below one is what closes the round trip together with `lnWadToRay`'s ≈10⁻⁹ envelope. -/ theorem accumReal_deficit_lt_one (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) @@ -72,11 +72,11 @@ theorem accumReal_deficit_lt_one (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask have hunder := r0_real_under_within hx hC hC0 obtain ⟨_, hkhi⟩ := kTree_bound hx hC hC0 set Ert := Real.exp (reducedArg x) with hErt - have hs4 : (2 : Int) ≤ (s : Int) := by rw [hsint]; linarith [hkhi] - have hs4n : 2 ≤ s := by exact_mod_cast hs4 - have hpow : (2 ^ 2 : Real) ≤ (2 ^ s : Real) := pow_le_pow_right₀ (by norm_num) hs4n + have hs2 : (2 : Int) ≤ (s : Int) := by rw [hsint]; linarith [hkhi] + have hs2n : 2 ≤ s := by exact_mod_cast hs2 + have hpow : (2 ^ 2 : Real) ≤ (2 ^ s : Real) := pow_le_pow_right₀ (by norm_num) hs2n -- (E − 39931/40000)·2^s < r0 − MARGIN, since E·2^s = scaleQ67·Ert ≤ r0 + U - -- and U + MARGIN < (39931/40000)·2⁴ ≤ (39931/40000)·2^s + -- and U + MARGIN < (39931/40000)·2² ≤ (39931/40000)·2^s have hbound : (expRayToWadTarget (int256 x) - 39931 / 40000) * (2 ^ s : Real) < (int256 (r0Tree x) : Real) - 1 := by have hkey : expRayToWadTarget (int256 x) * (2 ^ s : Real) = @@ -84,9 +84,10 @@ theorem accumReal_deficit_lt_one (x : Nat) (hx : x < 2 ^ 256) (hC : int256 Cmask have hwad : (WAD : Real) = (10 ^ 18 : Real) := by unfold WAD; norm_num rw [hwad] at hkey have hbudget : (2993 / 1000 : Real) + 1 < (39931 / 40000) * (2 ^ 2 : Real) := by norm_num - have h2425 : (39931 / 40000 : Real) * (2 ^ 2 : Real) ≤ (39931 / 40000) * (2 ^ s : Real) := + have hscaledBudget : + (39931 / 40000 : Real) * (2 ^ 2 : Real) ≤ (39931 / 40000) * (2 ^ s : Real) := mul_le_mul_of_nonneg_left hpow (by norm_num) - nlinarith [hunder, hkey, hbudget, hpow, h2425] + nlinarith [hunder, hkey, hbudget, hpow, hscaledBudget] rw [hAeq, lt_div_iff₀ hps]; linarith [hbound] /-! ## The `lnWadToRay` envelope on the round-trip band @@ -322,8 +323,9 @@ theorem run_exp_ray_to_wad_evm_lnWadToRay_roundTrip {w : Nat} (hlo : Wlo ≤ w) obtain ⟨x, hlnrun, hxlt, hle, hlt⟩ := lnWadToRay_band_run hlo hhi -- the exp target bracket + region membership for x's signed value obtain ⟨⟨hElt, hEle⟩, hCmask, hC0⟩ := expTarget_band (int256 x) hlo hhi hle hlt - refine ⟨x, expTree x, hlnrun, run_exp_ray_to_wad_evm_eq_expTree x (domain_of_below_C0 hxlt hC0), - ?_, ?_⟩ + refine ⟨x, expTree x, hlnrun, + run_exp_ray_to_wad_evm_eq_expTree x (domain_of_below_C0 hxlt hC0) + (expTree_int128_word hxlt hC0), ?_, ?_⟩ · -- scale point: w = 10^18 ⇒ x = 0 ⇒ expTree 0 = 10^18 intro hw subst hw @@ -334,7 +336,8 @@ theorem run_exp_ray_to_wad_evm_lnWadToRay_roundTrip {w : Nat} (hlo : Wlo ≤ w) subst hx0 have he : expTree 0 = 1000000000000000000 := by have := run_exp_ray_to_wad_evm_zero - rw [run_exp_ray_to_wad_evm_eq_expTree 0 (domain_of_below_C0 hxlt hC0)] at this + rw [run_exp_ray_to_wad_evm_eq_expTree 0 (domain_of_below_C0 hxlt hC0) + (expTree_int128_word hxlt hC0)] at this exact Except.ok.inj this rw [he]; norm_num · -- non scale point: x ≠ 0, region ⇒ body word = w − 1 diff --git a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean index e4c91e7de..d6132bc3d 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean @@ -3,13 +3,13 @@ import ExpProof.Mono.Stages /-! # The reciprocal-symmetric quotient stage -From the stage bounds this file assembles the closing quotient `r0 = ⌊scaleQ67·exp(t)⌋`: +From the stage bounds this file assembles the closing quotient +`r0 = ⌊scaleQ67·num/den⌋`: * `tod = ⌊t·Od / 2^129⌋` transported to `Int`, with `|tod| < 2^126`; * the numerator `num = ev + tod` and denominator `den = ev − tod` are strictly positive (the reduced argument keeps `|tod|` well below `ev`); -* `r0 = div(2^126·num, den)` — a plain `Nat` floor division — is at least `2^123` and below - `2^128`. +* the plain `Nat` floor division is at least `2^123` and below `2^129`. These give the range and nonnegativity obligations directly, and (via the cross-multiplication identity) reduce the within-octave monotonicity to a fact about `tod·ev`. @@ -156,17 +156,17 @@ theorem numden_pos {x : Nat} (hx : x < 2 ^ 256) /-! ## The runtime quotient `r0 = ⌊(10¹⁸·2⁶⁷)·num/den⌋` -/ /-- Abstract scaled-quotient bounds over opaque numerator/denominator words: `⌊scaleQ67·N/D⌋` -lies in `[2^124, 2^130)`. The dividend `scaleQ67·N` fits a word (`N < 2^129`, +lies in `[2^124, 2^129)`. The dividend `scaleQ67·N` fits a word (`N < 2^129`, `scaleQ67 < 2^127`); `2^124·D < 2^253 ≤ scaleQ67·N` keeps the quotient `≥ 2^124` (comfortably -clearing the closing stage's `r0 > MARGIN`), and `N < 4·D` with `4·scaleQ67 ≤ 2^130` keeps it -below `2^130`. -/ +clearing the closing stage's `r0 > MARGIN`), and `N < 4·D` with `4·scaleQ67 ≤ 2^129` keeps it +below `2^129`. -/ theorem r0Tree_bounds_of {N D : Nat} (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD : D < 2 ^ 256) (hDi : int256 D = (D : Int)) (hNpos : 0 < (N : Int)) (hDpos : 0 < (D : Int)) (hNlo : 2 ^ 127 ≤ N) (hND : (N : Int) < 4 * (D : Int)) : 2 ^ 124 ≤ int256 (evmDiv (evmMul scaleQ67 N) D) ∧ - int256 (evmDiv (evmMul scaleQ67 N) D) < 2 ^ 130 := by + int256 (evmDiv (evmMul scaleQ67 N) D) < 2 ^ 129 := by have hNw : N < 2 ^ 256 := by have : (2:Nat) ^ 128 < 2 ^ 256 := by norm_num omega @@ -181,14 +181,14 @@ theorem r0Tree_bounds_of {N D : Nat} (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD rw [hmul, evmDiv_eq hfit hD (by omega)] set q := scaleQ67 * N / D with hq have hspos : 0 < scaleQ67 := by unfold scaleQ67; norm_num - have hq_lt : q < 2 ^ 130 := by + have hq_lt : q < 2 ^ 129 := by rw [hq, Nat.div_lt_iff_lt_mul hDnat_pos] have hND' : N < 4 * D := by have h4 : ((4 * D : Nat) : Int) = 4 * (D : Int) := by push_cast; ring rw [← h4] at hND; exact_mod_cast hND have h1 : scaleQ67 * N < scaleQ67 * (4 * D) := (Nat.mul_lt_mul_left hspos).mpr hND' have h2 : scaleQ67 * (4 * D) = (4 * scaleQ67) * D := by ring - have h3 : (4 * scaleQ67) * D ≤ 2 ^ 130 * D := + have h3 : (4 * scaleQ67) * D ≤ 2 ^ 129 * D := Nat.mul_le_mul_right _ (by unfold scaleQ67; norm_num) omega have hq_ge : 2 ^ 124 ≤ q := by @@ -200,12 +200,12 @@ theorem r0Tree_bounds_of {N D : Nat} (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD have hqi : int256 (evmDiv (evmMul scaleQ67 N) D) = (q : Int) := by rw [hdiv] exact int256_of_lt (by - have : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num + have : (2:Nat) ^ 129 < 2 ^ 255 := by norm_num omega) rw [hqi] exact ⟨by exact_mod_cast hq_ge, by exact_mod_cast hq_lt⟩ -/-- Abstract runtime `r0` bounds over opaque even/odd words: `2^124 ≤ r0 < 2^130` with +/-- Abstract runtime `r0` bounds over opaque even/odd words: `2^124 ≤ r0 < 2^129` with `r0 = div(scaleQ67·(E+TD), E−TD)`. -/ theorem r0Tree_bounds_ofEvTod {E TD : Nat} (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) (hev_lo : (415147853590918758559635130244235626256 : Int) ≤ (E : Int)) @@ -213,20 +213,20 @@ theorem r0Tree_bounds_ofEvTod {E TD : Nat} (hevw : E < 2 ^ 256) (htodw : TD < 2 (htod_lo : -(85070591730234615865843651857942052864 : Int) ≤ int256 TD) (htod_hi : int256 TD < 85070591730234615865843651857942052864) : 2 ^ 124 ≤ int256 (evmDiv (evmMul scaleQ67 (evmAdd E TD)) (evmSub E TD)) ∧ - int256 (evmDiv (evmMul scaleQ67 (evmAdd E TD)) (evmSub E TD)) < 2 ^ 130 := by + int256 (evmDiv (evmMul scaleQ67 (evmAdd E TD)) (evmSub E TD)) < 2 ^ 129 := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_of hevw htodw hev_lo hev_hi htod_lo htod_hi have hNwlt : evmAdd E TD < 2 ^ 256 := evmAdd_lt _ _ have hDwlt : evmSub E TD < 2 ^ 256 := evmSub_lt _ _ - have h128 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num + have h129 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num have h127 : (3:Int) * 2 ^ 127 = 510423550381407695195061911147652317184 := by norm_num rw [h127] at hev_hi obtain ⟨hNi, hNlt255⟩ := int256_eq_of_nonneg hNwlt (by rw [hadd]; omega) obtain ⟨hDi, hDlt255⟩ := int256_eq_of_nonneg hDwlt (by rw [hsub]; omega) - have hNlt128 : evmAdd E TD < 2 ^ 129 := by - have : ((evmAdd E TD : Nat) : Int) < 2 ^ 129 := by rw [← hNi, hadd, h128]; omega + have hNlt129 : evmAdd E TD < 2 ^ 129 := by + have : ((evmAdd E TD : Nat) : Int) < 2 ^ 129 := by rw [← hNi, hadd, h129]; omega exact_mod_cast this - have hDlt128 : evmSub E TD < 2 ^ 129 := by - have : ((evmSub E TD : Nat) : Int) < 2 ^ 129 := by rw [← hDi, hsub, h128]; omega + have hDlt129 : evmSub E TD < 2 ^ 129 := by + have : ((evmSub E TD : Nat) : Int) < 2 ^ 129 := by rw [← hDi, hsub, h129]; omega exact_mod_cast this have hNlo : 2 ^ 127 ≤ evmAdd E TD := by have : (2 ^ 127 : Int) ≤ ((evmAdd E TD : Nat) : Int) := by @@ -237,11 +237,11 @@ theorem r0Tree_bounds_ofEvTod {E TD : Nat} (hevw : E < 2 ^ 256) (htodw : TD < 2 rw [← hNi, ← hDi, hadd, hsub]; omega have hNpos : 0 < ((evmAdd E TD : Nat) : Int) := by rw [← hNi, hadd]; omega have hDpos : 0 < ((evmSub E TD : Nat) : Int) := by rw [← hDi, hsub]; omega - exact r0Tree_bounds_of hNlt128 hDlt128 hDwlt hDi hNpos hDpos hNlo hND + exact r0Tree_bounds_of hNlt129 hDlt129 hDwlt hDi hNpos hDpos hNlo hND -/-- `2^124 ≤ r0Tree x < 2^130` on the wide region. -/ +/-- `2^124 ≤ r0Tree x < 2^129` on the wide region. -/ theorem r0Tree_bounds_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : - 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 130 := by + 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 129 := by obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW obtain ⟨hev_lo, hev_hi⟩ := evTree_facts hvlt obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound_wide hx hW @@ -261,13 +261,13 @@ theorem r0Tree_bounds_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : - 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 130 := + 2 ^ 124 ≤ int256 (r0Tree x) ∧ int256 (r0Tree x) < 2 ^ 129 := r0Tree_bounds_wide hx (wideRegion_of_wad hC hC0) /-! ## The scaled quotient at a symbolic scale -/ /-- Abstract scaled-quotient bounds at a symbolic scale `2^125 ≤ scale ≤ scaleMax`: `⌊scale·N/D⌋` -lies in `[2^123, 2^130)`. The lower bound is tight at the minimal scale: +lies in `[2^123, 2^129)`. The lower bound is tight at the minimal scale: `2^123·D < 2^123·2^129 = 2^125·2^127 ≤ scale·N`. -/ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD : D < 2 ^ 256) @@ -276,7 +276,7 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : (hNlo : 2 ^ 127 ≤ N) (hND : (N : Int) < 4 * (D : Int)) : 2 ^ 123 ≤ int256 (evmDiv (evmMul scale N) D) ∧ - int256 (evmDiv (evmMul scale N) D) < 2 ^ 130 := by + int256 (evmDiv (evmMul scale N) D) < 2 ^ 129 := by have hNw : N < 2 ^ 256 := by have : (2:Nat) ^ 128 < 2 ^ 256 := by norm_num omega @@ -291,17 +291,17 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : rw [hmul, evmDiv_eq hfit hD (by omega)] set q := scale * N / D with hq have hspos : 0 < scale := lt_of_lt_of_le (by norm_num) hslo - have hq_lt : q < 2 ^ 130 := by + have hq_lt : q < 2 ^ 129 := by rw [hq, Nat.div_lt_iff_lt_mul hDnat_pos] have hND' : N < 4 * D := by have h4 : ((4 * D : Nat) : Int) = 4 * (D : Int) := by push_cast; ring rw [← h4] at hND; exact_mod_cast hND have h1 : scale * N < scale * (4 * D) := (Nat.mul_lt_mul_left hspos).mpr hND' have h2 : scale * (4 * D) ≤ scaleMax * (4 * D) := Nat.mul_le_mul_right _ hshi - have h3 : scaleMax * (4 * D) ≤ 2 ^ 130 * D := by - have h4S : (4:Nat) * scaleMax ≤ 2 ^ 130 := by unfold scaleMax; norm_num + have h3 : scaleMax * (4 * D) ≤ 2 ^ 129 * D := by + have h4S : (4:Nat) * scaleMax ≤ 2 ^ 129 := by unfold scaleMax; norm_num calc scaleMax * (4 * D) = (4 * scaleMax) * D := by ring - _ ≤ 2 ^ 130 * D := Nat.mul_le_mul_right _ h4S + _ ≤ 2 ^ 129 * D := Nat.mul_le_mul_right _ h4S omega have hq_ge : 2 ^ 123 ≤ q := by rw [hq, Nat.le_div_iff_mul_le hDnat_pos] @@ -312,12 +312,12 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : have hqi : int256 (evmDiv (evmMul scale N) D) = (q : Int) := by rw [hdiv] exact int256_of_lt (by - have : (2:Nat) ^ 130 < 2 ^ 255 := by norm_num + have : (2:Nat) ^ 129 < 2 ^ 255 := by norm_num omega) rw [hqi] exact ⟨by exact_mod_cast hq_ge, by exact_mod_cast hq_lt⟩ -/-- Abstract scaled `r0` bounds over opaque even/odd words: `2^123 ≤ r0 < 2^130` with +/-- Abstract scaled `r0` bounds over opaque even/odd words: `2^123 ≤ r0 < 2^129` with `r0 = div(scale·(E+TD), E−TD)` at any `2^125 ≤ scale ≤ scaleMax`. -/ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) @@ -326,20 +326,20 @@ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) (htod_lo : -(85070591730234615865843651857942052864 : Int) ≤ int256 TD) (htod_hi : int256 TD < 85070591730234615865843651857942052864) : 2 ^ 123 ≤ int256 (evmDiv (evmMul scale (evmAdd E TD)) (evmSub E TD)) ∧ - int256 (evmDiv (evmMul scale (evmAdd E TD)) (evmSub E TD)) < 2 ^ 130 := by + int256 (evmDiv (evmMul scale (evmAdd E TD)) (evmSub E TD)) < 2 ^ 129 := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_of hevw htodw hev_lo hev_hi htod_lo htod_hi have hNwlt : evmAdd E TD < 2 ^ 256 := evmAdd_lt _ _ have hDwlt : evmSub E TD < 2 ^ 256 := evmSub_lt _ _ - have h128 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num + have h129 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num have h127 : (3:Int) * 2 ^ 127 = 510423550381407695195061911147652317184 := by norm_num rw [h127] at hev_hi obtain ⟨hNi, hNlt255⟩ := int256_eq_of_nonneg hNwlt (by rw [hadd]; omega) obtain ⟨hDi, hDlt255⟩ := int256_eq_of_nonneg hDwlt (by rw [hsub]; omega) - have hNlt128 : evmAdd E TD < 2 ^ 129 := by - have : ((evmAdd E TD : Nat) : Int) < 2 ^ 129 := by rw [← hNi, hadd, h128]; omega + have hNlt129 : evmAdd E TD < 2 ^ 129 := by + have : ((evmAdd E TD : Nat) : Int) < 2 ^ 129 := by rw [← hNi, hadd, h129]; omega exact_mod_cast this - have hDlt128 : evmSub E TD < 2 ^ 129 := by - have : ((evmSub E TD : Nat) : Int) < 2 ^ 129 := by rw [← hDi, hsub, h128]; omega + have hDlt129 : evmSub E TD < 2 ^ 129 := by + have : ((evmSub E TD : Nat) : Int) < 2 ^ 129 := by rw [← hDi, hsub, h129]; omega exact_mod_cast this have hNlo : 2 ^ 127 ≤ evmAdd E TD := by have : (2 ^ 127 : Int) ≤ ((evmAdd E TD : Nat) : Int) := by @@ -350,12 +350,12 @@ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) rw [← hNi, ← hDi, hadd, hsub]; omega have hNpos : 0 < ((evmAdd E TD : Nat) : Int) := by rw [← hNi, hadd]; omega have hDpos : 0 < ((evmSub E TD : Nat) : Int) := by rw [← hDi, hsub]; omega - exact r0Scaled_bounds_of hslo hshi hNlt128 hDlt128 hDwlt hDi hNpos hDpos hNlo hND + exact r0Scaled_bounds_of hslo hshi hNlt129 hDlt129 hDwlt hDi hNpos hDpos hNlo hND -/-- `2^123 ≤ r0ScaledTree scale x < 2^130` on the wide region, for `2^125 ≤ scale ≤ scaleMax`. -/ +/-- `2^123 ≤ r0ScaledTree scale x < 2^129` on the wide region, for `2^125 ≤ scale ≤ scaleMax`. -/ theorem r0Scaled_bounds {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : - 2 ^ 123 ≤ int256 (r0ScaledTree scale x) ∧ int256 (r0ScaledTree scale x) < 2 ^ 130 := by + 2 ^ 123 ≤ int256 (r0ScaledTree scale x) ∧ int256 (r0ScaledTree scale x) < 2 ^ 129 := by obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW obtain ⟨hev_lo, hev_hi⟩ := evTree_facts hvlt obtain ⟨htod_lo, htod_hi, _, _⟩ := todTree_bound_wide hx hW diff --git a/formal/exp/ExpProof/ExpProof/Mono/RangeNonneg.lean b/formal/exp/ExpProof/ExpProof/Mono/RangeNonneg.lean index b673bae42..57a46f2e8 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/RangeNonneg.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/RangeNonneg.lean @@ -3,14 +3,14 @@ import ExpProof.Mono.Quot /-! # The range and nonnegativity obligations of `RegionMonotonicityFacts` -`r1Tree x = shr(68 − k, r0 − MARGIN)` closes the kernel: the quotient already carries the -`10¹⁸·2⁶⁸` output scale, so the closing stage subtracts the one-sided margin and floors with the +`r1Tree x = shr(67 − k, r0 − MARGIN)` closes the kernel: the quotient already carries the +`10¹⁸·2⁶⁷` output scale, so the closing stage subtracts the one-sided margin and floors with the `2ᵏ` octave scaling folded into the shift (`67 − k ∈ [2, 128]`). * **nonneg**: `r0 ≥ 2^124` gives `r0 > MARGIN`, and the shift argument is nonnegative; the logical shift of a canonical nonnegative word stays nonnegative. -* **range**: `r0 < 2^130` keeps the shift argument below `2^130`, and the `≥ 4` shift floors it - below `2^126 < 2^254`. +* **range**: `r0 < 2^129` keeps the shift argument below `2^129`, and the at-least-two-bit shift + floors it below `2^127 < 2^254`. -/ namespace ExpYul @@ -30,16 +30,16 @@ theorem closing_shift {x : Nat} (hx : x < 2 ^ 256) (s : Int) = 67 - int256 (kTree x) := by obtain ⟨hklo, hkhi⟩ := kTree_bound hx hC hC0 have hkw : kTree x < 2 ^ 256 := by unfold kTree; exact evmSar_lt _ _ - -- 68 (as int) - int256 k, transported through evmSub - have h68 : int256 (0x43 : Nat) = 67 := by + -- 67 (as int) - int256 k, transported through evmSub + have h67 : int256 (0x43 : Nat) = 67 := by rw [int256_of_lt (by norm_num)]; simp have hip255 : (2:Int)^255 = 57896044618658097711785492504343953926634992332820282019728792003956564819968 := by norm_num have hsub : int256 (evmSub 0x43 (kTree x)) = 67 - int256 (kTree x) := by have := evmSub_transport (a := 0x43) (b := kTree x) (by norm_num) hkw - (by rw [h68, hip255]; omega) - (by rw [h68, hip255]; omega) - rw [h68] at this; exact this + (by rw [h67, hip255]; omega) + (by rw [h67, hip255]; omega) + rw [h67] at this; exact this -- the result is a small nonnegative word, so its Nat value is 67 - int256 k have hsublt : evmSub 0x43 (kTree x) < 2 ^ 256 := evmSub_lt _ _ have hnn : 0 ≤ int256 (evmSub 0x43 (kTree x)) := by rw [hsub]; omega @@ -55,22 +55,22 @@ theorem closing_shift {x : Nat} (hx : x < 2 ^ 256) /-! ## The shift argument `r0 − MARGIN` -/ /-- Abstract bound on the shift argument `r0 − MARGIN` over an opaque `r0` word in -`[2^124, 2^130)`: its signed value is in `[2^124 − MARGIN, 2^130)`, in particular nonnegative -and below `2^130`. -/ +`[2^124, 2^129)`: its signed value is in `[2^124 − MARGIN, 2^129)`, in particular nonnegative +and below `2^129`. -/ theorem shiftArg_bounds_of {r0 : Nat} (hr0w : r0 < 2 ^ 256) - (hr0_lo : (2 ^ 124 : Int) ≤ int256 r0) (hr0_hi : int256 r0 < 2 ^ 130) : + (hr0_lo : (2 ^ 124 : Int) ≤ int256 r0) (hr0_hi : int256 r0 < 2 ^ 129) : int256 (evmSub r0 0x1) = int256 r0 - 0x1 ∧ 0 ≤ int256 r0 - 0x1 ∧ - int256 r0 - 0x1 < 2 ^ 130 := by + int256 r0 - 0x1 < 2 ^ 129 := by have hmarlt : (0x1 : Nat) < 2 ^ 256 := by norm_num have hmari : int256 (0x1 : Nat) = 0x1 := by rw [int256_of_lt (by norm_num)]; simp have hp124 : (2:Int)^124 = 21267647932558653966460912964485513216 := by norm_num - have hp130 : (2:Int)^130 = 1361129467683753853853498429727072845824 := by norm_num + have hp129 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num have hip255 : (2:Int)^255 = 57896044618658097711785492504343953926634992332820282019728792003956564819968 := by norm_num rw [hp124] at hr0_lo - rw [hp130] at hr0_hi + rw [hp129] at hr0_hi have hsub : int256 (evmSub r0 0x1) = int256 r0 - 0x1 := by have := evmSub_transport hr0w hmarlt (by rw [hmari]; simp only [ipow255]; omega) @@ -80,26 +80,26 @@ theorem shiftArg_bounds_of {r0 : Nat} (hr0w : r0 < 2 ^ 256) /-! ## Abstract floor facts for the closing shift -/ -/-- Abstract closing-shift facts over an opaque shift argument word `W` and shift `s ∈ [4, 129]` -with `int256 W ∈ [0, 2^130)`: the floor `shr(s, W)` is nonnegative and below `2^126`. -/ +/-- Abstract closing-shift facts over an opaque shift argument word `W` and shift `s ∈ [2, 128]` +with `int256 W ∈ [0, 2^129)`: the floor `shr(s, W)` is nonnegative and below `2^127`. -/ theorem closingShr_facts {W s : Nat} (hWw : W < 2 ^ 256) (hslo : 2 ≤ s) (hshi : s ≤ 128) - (hWnn : 0 ≤ int256 W) (hWhi : int256 W < 2 ^ 130) : - 0 ≤ int256 (evmShr s W) ∧ int256 (evmShr s W) < 2 ^ 128 := by + (hWnn : 0 ≤ int256 W) (hWhi : int256 W < 2 ^ 129) : + 0 ≤ int256 (evmShr s W) ∧ int256 (evmShr s W) < 2 ^ 127 := by obtain ⟨hWi, _⟩ := int256_eq_of_nonneg hWw hWnn - have hWnat : W < 2 ^ 130 := by - have : ((W : Nat) : Int) < 2 ^ 130 := by rw [← hWi]; exact hWhi + have hWnat : W < 2 ^ 129 := by + have : ((W : Nat) : Int) < 2 ^ 129 := by rw [← hWi]; exact hWhi exact_mod_cast this rw [evmShr_eq_div (by omega) hWw] - have hqlt : W / 2 ^ s < 2 ^ 128 := by + have hqlt : W / 2 ^ s < 2 ^ 127 := by have h4 : (2:Nat) ^ 2 ≤ 2 ^ s := Nat.pow_le_pow_right (by norm_num) hslo have h1 : W / 2 ^ s ≤ W / 2 ^ 2 := Nat.div_le_div_left h4 (Nat.two_pow_pos _) - have h2 : W / 2 ^ 2 < 2 ^ 128 := by + have h2 : W / 2 ^ 2 < 2 ^ 127 := by rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] - calc W < 2 ^ 130 := hWnat - _ = 2 ^ 128 * 2 ^ 2 := by rw [← Nat.pow_add] + calc W < 2 ^ 129 := hWnat + _ = 2 ^ 127 * 2 ^ 2 := by rw [← Nat.pow_add] omega rw [int256_of_lt (by - have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + have : (2:Nat) ^ 127 < 2 ^ 255 := by norm_num omega)] constructor · positivity @@ -123,27 +123,30 @@ theorem r1Tree_int256_nonneg {x : Nat} (hx : x < 2 ^ 256) exact (closingShr_facts (evmSub_lt _ _) hslo hshi (by rw [hargeq]; omega) (by rw [hargeq]; omega)).1 -/-- **`range`**: `r1Tree x < 2^254` on the meaningful region. -/ -theorem r1Tree_range {x : Nat} (hx : x < 2 ^ 256) +/-- The closing-shift result fits in the nonnegative half of `int128`. -/ +theorem r1Tree_int128_range {x : Nat} (hx : x < 2 ^ 256) (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : - r1Tree x < 2 ^ 254 := by + r1Tree x < 2 ^ 127 := by obtain ⟨s, hseq, hslo, hshi, _⟩ := closing_shift hx hC hC0 obtain ⟨hr0lo, hr0hi⟩ := r0Tree_bounds hx hC hC0 obtain ⟨hargeq, hargnn, harghi⟩ := shiftArg_bounds_of (r0 := r0Tree x) (r0Tree_lt x) hr0lo hr0hi have hr1 : r1Tree x = evmShr (evmSub 0x43 (kTree x)) (evmSub (r0Tree x) 0x1) := rfl obtain ⟨hnn, hlt⟩ := closingShr_facts (W := evmSub (r0Tree x) 0x1) (s := s) (evmSub_lt _ _) hslo hshi (by rw [hargeq]; omega) (by rw [hargeq]; omega) - -- int256 (r1Tree x) ∈ [0, 2^126) ⇒ the Nat word is < 2^254 have hReq : int256 (r1Tree x) = int256 (evmShr s (evmSub (r0Tree x) 0x1)) := by rw [hr1, hseq] rw [← hReq] at hnn hlt have hr1w : r1Tree x < 2 ^ 256 := r1Tree_lt x obtain ⟨hi, _⟩ := int256_eq_of_nonneg hr1w hnn - have hp254 : (2:Int)^128 < 2^254 := by norm_num - have hcast : ((r1Tree x : Nat) : Int) < 2 ^ 254 := by + have hcast : ((r1Tree x : Nat) : Int) < 2 ^ 127 := by rw [← hi] - generalize int256 (r1Tree x) = V at hlt ⊢ - omega + exact hlt exact_mod_cast hcast +/-- **`range`**: `r1Tree x < 2^254` on the meaningful region. -/ +theorem r1Tree_range {x : Nat} (hx : x < 2 ^ 256) + (hC : int256 Cmask < int256 x) (hC0 : int256 x < int256 C0thresh) : + r1Tree x < 2 ^ 254 := + lt_trans (r1Tree_int128_range hx hC hC0) (by norm_num) + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mono/RunBridge.lean b/formal/exp/ExpProof/ExpProof/Mono/RunBridge.lean index 90e9cfa35..13833825b 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/RunBridge.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/RunBridge.lean @@ -19,9 +19,18 @@ set_option maxRecDepth 100000 /-- `expTree x` is the inline value tree. -/ theorem run_exp_ray_to_wad_evm_eq_expTree (x : Nat) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (expTree x)) = + FormalYul.word (expTree x)) : run_exp_ray_to_wad_evm x = .ok (expTree x) := by - rw [run_exp_ray_to_wad_evm_eq_tree x hval] + have hcleanTree := hresultClean + unfold expTree r1Tree r0Tree todTree odTree evTree vTree tTree kTree at hcleanTree + unfold Cmask kRoundShift kHalfShift cInvQ192 k27Q235 ln2Q235 tArgShift squareShift at hcleanTree + unfold ev0 ev1 ev2 ev3 ev4 evShift1 evShift2 evShift3 evShift4 at hcleanTree + unfold od0 od1 od2 od3 od4 odShift1 odShift2 odShift3 odShift4 at hcleanTree + unfold todShift foldShift scaleQ67 marginWord at hcleanTree + rw [run_exp_ray_to_wad_evm_eq_tree x hval hcleanTree] unfold expTree r1Tree r0Tree todTree odTree evTree vTree tTree kTree unfold Cmask kRoundShift kHalfShift cInvQ192 k27Q235 ln2Q235 tArgShift squareShift unfold ev0 ev1 ev2 ev3 ev4 evShift1 evShift2 evShift3 evShift4 diff --git a/formal/exp/ExpProof/ExpProof/Mono/Seam.lean b/formal/exp/ExpProof/ExpProof/Mono/Seam.lean index 5a4a19abb..ef03ad6e0 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Seam.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Seam.lean @@ -70,7 +70,7 @@ theorem seam_close {arg1 arg2 s1 s2 : Nat} rw [int256_of_lt hq1lt, int256_of_lt hq2lt] exact_mod_cast hqle -/-- The closing shifts at a seam differ by one (`s2 = s1 − 1`), both in `[4, 129]`. -/ +/-- The closing shifts at a seam differ by one (`s2 = s1 − 1`), both in `[2, 128]`. -/ theorem seam_closing_shifts {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hC1 : int256 Cmask < int256 x1) (hC01 : int256 x1 < int256 C0thresh) (hx2 : x2 < 2 ^ 256) (hC2 : int256 Cmask < int256 x2) (hC02 : int256 x2 < int256 C0thresh) @@ -80,7 +80,7 @@ theorem seam_closing_shifts {x1 x2 : Nat} obtain ⟨s1, hs1eq, _, hs1hi, hs1int⟩ := closing_shift hx1 hC1 hC01 obtain ⟨s2, hs2eq, hs2lo, _, hs2int⟩ := closing_shift hx2 hC2 hC02 refine ⟨s1, s2, hs1eq, hs2eq, by omega, by omega, ?_⟩ - -- `(s2 : Int) + 1 = 68 − k2 + 1 = 68 − k1 = (s1 : Int)` + -- `(s2 : Int) + 1 = 67 − k2 + 1 = 67 − k1 = (s1 : Int)` have : (s2 : Int) + 1 = (s1 : Int) := by rw [hs1int, hs2int, hk]; ring omega diff --git a/formal/exp/ExpProof/ExpProof/Mono/Top.lean b/formal/exp/ExpProof/ExpProof/Mono/Top.lean index cc5352876..837b488eb 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Top.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Top.lean @@ -3,6 +3,7 @@ import ExpProof.Mono.ShellOn import ExpProof.Mono.RunBridge import ExpProof.Mono.Pin import ExpProof.Mono.Seam +import ExpProof.Mul.WordBridge /-! # Top-level monotonicity reduction @@ -30,7 +31,7 @@ set_option maxRecDepth 100000 /-- The analytic monotonicity facts on the meaningful region `int256 C < int256 x < C0` (for canonical words). -/ structure RegionMonotonicityFacts : Prop where - /-- `r1Tree` never exceeds `≈ 2^123 < 2^254`. -/ + /-- This bound prevents signed-word wrap in the arithmetic comparisons below. -/ range : ∀ x : Nat, x < 2 ^ 256 → int256 Cmask < int256 x → int256 x < int256 C0thresh → r1Tree x < 2 ^ 254 /-- `0 ≤ r1Tree` on the region (the floored `exp` value is never negative). -/ @@ -149,6 +150,47 @@ theorem domain_of_below_C0 {x : Nat} (hx : x < 2 ^ 256) (h : int256 x < int256 C rw [hC0]; exact_mod_cast h · right; omega +theorem expTree_int128_range {x : Nat} (hx : x < 2 ^ 256) + (hdom : int256 x < int256 C0thresh) : expTree x < 2 ^ 127 := by + have hu : u256 x = x := u256_id hx + have huC : u256 Cmask = Cmask := u256_id Cmask_lt + by_cases hC : int256 Cmask < int256 x + · by_cases hx0 : x = 0 + · subst hx0 + have hzero : expTree 0 = 1000000000000000000 := by + unfold expTree + rw [r1Tree_zero] + decide + rw [hzero] + norm_num + · have hr1 := r1Tree_int128_range hx hC hdom + have hmask : int256 (u256 Cmask) < int256 (u256 x) := by + rw [huC, hu] + exact hC + have heq := int256_expTree_of_gt hmask + (lt_trans hr1 (by norm_num : (2 : Nat) ^ 127 < 2 ^ 254)) + rw [hu, if_neg hx0] at heq + have hnn : 0 ≤ int256 (expTree x) := by + rw [heq] + positivity + obtain ⟨hi, _⟩ := int256_eq_of_nonneg (expTree_lt x) hnn + have hcast : ((expTree x : Nat) : Int) < 2 ^ 127 := by + rw [← hi, heq] + simp only [zero_add] + exact_mod_cast hr1 + exact_mod_cast hcast + · have hle : int256 (u256 x) ≤ int256 (u256 Cmask) := by + rw [hu, huC] + omega + rw [expTree_eq_zero_of_le hle] + norm_num + +theorem expTree_int128_word {x : Nat} (hx : x < 2 ^ 256) + (hdom : int256 x < int256 C0thresh) : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (expTree x)) = + FormalYul.word (expTree x) := + signextend_15_nonnegative (expTree_int128_range hx hdom) + /-- **Runtime monotonicity.** Under the region monotonicity facts, the compiled `expRayToWad` signed results are `≤`-ordered for ordered canonical inputs strictly below the supported threshold (the entire non-reverting `int256` domain). -/ @@ -160,7 +202,9 @@ theorem run_exp_ray_to_wad_evm_mono (H : RegionMonotonicityFacts) (x1 x2 : Nat) have hdom1 : int256 x1 < int256 C0thresh := lt_of_le_of_lt hle hdom refine ⟨expTree x1, expTree x2, ?_, ?_, ?_⟩ · exact run_exp_ray_to_wad_evm_eq_expTree x1 (domain_of_below_C0 hx1 hdom1) + (expTree_int128_word hx1 hdom1) · exact run_exp_ray_to_wad_evm_eq_expTree x2 (domain_of_below_C0 hx2 hdom) + (expTree_int128_word hx2 hdom) · exact expTree_mono H hx1 hx2 hle hdom /-- **Runtime monotonicity, modulo the octave seam.** With `range`/`nonneg` and the diff --git a/formal/exp/ExpProof/ExpProof/Mul.lean b/formal/exp/ExpProof/ExpProof/Mul.lean index 2246a82c0..a8d3909d5 100644 --- a/formal/exp/ExpProof/ExpProof/Mul.lean +++ b/formal/exp/ExpProof/ExpProof/Mul.lean @@ -60,8 +60,13 @@ theorem mulExpRay_run_bracket_zero_of_run {x : Nat} theorem run_mul_exp_ray_evm_zero_of_guard (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : run_mul_exp_ray_evm 0 x = .ok 0 := by + have hresultClean : + EvmYul.UInt256.signextend (word 15) (word (mulExpTree 0 x)) = + word (mulExpTree 0 x) := by + rw [mulExpTree_zero] + exact int128Word_zero.2 simpa [mulExpTree_zero] using - run_mul_exp_ray_evm_eq_tree_of_guard 0 x int128CalldataWord_zero.2 hguard + run_mul_exp_ray_evm_eq_tree_of_guard 0 x int128Word_zero.2 hresultClean hguard /-- The compiled runtime satisfies the public bracket spec at zero magnitude whenever the guard accepts. -/ @@ -69,12 +74,6 @@ theorem mulExpRay_run_bracket_zero (x : Nat) (hguard : mulExpGuardTree 0 x = 0) MulExpRayRunBracket 0 x := mulExpRay_run_bracket_zero_of_run (run_mul_exp_ray_evm_zero_of_guard x hguard) -/-- **Value path on the domain.** Accepted inputs return the compiled arithmetic tree. -/ -theorem run_mul_exp_ray_evm_eq_tree {y x : Nat} (h : MulExpRayValueDomain y x) : - run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := - run_mul_exp_ray_evm_eq_tree_of_guard y x h.1.1.2 - ((valueDomain_iff_guard_eq_zero h.1).mp h) - /-- **Panic revert.** Rejected inputs revert. -/ theorem run_mul_exp_ray_evm_revert {y x : Nat} (h : MulExpRayPanicDomain y x) : run_mul_exp_ray_evm y x = .error "revert" := diff --git a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean index d038e75b5..ea241bf41 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean @@ -79,13 +79,13 @@ noncomputable section /-! ## The live-region magnitude bracket -/ /-- **Live-region magnitude bracket.** On the live region the kernel magnitude `m` is a -nonnegative value below `2^128` with `m ≤ A < m + 2`. -/ +nonnegative value below `2^127` with `m ≤ A < m + 2`. -/ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : 0 ≤ int256 (mulMagnitudeTree y x) ∧ - int256 (mulMagnitudeTree y x) < 2 ^ 128 ∧ + int256 (mulMagnitudeTree y x) < 2 ^ 127 ∧ (int256 (mulMagnitudeTree y x) : Real) ≤ mulExpRayMagnitudeTarget (int256 y) (int256 x) ∧ mulExpRayMagnitudeTarget (int256 y) (int256 x) < (int256 (mulMagnitudeTree y x) : Real) + 2 := by @@ -110,17 +110,17 @@ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 2 have hsub : evmSub (r0MulTree y x) marginWord = r0MulTree y x - 1 := by unfold marginWord exact evmSub_small hr0nat1 hr0w - have hr0nat130 : r0MulTree y x < 2 ^ 130 := by - have h : ((r0MulTree y x : Nat) : Int) < 2 ^ 130 := by rw [← hr0i]; exact hr0hi + have hr0nat129 : r0MulTree y x < 2 ^ 129 := by + have h : ((r0MulTree y x : Nat) : Int) < 2 ^ 129 := by rw [← hr0i]; exact hr0hi exact_mod_cast h set W := r0MulTree y x - 1 with hWdef - have hWnat130 : W < 2 ^ 130 := lt_of_le_of_lt (Nat.sub_le _ _) hr0nat130 - have hWw : W < 2 ^ 256 := lt_trans hWnat130 (by norm_num) - have hWi : int256 W = (W : Int) := int256_of_lt (lt_trans hWnat130 (by norm_num)) + have hWnat129 : W < 2 ^ 129 := lt_of_le_of_lt (Nat.sub_le _ _) hr0nat129 + have hWw : W < 2 ^ 256 := lt_trans hWnat129 (by norm_num) + have hWi : int256 W = (W : Int) := int256_of_lt (lt_trans hWnat129 (by norm_num)) have hWnn : 0 ≤ int256 W := by rw [hWi]; exact Int.natCast_nonneg _ - have hWhi : int256 W < 2 ^ 130 := by + have hWhi : int256 W < 2 ^ 129 := by rw [hWi] - exact_mod_cast hWnat130 + exact_mod_cast hWnat129 -- the closing-shift word obtain ⟨hsh2, hsh256, hsheq⟩ := mulShift_word_facts hy hx habs hW hlive set sh := mulShiftTree y x with hshdef @@ -248,9 +248,9 @@ theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256 exact ⟨le_refl 0, by simpa using hmle, by rw [neg_zero]; simpa using hmlt2⟩ · rw [mulExpTree_negative hlo hy hmpos] have hmnat255 : mulMagnitudeTree y x < 2 ^ 255 := by - have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 128 := by rw [← hmi]; exact hmlt - have h' : mulMagnitudeTree y x < 2 ^ 128 := by exact_mod_cast h - have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 127 := by rw [← hmi]; exact hmlt + have h' : mulMagnitudeTree y x < 2 ^ 127 := by exact_mod_cast h + have : (2:Nat) ^ 127 < 2 ^ 255 := by norm_num omega have hres : int256 (2 ^ 256 - mulMagnitudeTree y x) = -(int256 (mulMagnitudeTree y x)) := by unfold int256 @@ -266,6 +266,87 @@ theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256 rw [if_pos hyneg, neg_neg] exact ⟨hm0, hmle, hmlt2⟩ +/-! ## Result range -/ + +theorem mulExpTree_int128_range_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) + (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) + (hx0 : int256 x ≠ 0) (hW : WideRegion x) + (hlive : 2 ≤ int256 (mulShiftTree y x)) : + -(2 ^ 127 : Int) ≤ int256 (mulExpTree y x) ∧ + int256 (mulExpTree y x) < 2 ^ 127 := by + obtain ⟨hm0, hmlt, _, _⟩ := mulMagnitude_bracket_live hy hx hy0 habs hx0 hW hlive + have hmagw : mulMagnitudeTree y x < 2 ^ 256 := mulMagnitudeTree_lt y x + obtain ⟨hmi, _⟩ := int256_eq_of_nonneg hmagw hm0 + have hmnat127 : mulMagnitudeTree y x < 2 ^ 127 := by + have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 127 := by + rw [← hmi] + exact hmlt + exact_mod_cast h + by_cases hneg : y < 2 ^ 255 + · rw [mulExpTree_pos (Nat.pos_of_ne_zero hy0) hneg] + exact ⟨by omega, hmlt⟩ + · have hlo : 2 ^ 255 ≤ y := by omega + rcases Nat.eq_zero_or_pos (mulMagnitudeTree y x) with hmz | hmpos + · have hzero : mulExpTree y x = 0 := by + unfold mulExpTree + rw [hmz] + unfold evmMul + rw [u256_self (by norm_num : (0 : Nat) < 2 ^ 256)] + simp [u256, WORD_MOD] + rw [hzero, int256_zero_word] + norm_num + · rw [mulExpTree_negative hlo hy hmpos] + have hres : int256 (2 ^ 256 - mulMagnitudeTree y x) = + -(int256 (mulMagnitudeTree y x)) := by + unfold int256 + rw [if_neg (by omega), if_pos (lt_trans hmnat127 (by norm_num))] + omega + rw [hres] + constructor + · exact neg_le_neg (le_of_lt hmlt) + · exact lt_of_le_of_lt (neg_nonpos.mpr hm0) (by norm_num) + +theorem mulExpTree_int128_range {y x : Nat} (h : MulExpRayValueDomain y x) : + -(2 ^ 127 : Int) ≤ int256 (mulExpTree y x) ∧ + int256 (mulExpTree y x) < 2 ^ 127 := by + obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ := h + have habs : absTree y ≤ scaleMax := + (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale + rcases Nat.eq_zero_or_pos y with hy0 | hypos + · subst hy0 + rw [mulExpTree_zero, int256_zero_word] + norm_num + by_cases hclamp : int256 x ≤ int256 mulExpRayZeroMax + · rw [mulExpTree_clamped hx hclamp, int256_zero_word] + norm_num + by_cases hx0 : int256 x = 0 + · have hxw0 : x = 0 := (int256_zero_iff_of_canonical hx).mp hx0 + subst hxw0 + rw [mulExpTree_scale_point hy.1 habs] + have habsNat : (int256 y).natAbs < 2 ^ 127 := by + rw [← absTree_eq_natAbs hy.1] + exact lt_of_le_of_lt habs scaleMax_lt_2127 + have habsInt : (((int256 y).natAbs : Nat) : Int) < 2 ^ 127 := by + exact_mod_cast habsNat + by_cases hyneg : int256 y < 0 + · rw [Int.ofNat_natAbs_of_nonpos (le_of_lt hyneg)] at habsInt + omega + · rw [Int.natAbs_of_nonneg (not_lt.mp hyneg)] at habsInt + omega + · exact mulExpTree_int128_range_live hy.1 hx (by omega) habs hx0 + ⟨by omega, hxhi⟩ hlive + +theorem mulExpTree_int128_word {y x : Nat} (h : MulExpRayValueDomain y x) : + Int128Word (mulExpTree y x) := by + have hrange := mulExpTree_int128_range h + have hword := mulExpTree_lt y x + exact ⟨hword, signextend_15_eq_self_of_int256_range hword hrange.1 hrange.2⟩ + +theorem run_mul_exp_ray_evm_eq_tree {y x : Nat} (h : MulExpRayValueDomain y x) : + run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := + run_mul_exp_ray_evm_eq_tree_of_guard y x h.1.1.2 (mulExpTree_int128_word h).2 + ((valueDomain_iff_guard_eq_zero h.1).mp h) + /-! ## The bracket on the whole value domain -/ /-- **The public runtime bracket on the value domain.** Every accepted input returns a result diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean index ed3990c1a..2c728b58c 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -18,26 +18,26 @@ open FormalYul.Preservation set_option maxRecDepth 100000 -/-- A canonical ABI word for an `int128` argument. -/ -def Int128CalldataWord (y : Nat) : Prop := - y < 2 ^ 256 ∧ - EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y +/-- A canonical EVM word for an `int128` value. -/ +def Int128Word (w : Nat) : Prop := + w < 2 ^ 256 ∧ + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word w) = FormalYul.word w -theorem int128CalldataWord_zero : Int128CalldataWord 0 := by - unfold Int128CalldataWord +theorem int128Word_zero : Int128Word 0 := by + unfold Int128Word decide -theorem int128CalldataWord_scaleMax : Int128CalldataWord scaleMax := by - unfold Int128CalldataWord +theorem int128Word_scaleMax : Int128Word scaleMax := by + unfold Int128Word decide -theorem int128CalldataWord_min : Int128CalldataWord (2 ^ 256 - 2 ^ 127) := by - unfold Int128CalldataWord +theorem int128Word_min : Int128Word (2 ^ 256 - 2 ^ 127) := by + unfold Int128Word decide /-- ABI words transported into this proof layer. -/ def MulExpRayCanonical (y x : Nat) : Prop := - Int128CalldataWord y ∧ x < 2 ^ 256 + Int128Word y ∧ x < 2 ^ 256 /-- The exact successful-input domain induced by the implementation guard. -/ def MulExpRayValueDomain (y x : Nat) : Prop := diff --git a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean index 446cfbddb..3f9e93450 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean @@ -39,7 +39,7 @@ theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleMax) : · exact scaleShift_antitone hpos hab hb /-- Shrinking the magnitude keeps an accepted input accepted: the headroom shift only grows. -/ -theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : Int128CalldataWord y1) +theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : Int128Word y1) (h2 : MulExpRayValueDomain y2 x) (hab : absTree y1 ≤ absTree y2) : MulExpRayValueDomain y1 x := by obtain ⟨⟨_, hx⟩, hscale2, hxhi, hlv2⟩ := h2 @@ -252,7 +252,7 @@ the maximal scale. -/ theorem run_mul_exp_ray_evm_revert_int128_min {x : Nat} (hx : x < 2 ^ 256) : run_mul_exp_ray_evm (2 ^ 256 - 2 ^ 127) x = .error "revert" := by apply run_mul_exp_ray_evm_revert - refine ⟨⟨int128CalldataWord_min, hx⟩, Or.inl ?_⟩ + refine ⟨⟨int128Word_min, hx⟩, Or.inl ?_⟩ have hiff := scaleShiftTree_le_127_iff (absTree_lt (2 ^ 256 - 2 ^ 127)) by_contra hshift have hcap := hiff.mp diff --git a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean index 5eaa4507c..ae6f5664a 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean @@ -407,7 +407,7 @@ theorem mulExpTree_clamped {y x : Nat} (hx : x < 2 ^ 256) private theorem int256_zero_word : int256 (0 : Nat) = 0 := by unfold int256; norm_num /-- **Scale point.** `mulExpRay(y, 0)` returns `y` whenever the two-bit closing-shift guard accepts. -/ -theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : Int128CalldataWord y) +theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := by obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy.1 habs @@ -416,11 +416,16 @@ theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : Int128CalldataWord y) refine ⟨hs127, ?_, hshift⟩ rw [int256_mulExpRayHi, int256_zero_word] norm_num - have h := run_mul_exp_ray_evm_eq_tree_of_guard y 0 hy.2 hguard + have hresultClean : + EvmYul.UInt256.signextend (word 15) (word (mulExpTree y 0)) = + word (mulExpTree y 0) := by + rw [mulExpTree_scale_point hy.1 habs] + exact hy.2 + have h := run_mul_exp_ray_evm_eq_tree_of_guard y 0 hy.2 hresultClean hguard rwa [mulExpTree_scale_point hy.1 habs] at h /-- **Clamp.** An accepted `mulExpRay(y, x)` returns zero at or below the zero cutoff. -/ -theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) +theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : run_mul_exp_ray_evm y x = .ok 0 := by @@ -431,7 +436,12 @@ theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : Int128CalldataWord y) (hx rw [int256_mulExpRayHi] rw [int256_mulExpRayZeroMax] at hclamp omega - have h := run_mul_exp_ray_evm_eq_tree_of_guard y x hy.2 hguard + have hresultClean : + EvmYul.UInt256.signextend (word 15) (word (mulExpTree y x)) = + word (mulExpTree y x) := by + rw [mulExpTree_clamped hx hclamp] + exact int128Word_zero.2 + have h := run_mul_exp_ray_evm_eq_tree_of_guard y x hy.2 hresultClean hguard rwa [mulExpTree_clamped hx hclamp] at h /-! ## Shell brackets -/ @@ -439,7 +449,7 @@ theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : Int128CalldataWord y) (hx noncomputable section /-- **Scale-point bracket.** The exact result `y` satisfies the public bracket at `x = 0`. -/ -theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : Int128CalldataWord y) +theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := by refine ⟨y, run_mul_exp_ray_evm_scale_point hy habs hshift, ?_⟩ @@ -505,7 +515,7 @@ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) _ < 1 := hexp1 /-- **Clamp bracket.** The zero result satisfies the public bracket at or below the cutoff. -/ -theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) +theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : MulExpRayRunBracket y x := by diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean index f264b828a..e2db20200 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -237,7 +237,7 @@ theorem scaleMax_octave_neg_two_valueDomain {x : Nat} (hx : x < 2 ^ 256) rw [mulShiftTree_transport_global hcap, hs, hk] norm_num exact ⟨hs, hshift, - ⟨⟨int128CalldataWord_scaleMax, hx⟩, by rw [hs]; norm_num, hxhi, by omega⟩⟩ + ⟨⟨int128Word_scaleMax, hx⟩, by rw [hs]; norm_num, hxhi, by omega⟩⟩ /-- The closing-shift word carries the signed difference `S − k` on the wide region. -/ theorem mulShiftTree_transport {y x : Nat} (_hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) @@ -270,26 +270,26 @@ theorem mulShift_word_facts {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) have h254 : mulShiftTree y x ≤ 254 := by exact_mod_cast this omega -/-- Closing `shr` at any shift `s ∈ [2, 255]`: a nonnegative argument below `2^130` floors to a -nonnegative value below `2^128`. -/ +/-- Closing `shr` at any shift `s ∈ [2, 255]`: a nonnegative argument below `2^129` floors to a +nonnegative value below `2^127`. -/ theorem mulShr_facts {W s : Nat} (hWw : W < 2 ^ 256) (hslo : 2 ≤ s) (hshi : s ≤ 255) - (hWnn : 0 ≤ int256 W) (hWhi : int256 W < 2 ^ 130) : - 0 ≤ int256 (evmShr s W) ∧ int256 (evmShr s W) < 2 ^ 128 := by + (hWnn : 0 ≤ int256 W) (hWhi : int256 W < 2 ^ 129) : + 0 ≤ int256 (evmShr s W) ∧ int256 (evmShr s W) < 2 ^ 127 := by obtain ⟨hWi, _⟩ := int256_eq_of_nonneg hWw hWnn - have hWnat : W < 2 ^ 130 := by - have : ((W : Nat) : Int) < 2 ^ 130 := by rw [← hWi]; exact hWhi + have hWnat : W < 2 ^ 129 := by + have : ((W : Nat) : Int) < 2 ^ 129 := by rw [← hWi]; exact hWhi exact_mod_cast this rw [evmShr_eq_div (by omega) hWw] - have hqlt : W / 2 ^ s < 2 ^ 128 := by + have hqlt : W / 2 ^ s < 2 ^ 127 := by have h4 : (2:Nat) ^ 2 ≤ 2 ^ s := Nat.pow_le_pow_right (by norm_num) hslo have h1 : W / 2 ^ s ≤ W / 2 ^ 2 := Nat.div_le_div_left h4 (Nat.two_pow_pos _) - have h2 : W / 2 ^ 2 < 2 ^ 128 := by + have h2 : W / 2 ^ 2 < 2 ^ 127 := by rw [Nat.div_lt_iff_lt_mul (Nat.two_pow_pos _)] - calc W < 2 ^ 130 := hWnat - _ = 2 ^ 128 * 2 ^ 2 := by rw [← Nat.pow_add] + calc W < 2 ^ 129 := hWnat + _ = 2 ^ 127 * 2 ^ 2 := by rw [← Nat.pow_add] omega rw [int256_of_lt (by - have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + have : (2:Nat) ^ 127 < 2 ^ 255 := by norm_num omega)] constructor · positivity diff --git a/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean b/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean index 61e2b5584..0940a4a86 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean @@ -1,10 +1,11 @@ import ExpProof.Mono.WordFacts /-! -# Word-level bridges for the `mulExpRay` guard +# Word-level bridges for signed Exp values and `mulExpRay` guards -Comparison and boolean-word facts that translate the compiled guard word into signed -predicates. They complement `Mono.WordFacts` without disturbing its downstream consumers. +Signed-width cleanup applies to both public Exp results. Comparison and boolean-word facts connect +the `mulExpRay` guard operations to their arithmetic predicates. These facts extend +`Mono.WordFacts`. -/ namespace ExpYul @@ -13,6 +14,8 @@ open FormalYul open FormalYul.Preservation open Common.Word +set_option maxRecDepth 100000 + /-- `evmSgt` is `evmSlt` with the operands swapped. -/ theorem evmSgt_eq_evmSlt_swap (a b : Nat) : evmSgt a b = evmSlt b a := rfl @@ -58,4 +61,147 @@ theorem evmAnd_ite (c d : Prop) [Decidable c] [Decidable d] : unfold evmAnd u256 WORD_MOD split_ifs <;> simp_all +private theorem word_and (a b : Nat) : + word a &&& word b = word (evmAnd a b) := by + simpa only [word] using + FormalYul.Preservation.uint256_ofNat_and_eq_word_evmAnd a b + +private theorem word_or (a b : Nat) : + word a ||| word b = word (evmOr a b) := by + simpa only [word] using + FormalYul.Preservation.uint256_ofNat_or_eq_word_evmOr a b + +private theorem signextend_15_eq_ite (w : Nat) : + EvmYul.UInt256.signextend (word 15) (word w) = + if word w &&& word (2 ^ 127) ≠ word 0 then + word w ||| word (2 ^ 256 - 2 ^ 127) + else + word w &&& word (2 ^ 127 - 1) := by + unfold EvmYul.UInt256.signextend + rw [if_pos (by decide)] + change + (if word w &&& word (2 ^ 127) ≠ word 0 then + word w ||| word (2 ^ 256 - 2 ^ 127) + else + word w &&& word (2 ^ 127 - 1)) = _ + rfl + +private theorem and_pow127_eq_zero_of_lt {n : Nat} (hn : n < 2 ^ 127) : + n &&& 2 ^ 127 = 0 := by + apply Nat.eq_of_testBit_eq + intro i + simp only [Nat.testBit_and, Nat.testBit_two_pow] + by_cases hi : i = 127 + · subst i + simp [Nat.testBit_lt_two_pow hn] + · simp [Ne.symm hi] + +private theorem testBit_pow256_sub_pos_le_pow127 {n : Nat} (hnpos : 0 < n) + (hn : n ≤ 2 ^ 127) : + (2 ^ 256 - n).testBit 127 = true := by + have hnrepr : n = (n - 1) + 1 := by omega + rw [hnrepr, Nat.testBit_two_pow_sub_succ (by omega : n - 1 < 2 ^ 256)] + simp [Nat.testBit_lt_two_pow (by omega : n - 1 < 2 ^ 127)] + +private theorem and_pow127_eq_pow127_of_testBit {n : Nat} + (hbit : n.testBit 127 = true) : + n &&& 2 ^ 127 = 2 ^ 127 := by + apply Nat.eq_of_testBit_eq + intro i + simp only [Nat.testBit_and, Nat.testBit_two_pow] + by_cases hi : i = 127 + · subst i + simp [hbit] + · simp [Ne.symm hi] + +private theorem or_sign_mask_eq_self {n : Nat} (hnpos : 0 < n) (hn : n ≤ 2 ^ 127) : + (2 ^ 256 - n) ||| (2 ^ 256 - 2 ^ 127) = 2 ^ 256 - n := by + let low := 2 ^ 127 - n + let high := 2 ^ 129 - 1 + have hlowDef : low = 2 ^ 127 - n := rfl + have hhighDef : high = 2 ^ 129 - 1 := rfl + have hlow : low < 2 ^ 127 := by + rw [hlowDef] + omega + have hmask : 2 ^ 256 - 2 ^ 127 = 2 ^ 127 * high := by + rw [hhighDef] + calc + 2 ^ 256 - 2 ^ 127 = 2 ^ 127 * 2 ^ 129 - 2 ^ 127 := by + rw [show 256 = 127 + 129 by omega, Nat.pow_add] + _ = 2 ^ 127 * (2 ^ 129 - 1) := by + rw [Nat.mul_sub_left_distrib, Nat.mul_one] + have hword : 2 ^ 256 - n = 2 ^ 127 * high + low := by + rw [← hmask] + rw [hlowDef] + omega + have hconcat : 2 ^ 127 * high + low = 2 ^ 127 * high ||| low := + Nat.two_pow_add_eq_or_of_lt hlow high + calc + (2 ^ 256 - n) ||| (2 ^ 256 - 2 ^ 127) = + (2 ^ 127 * high ||| low) ||| 2 ^ 127 * high := by rw [hword, hmask, hconcat] + _ = 2 ^ 127 * high ||| low := by + rw [Nat.or_assoc, Nat.or_comm low (2 ^ 127 * high), ← Nat.or_assoc, Nat.or_self] + _ = 2 ^ 256 - n := by rw [← hconcat, ← hword] + +theorem signextend_15_nonnegative {n : Nat} (hn : n < 2 ^ 127) : + EvmYul.UInt256.signextend (word 15) (word n) = word n := by + have hlandZero : word n &&& word (2 ^ 127) = word 0 := by + rw [word_and, FormalYul.Preservation.evmAnd_eq_of_lt] + · rw [and_pow127_eq_zero_of_lt hn] + · simpa [WORD_MOD] using lt_trans hn (by norm_num : 2 ^ 127 < 2 ^ 256) + · norm_num [WORD_MOD] + have hlandSelf : word n &&& word (2 ^ 127 - 1) = word n := by + rw [word_and, FormalYul.Preservation.evmAnd_eq_of_lt] + · rw [Nat.and_two_pow_sub_one_of_lt_two_pow hn] + · simpa [WORD_MOD] using lt_trans hn (by norm_num : 2 ^ 127 < 2 ^ 256) + · norm_num [WORD_MOD] + rw [signextend_15_eq_ite, hlandZero, if_neg (by simp), hlandSelf] + +theorem signextend_15_negative {n : Nat} (hnpos : 0 < n) (hn : n ≤ 2 ^ 127) : + EvmYul.UInt256.signextend (word 15) (word (2 ^ 256 - n)) = word (2 ^ 256 - n) := by + have hlandSign : + word (2 ^ 256 - n) &&& word (2 ^ 127) = word (2 ^ 127) := by + rw [word_and, FormalYul.Preservation.evmAnd_eq_of_lt] + · rw [and_pow127_eq_pow127_of_testBit (testBit_pow256_sub_pos_le_pow127 hnpos hn)] + · norm_num [WORD_MOD] + omega + · norm_num [WORD_MOD] + have hlorSelf : + word (2 ^ 256 - n) ||| word (2 ^ 256 - 2 ^ 127) = + word (2 ^ 256 - n) := by + rw [word_or, FormalYul.Preservation.evmOr_eq_of_lt] + · rw [or_sign_mask_eq_self hnpos hn] + · norm_num [WORD_MOD] + omega + · norm_num [WORD_MOD] + rw [signextend_15_eq_ite, hlandSign, if_pos (by decide), hlorSelf] + +theorem signextend_15_canonical {w : Nat} + (hw : w < 2 ^ 127 ∨ ∃ n, 0 < n ∧ n ≤ 2 ^ 127 ∧ w = 2 ^ 256 - n) : + EvmYul.UInt256.signextend (word 15) (word w) = word w := by + rcases hw with hw | ⟨n, hnpos, hn, rfl⟩ + · exact signextend_15_nonnegative hw + · exact signextend_15_negative hnpos hn + +theorem signextend_15_eq_self_of_int256_range {w : Nat} (hw : w < 2 ^ 256) + (hlo : -(2 ^ 127 : Int) ≤ int256 w) (hhi : int256 w < 2 ^ 127) : + EvmYul.UInt256.signextend (word 15) (word w) = word w := by + apply signextend_15_canonical + by_cases hpos : w < 2 ^ 255 + · left + have hwi : int256 w = (w : Int) := int256_of_lt hpos + have h : ((w : Nat) : Int) < 2 ^ 127 := by rw [← hwi]; exact hhi + exact_mod_cast h + · right + have hwloInt : (2 ^ 256 : Int) - 2 ^ 127 ≤ (w : Int) := by + unfold int256 at hlo + rw [if_neg hpos] at hlo + omega + have hbaseCast : ((2 ^ 256 - 2 ^ 127 : Nat) : Int) = + (2 ^ 256 : Int) - 2 ^ 127 := by norm_num + have hwlo : 2 ^ 256 - 2 ^ 127 ≤ w := by + rw [← hbaseCast] at hwloInt + exact_mod_cast hwloInt + refine ⟨2 ^ 256 - w, by omega, by omega, by omega⟩ + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean index d7d01611a..3bd256fdc 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean @@ -62,7 +62,7 @@ theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW : WideRegion x) : int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 ∧ - 0 ≤ int256 (r0MulTree y x) - 1 ∧ int256 (r0MulTree y x) - 1 < 2 ^ 130 := by + 0 ≤ int256 (r0MulTree y x) - 1 ∧ int256 (r0MulTree y x) - 1 < 2 ^ 129 := by have hpos : 1 ≤ absTree y := absTree_pos hy hy0 have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs obtain ⟨_, _, hshi⟩ := mulScaleTree_spec hy habs @@ -76,9 +76,9 @@ theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) rw [int256_of_lt (by norm_num)] norm_num have hp123 : (2:Int)^123 = 10633823966279326983230456482242756608 := by norm_num - have hp130 : (2:Int)^130 = 1361129467683753853853498429727072845824 := by norm_num + have hp129 : (2:Int)^129 = 680564733841876926926749214863536422912 := by norm_num rw [hp123] at hr0lo - rw [hp130] at hr0hi + rw [hp129] at hr0hi have hsub : int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 := by have := evmSub_transport hr0w hmarlt (by rw [hmari]; simp only [ipow255]; linarith [hr0lo, hr0hi]) @@ -553,9 +553,9 @@ theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) mulMagnitudeTree y x < 2 ^ 255 := by obtain ⟨hm0, hmlt, _, _⟩ := mulMagnitude_bracket_live hy hx hy0 habs hx0 hW hlive obtain ⟨hmi, _⟩ := int256_eq_of_nonneg (mulMagnitudeTree_lt y x) hm0 - have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 128 := by rw [← hmi]; exact hmlt - have h' : mulMagnitudeTree y x < 2 ^ 128 := by exact_mod_cast h - have : (2:Nat) ^ 128 < 2 ^ 255 := by norm_num + have h : ((mulMagnitudeTree y x : Nat) : Int) < 2 ^ 127 := by rw [← hmi]; exact hmlt + have h' : mulMagnitudeTree y x < 2 ^ 127 := by exact_mod_cast h + have : (2:Nat) ^ 127 < 2 ^ 255 := by norm_num omega /-! ## Magnitude monotonicity over the live region -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean index fea6343d2..753ecfc00 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Dispatcher.lean @@ -409,28 +409,29 @@ theorem call_allocate_unbounded_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -/-- `abi_encode_t_int256_to_t_int256_fromStack(value, pos) := mstore(pos, cleanup(value))`, -specialized to a literal `value = word v` (the only shape the return path needs). -/ -theorem call_abi_encode_t_int256_to_t_int256_fromStack_direct +/-- `abi_encode_t_int128_to_t_int128_fromStack(value, pos)` stores the signed-128 cleanup of +`value`. -/ +theorem call_abi_encode_t_int128_to_t_int128_fromStack_direct (v : Nat) (pos : EvmYul.UInt256) (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : EvmYul.Yul.call (fuel + 90) [FormalYul.word v, pos] - (.some "abi_encode_t_int256_to_t_int256_fromStack") + (.some "abi_encode_t_int128_to_t_int128_fromStack") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok ((EvmYul.Yul.State.Ok shared store).setMachineState - ((EvmYul.Yul.State.Ok shared store).toMachineState.mstore pos (FormalYul.word v)), []) := by + ((EvmYul.Yul.State.Ok shared store).toMachineState.mstore pos + (EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word v))), []) := by rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_abi_encode_t_int256_to_t_int256_fromStack] - simp only [yulFunction_abi_encode_t_int256_to_t_int256_fromStack, + lookup_abi_encode_t_int128_to_t_int128_fromStack] + simp only [yulFunction_abi_encode_t_int128_to_t_int128_fromStack, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hcleanup := - call_cleanup_t_int256_direct (v := v) (fuel := fuel) (extra := 64) (shared := shared) + call_cleanup_t_int128_direct (v := v) (fuel := fuel) (extra := 64) (shared := shared) (store := Finmap.insert "value" (FormalYul.word v) (Finmap.insert "pos" pos (Inhabited.default : EvmYul.Yul.VarStore))) (hlookup := hlookup) @@ -444,29 +445,30 @@ theorem call_abi_encode_t_int256_to_t_int256_fromStack_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, FormalYul.word, hcleanup] -/-- `abi_encode_tuple_t_int256__to_t_int256__fromStack(headStart, value)` encodes a single `int256` -return value (`value = word v`) and returns the tail pointer `headStart + 32`. -/ -theorem call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct +/-- `abi_encode_tuple_t_int128__to_t_int128__fromStack(headStart, value)` encodes one signed-128 +return value and returns the tail pointer `headStart + 32`. -/ +theorem call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart : EvmYul.UInt256) (v : Nat) (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : EvmYul.Yul.call (fuel + 150) [headStart, FormalYul.word v] - (.some "abi_encode_tuple_t_int256__to_t_int256__fromStack") + (.some "abi_encode_tuple_t_int128__to_t_int128__fromStack") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok ((EvmYul.Yul.State.Ok shared store).setMachineState - ((EvmYul.Yul.State.Ok shared store).toMachineState.mstore headStart (FormalYul.word v)), + ((EvmYul.Yul.State.Ok shared store).toMachineState.mstore headStart + (EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word v))), [headStart + FormalYul.word 32]) := by rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_abi_encode_tuple_t_int256__to_t_int256__fromStack] - simp only [yulFunction_abi_encode_tuple_t_int256__to_t_int256__fromStack, + lookup_abi_encode_tuple_t_int128__to_t_int128__fromStack] + simp only [yulFunction_abi_encode_tuple_t_int128__to_t_int128__fromStack, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hencode := - call_abi_encode_t_int256_to_t_int256_fromStack_direct + call_abi_encode_t_int128_to_t_int128_fromStack_direct (v := v) (pos := headStart + FormalYul.word 0) (fuel := fuel + 55) (shared := shared) (store := Finmap.insert "tail" (headStart + FormalYul.word 32) diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 25133cc0e..f0356768b 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -44,6 +44,28 @@ theorem call_zero_value_for_split_t_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +/-- `zero_value_for_split_t_int128()` returns the word `0`. -/ +theorem call_zero_value_for_split_t_int128_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [] (.some "zero_value_for_split_t_int128") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_zero_value_for_split_t_int128] + simp only [yulFunction_zero_value_for_split_t_int128, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + /-- `zero_value_for_split_t_uint256()` returns the word `0`. -/ theorem call_zero_value_for_split_t_uint256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -667,6 +689,47 @@ theorem call_convert_uint256_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] +/-- `convert_t_int256_to_t_int128(value)` returns the signed-128 cleanup of `value`. -/ +theorem call_convert_int256_to_int128_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word v] + (.some "convert_t_int256_to_t_int128") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, + [EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word v)]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_int256_to_t_int128] + simp only [yulFunction_convert_t_int256_to_t_int128, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_int256_direct (v := v) (fuel := fuel + extra) (extra := 92) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := v) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int128_direct (v := v) (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + theorem call_fun__octave_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index c77452058..50298e444 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -49,7 +49,7 @@ theorem call_fun_mulExpRay_revert_direct let k := kTree x let shift := evmSub s k have hzeroInit := - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2176) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2176) (shared := shared) (hlookup := hlookup) have hzeroUint1 := call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2173) @@ -210,7 +210,7 @@ theorem call_fun_wrap_mulExpRay_revert_direct EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.setStore, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2276) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2276) (shared := shared) (hlookup := hlookup), hinner] diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 0bbf00c6a..7e1d61e22 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -30,6 +30,9 @@ theorem call_fun_mulExpRay_direct some (FormalYul.accountFor yulContract)) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : EvmYul.Yul.call (fuel + (extra + 2200)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = @@ -50,7 +53,7 @@ theorem call_fun_mulExpRay_direct let shift := evmSub s k let scale := evmShl s ay have hzeroInit := - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2176) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2176) (shared := shared) (hlookup := hlookup) have hzeroUint1 := call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2173) @@ -124,9 +127,12 @@ theorem call_fun_mulExpRay_direct call_fun__expRayKernel_direct (x := x) (k := k) (scale := scale) (shift := shift) (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1436) (shared := shared) (hlookup := hlookup) - have hconvertOut := + have hconvertInt256 := call_convert_uint256_to_int256_direct (v := mulExpTree y x) (fuel := fuel + extra) (extra := 2011) (shared := shared) (hlookup := hlookup) + have hconvertNarrow := + call_convert_int256_to_int128_direct (v := mulExpTree y x) (fuel := fuel + extra) + (extra := 2010) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz @@ -163,7 +169,7 @@ theorem call_fun_mulExpRay_direct tArgShift, k27Q235, ln2Q235, squareShift, ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, - todShift, marginWord, scaleMaxClz, mulExpRayZeroMax] at hconvertOut + todShift, marginWord, scaleMaxClz, mulExpRayZeroMax] at hconvertInt256 hconvertNarrow have hguardUnfold : evmOr (evmOr @@ -192,7 +198,7 @@ theorem call_fun_mulExpRay_direct hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hOrOut, hconvertTwo, hcleanupShift, hOrGuard, hscaleShift, - hconvertShiftOut, hZM, hkernel, hconvertOut, + hconvertShiftOut, hZM, hkernel, hconvertInt256, hconvertNarrow, FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, FormalYul.Preservation.uint256_ofNat_lt_eq_word_evmLt, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, @@ -210,6 +216,7 @@ theorem call_fun_mulExpRay_direct todShift, marginWord, scaleShiftTree, absTree, signTree, kTree, scaleMaxClz, mulExpRayZeroMax, hclean] + simpa only [FormalYul.word] using hresultClean set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay(y, x)` forwards to the value path. -/ @@ -219,6 +226,9 @@ theorem call_fun_wrap_mulExpRay_direct some (FormalYul.accountFor yulContract)) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : EvmYul.Yul.call (fuel + (extra + 2300)) [FormalYul.word y, FormalYul.word x] (.some yulName_fun_wrap_mulExpRay) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = @@ -233,7 +243,8 @@ theorem call_fun_wrap_mulExpRay_direct EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hinner := call_fun_mulExpRay_direct (y := y) (x := x) (fuel := fuel + extra) (extra := 89) - (shared := shared) (hlookup := hlookup) (hclean := hclean) (hguard := hguard) + (shared := shared) (hlookup := hlookup) (hclean := hclean) + (hresultClean := hresultClean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_mulExpRay] at hinner simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', @@ -243,7 +254,7 @@ theorem call_fun_wrap_mulExpRay_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 2276) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2276) (shared := shared) (hlookup := hlookup), hinner] @@ -253,6 +264,9 @@ theorem external_fun_wrap_mulExpRay_calldata_result (y x : Nat) (store : EvmYul.Yul.VarStore) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -300,14 +314,15 @@ theorem external_fun_wrap_mulExpRay_calldata_result (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) (hguard := hguard) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) + (hresultClean := hresultClean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap have halloc := call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr y x) (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup y x) simp only [FormalYul.word, baseStore] at halloc have hencode := - call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart := memPos) (v := mulExpTree y x) (fuel := 999831) (shared := memShared) (store := encStore) (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup y x]) @@ -341,7 +356,7 @@ theorem external_fun_wrap_mulExpRay_calldata_result change FormalYul.wordNat (EvmYul.UInt256.ofNat (mulExpTree y x)) = mulExpTree y x exact (FormalYul.Preservation.wordNat_ofNat (mulExpTree y x)).trans (FormalYul.Preservation.u256_eq_of_lt _ (mulExpTree_lt y x)) - rw [hnat] + exact (congrArg (fun w => Except.ok w.toNat) hresultClean).trans (congrArg Except.ok hnat) set_option maxHeartbeats 12000000 in /-- The external `mulExpRay` entrypoint on the value path halts (returns). -/ @@ -349,6 +364,9 @@ theorem external_fun_wrap_mulExpRay_calldata_halts (y x : Nat) (store : EvmYul.Yul.VarStore) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -390,14 +408,15 @@ theorem external_fun_wrap_mulExpRay_calldata_halts (store := Finmap.insert "param_0" (FormalYul.word y) (Finmap.insert "param_1" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) (hguard := hguard) + (hlookup := mulExpSharedAfterFreePtr_lookup y x) (hclean := hclean) + (hresultClean := hresultClean) (hguard := hguard) simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_wrap_mulExpRay] at hwrap have halloc := call_allocate_unbounded_direct (fuel := 999962) (shared := mulExpSharedAfterFreePtr y x) (store := baseStore) (hlookup := mulExpSharedAfterFreePtr_lookup y x) simp only [FormalYul.word, baseStore] at halloc have hencode := - call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart := memPos) (v := mulExpTree y x) (fuel := 999831) (shared := memShared) (store := encStore) (hlookup := by simp [memShared, mulExpSharedAfterFreePtr_lookup y x]) @@ -424,6 +443,9 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_result (y x : Nat) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -465,7 +487,7 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_result (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) - hclean hguard + hclean hresultClean hguard set_option maxHeartbeats 12000000 in /-- Halt, starting from the exact state the dispatcher hands the external `mulExpRay` @@ -474,6 +496,9 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_halts (y x : Nat) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_mulExpRay) (.some yulContract) @@ -509,19 +534,23 @@ theorem external_fun_wrap_mulExpRay_dispatcher_state_halts (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) (Inhabited.default : EvmYul.Yul.VarStore)) - hclean hguard + hclean hresultClean hguard set_option maxHeartbeats 12000000 in -/-- **Value path.** When the guard word is zero, the compiled runtime returns the signed -dynamic-scale arithmetic tree — for every multiplier, including zero. -/ +/-- **Value path.** With canonical input and result words, a zero guard makes the compiled runtime +return the signed dynamic-scale arithmetic tree — for every multiplier, including zero. -/ theorem run_mul_exp_ray_evm_eq_tree_of_guard (y x : Nat) (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word y) = FormalYul.word y) + (hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word (mulExpTree y x)) = + FormalYul.word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := by obtain ⟨haltState, _haltValue, hhalt⟩ := - external_fun_wrap_mulExpRay_dispatcher_state_halts y x hclean hguard - have hresult := external_fun_wrap_mulExpRay_dispatcher_state_result y x hclean hguard + external_fun_wrap_mulExpRay_dispatcher_state_halts y x hclean hresultClean hguard + have hresult := + external_fun_wrap_mulExpRay_dispatcher_state_result y x hclean hresultClean hguard rw [hhalt] at hresult have hReturn : FormalYul.Preservation.DispatcherReturn yulContract diff --git a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean index 37b7c1775..22169ddb3 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean @@ -101,7 +101,7 @@ theorem call_fun_expRayToWad_revert_direct EvmYul.Yul.State.setStore, FormalYul.word, slt_thresh_ge h1 h2, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 976) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 976) (shared := shared) (hlookup := hlookup), call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 826) (shared := shared) (hlookup := hlookup), @@ -137,7 +137,7 @@ theorem call_fun_wrap_expRayToWad_revert_direct EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.setStore, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 1176) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 1176) (shared := shared) (hlookup := hlookup), h70] diff --git a/formal/exp/ExpProof/ExpProof/Seam/Value.lean b/formal/exp/ExpProof/ExpProof/Seam/Value.lean index e6097d01a..7a67293f3 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Value.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Value.lean @@ -112,11 +112,14 @@ theorem call_fun_expRayToWad_zero_direct have hkernel := call_fun__expRayKernel_zero_direct (fuel := fuel + extra) (extra := 173) (shared := shared) (hlookup := hlookup) - have hconvertOut := + have hconvertInt256 := call_convert_uint256_to_int256_direct (v := 1000000000000000000) (fuel := fuel + extra) (extra := 752) (shared := shared) (hlookup := hlookup) + have hconvertNarrow := + call_convert_int256_to_int128_direct (v := 1000000000000000000) (fuel := fuel + extra) + (extra := 751) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hoctave hscale hconv67 - simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertOut + simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertInt256 hconvertNarrow simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -126,10 +129,10 @@ theorem call_fun_expRayToWad_zero_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 876) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 876) (shared := shared) (hlookup := hlookup), hconstHi, hcleanupHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, - hzeroCutoff, hkernel, hconvertOut, k] + hzeroCutoff, hkernel, hconvertInt256, hconvertNarrow, k] set_option maxHeartbeats 8000000 in /-- `fun_wrap_expRayToWad` at `x = 0` forwards to `fun_expRayToWad`, giving `10^18`. -/ @@ -160,7 +163,7 @@ theorem call_fun_wrap_expRayToWad_zero_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 1076) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 1076) (shared := shared) (hlookup := hlookup), h70] @@ -217,11 +220,14 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_result (store := baseStore) (hlookup := expSharedAfterFreePtr_lookup 0) simp only [FormalYul.word, baseStore] at halloc have hencode := - call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart := memPos) (v := 1000000000000000000) (fuel := 999831) (shared := memShared) (store := encStore) (hlookup := by simp [memShared, expSharedAfterFreePtr_lookup 0]) simp [FormalYul.word, memShared, encStore, memPos, baseStore] at hencode + have hresultClean : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word 1000000000000000000) = + FormalYul.word 1000000000000000000 := by decide simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -251,7 +257,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_result change FormalYul.wordNat (EvmYul.UInt256.ofNat 1000000000000000000) = 1000000000000000000 exact (FormalYul.Preservation.wordNat_ofNat 1000000000000000000).trans (FormalYul.Preservation.u256_eq_of_lt _ (by decide)) - rw [hnat] + exact (congrArg (fun w => Except.ok w.toNat) hresultClean).trans (congrArg Except.ok hnat) set_option maxHeartbeats 12000000 in /-- The external entrypoint at `x = 0` halts (returns), as opposed to reverting. -/ @@ -300,7 +306,7 @@ theorem external_fun_wrap_expRayToWad_zero_calldata_halts (store := baseStore) (hlookup := expSharedAfterFreePtr_lookup 0) simp only [FormalYul.word, baseStore] at halloc have hencode := - call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart := memPos) (v := 1000000000000000000) (fuel := 999831) (shared := memShared) (store := encStore) (hlookup := by simp [memShared, expSharedAfterFreePtr_lookup 0]) @@ -509,12 +515,36 @@ theorem call_fun__expRayKernel_direct set_option maxHeartbeats 4000000 in /-- `fun_expRayToWad(x)` for a signed input strictly below the threshold: the overflow guard `iszero(slt(x, C)) = 0` is skipped (via `slt_thresh_lt`), so the kernel result — the `evm*` tree — -is forwarded. -/ +is forwarded when it is fixed by `int128` cleanup. -/ theorem call_fun_expRayToWad_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : EvmYul.Yul.call (fuel + (extra + 900)) [FormalYul.word x] (.some yulName_fun_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word ( @@ -580,7 +610,7 @@ theorem call_fun_expRayToWad_direct (zeroCutoff := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) (fuel := fuel + extra) (extra := 173) (shared := shared) (hlookup := hlookup) - have hconvertOut := + have hconvertInt256 := call_convert_uint256_to_int256_direct (v := let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) @@ -603,8 +633,31 @@ theorem call_fun_expRayToWad_direct evmAdd (evmIszero x) (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) (fuel := fuel + extra) (extra := 752) (shared := shared) (hlookup := hlookup) + have hconvertNarrow := + call_convert_int256_to_int128_direct + (v := + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) + (fuel := fuel + extra) (extra := 751) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hoctave hscale hconv67 - simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertOut + simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertInt256 hconvertNarrow simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -615,19 +668,44 @@ theorem call_fun_expRayToWad_direct EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, slt_thresh_lt hval, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 876) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 876) (shared := shared) (hlookup := hlookup), hconstHi, hcleanupHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, - hzeroCutoff, hkernel, hconvertOut, k] + hzeroCutoff, hkernel, hconvertInt256, hconvertNarrow, k] + simpa only [FormalYul.word] using hresultClean set_option maxHeartbeats 4000000 in -/-- `fun_wrap_expRayToWad(x)` for a signed input below the threshold forwards to +/-- `fun_wrap_expRayToWad(x)` forwards an `int128`-canonical result below the threshold from `fun_expRayToWad`, returning the `evm*` tree. -/ theorem call_fun_wrap_expRayToWad_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : EvmYul.Yul.call (fuel + (extra + 1100)) [FormalYul.word x] (.some yulName_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word ( @@ -662,6 +740,7 @@ theorem call_fun_wrap_expRayToWad_direct have h70 := call_fun_expRayToWad_direct (x := x) (fuel := fuel + extra) (extra := 191) (shared := shared) (hlookup := hlookup) (hval := hval) + (hresultClean := hresultClean) simp only [Nat.reduceAdd, FormalYul.word] at h70 simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', @@ -671,16 +750,40 @@ theorem call_fun_wrap_expRayToWad_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, - call_zero_value_for_split_t_int256_direct (fuel := fuel + extra) (extra := 1076) + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 1076) (shared := shared) (hlookup := hlookup), h70] set_option maxHeartbeats 16000000 in -/-- The external entrypoint for a signed input below the threshold ABI-encodes and returns the -`evm*` tree. -/ +/-- The external entrypoint ABI-encodes and returns an `int128`-canonical `evm*` tree for a signed +input below the threshold. -/ theorem external_fun_wrap_expRayToWad_calldata_result (x : Nat) (store : EvmYul.Yul.VarStore) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok (expSharedAfterFreePtr x) store) @@ -740,6 +843,10 @@ theorem external_fun_wrap_expRayToWad_calldata_result evmAdd (evmIszero x) (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) with htree + have hcleanTree : + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree := by + simpa only [← htree] using hresultClean let baseStore := Finmap.insert "ret_0" (FormalYul.word tree) (Finmap.insert "param_0" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore)) @@ -765,13 +872,14 @@ theorem external_fun_wrap_expRayToWad_calldata_result (store := Finmap.insert "param_0" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := expSharedAfterFreePtr_lookup x) (hval := hval) + (hresultClean := hresultClean) simp only [Nat.reduceAdd, FormalYul.word, ← htree] at hwrap have halloc := call_allocate_unbounded_direct (fuel := 999962) (shared := expSharedAfterFreePtr x) (store := baseStore) (hlookup := expSharedAfterFreePtr_lookup x) simp only [FormalYul.word, baseStore] at halloc have hencode := - call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart := memPos) (v := tree) (fuel := 999831) (shared := memShared) (store := encStore) (hlookup := by simp [memShared, expSharedAfterFreePtr_lookup x]) @@ -800,14 +908,44 @@ theorem external_fun_wrap_expRayToWad_calldata_result FormalYul.word 32 := by decide rw [hretLen] rw [FormalYul.Preservation.resultWord_evmReturn_mstore_word] - rw [htree] - exact congrArg _ (toNat_ofNat_evmAdd _ _) + calc + Except.ok (EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree)).toNat = + Except.ok (FormalYul.word tree).toNat := + congrArg (fun w => Except.ok w.toNat) hcleanTree + _ = _ := by + rw [htree] + exact congrArg _ (toNat_ofNat_evmAdd _ _) set_option maxHeartbeats 16000000 in -/-- The external entrypoint halts (returns) for a signed input below the threshold. -/ +/-- The external entrypoint halts (returns) below the threshold when the result is fixed by +`int128` cleanup. -/ theorem external_fun_wrap_expRayToWad_calldata_halts (x : Nat) (store : EvmYul.Yul.VarStore) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok (expSharedAfterFreePtr x) store) = @@ -866,13 +1004,14 @@ theorem external_fun_wrap_expRayToWad_calldata_halts (store := Finmap.insert "param_0" (FormalYul.word x) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := expSharedAfterFreePtr_lookup x) (hval := hval) + (hresultClean := hresultClean) simp only [Nat.reduceAdd, FormalYul.word, ← htree] at hwrap have halloc := call_allocate_unbounded_direct (fuel := 999962) (shared := expSharedAfterFreePtr x) (store := baseStore) (hlookup := expSharedAfterFreePtr_lookup x) simp only [FormalYul.word, baseStore] at halloc have hencode := - call_abi_encode_tuple_t_int256__to_t_int256__fromStack_direct + call_abi_encode_tuple_t_int128__to_t_int128__fromStack_direct (headStart := memPos) (v := tree) (fuel := 999831) (shared := memShared) (store := encStore) (hlookup := by simp [memShared, expSharedAfterFreePtr_lookup x]) @@ -896,7 +1035,31 @@ set_option maxHeartbeats 16000000 in /-- Result from the dispatcher-handed state. -/ theorem external_fun_wrap_expRayToWad_dispatcher_state_result (x : Nat) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : ((match EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok @@ -956,13 +1119,37 @@ theorem external_fun_wrap_expRayToWad_dispatcher_state_result (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) - (Inhabited.default : EvmYul.Yul.VarStore)) hval + (Inhabited.default : EvmYul.Yul.VarStore)) hval hresultClean set_option maxHeartbeats 16000000 in /-- Halt from the dispatcher-handed state. -/ theorem external_fun_wrap_expRayToWad_dispatcher_state_halts (x : Nat) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : ∃ state value, EvmYul.Yul.call 999989 [] (.some yulName_external_fun_wrap_expRayToWad) (.some yulContract) (EvmYul.Yul.State.Ok @@ -996,15 +1183,39 @@ theorem external_fun_wrap_expRayToWad_dispatcher_state_halts (Inhabited.default : EvmYul.Yul.VarStore)).toState (EvmYul.UInt256.ofNat 0)) (EvmYul.UInt256.ofNat 224)) - (Inhabited.default : EvmYul.Yul.VarStore)) hval + (Inhabited.default : EvmYul.Yul.VarStore)) hval hresultClean set_option maxHeartbeats 16000000 in -/-- **Value path.** For any signed input strictly below the supported-range threshold, -`run_exp_ray_to_wad_evm x` returns the `evm*` arithmetic tree ``. The handle for -the runtime floor and monotonicity claims at the run level. -/ +/-- **Value path.** For a signed input strictly below the supported-range threshold whose result is +fixed by `int128` cleanup, `run_exp_ray_to_wad_evm x` returns the `evm*` arithmetic tree ``. +The handle for the runtime floor and monotonicity claims at the run level. -/ theorem run_exp_ray_to_wad_evm_eq_tree (x : Nat) - (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) : + (hval : FormalYul.u256 x < 0x92b2f16cc66c5a4ae96e80d4 ∨ 2 ^ 255 ≤ FormalYul.u256 x) + (hresultClean : + let tree := + let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) + let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) + (evmMul 0x58b90bfbe8e7bcd5e4f1d9cc01f97b57a079a193394c5b16c5068badc5d k)) + let v := evmShr 0x87 (evmMul t t) + let ev := evmAdd (evmShl 0x1 0x9c2948bcaca16a0dd2fe98bb4470c388) (evmShr 0x7d (evmMul + (evmAdd 0x93f11e650dd6c64b96ce79065cdf80f4 (evmShr 0x81 (evmMul + (evmAdd 0x9064d9657e9a21fc16bb69331b81ae1e (evmShr 0x7b (evmMul + (evmAdd 0x9a036222841f47c6ed6fc3f7599445 (evmShr 0x95 (evmMul + (evmAdd 0xb9aacfacf3c10b378435f8e22adf48500e v) v))) v))) v))) v)) + let od := evmAdd 0x9c2948bcaca16a0dd2fe98bb4470c388 (evmShr 0x80 (evmMul + (evmAdd 0xaf566247c05753b42892f77b67a6b7c7 (evmShr 0x7a (evmMul + (evmAdd 0xad4506af99be27419341e181693281 (evmShr 0x84 (evmMul + (evmAdd 0xc926ddbecdeeb42e68cd16db7ed378 (evmShr 0x7e (evmMul + 0xdc07aff8276bde9a361278df6a10 v))) v))) v))) v)) + let tod := evmSar 0x81 (evmMul t od) + let r0 := evmDiv (evmMul 0x6f05b59d3b2000000000000000000000 (evmAdd ev tod)) + (evmSub ev tod) + let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) + evmAdd (evmIszero x) + (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) + EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word tree) = + FormalYul.word tree) : run_exp_ray_to_wad_evm x = .ok ( let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) let t := evmSar 0x6a (evmSub (evmMul 0x279d346de4781f921dd7a89933d54d1f72928 x) @@ -1027,8 +1238,9 @@ theorem run_exp_ray_to_wad_evm_eq_tree (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1) ) := by obtain ⟨haltState, _haltValue, hhalt⟩ := - external_fun_wrap_expRayToWad_dispatcher_state_halts x hval - have hresult := external_fun_wrap_expRayToWad_dispatcher_state_result x hval + external_fun_wrap_expRayToWad_dispatcher_state_halts x hval hresultClean + have hresult := + external_fun_wrap_expRayToWad_dispatcher_state_result x hval hresultClean rw [hhalt] at hresult have hReturn : FormalYul.Preservation.DispatcherReturn yulContract diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index 613ae2358..e86bb2299 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -75,7 +75,7 @@ example : run_exp_ray_to_wad_evm 0 = .ok 1000000000000000000 := /-! ## Monotonicity The octave-seam `r0`-doubling bound `SeamR0Bound` is discharged (`seamR0Bound_holds`, via the -per-point real bracket `r0Tree x ≈ (10¹⁸·2⁶⁸)·exp(rt)` and the seam relation `exp(rt1) = +per-point real bracket `r0Tree x ≈ (10¹⁸·2⁶⁷)·exp(rt)` and the seam relation `exp(rt1) = 2·exp(rt2)·exp(−1/RAY)`), so monotonicity holds over the whole supported domain with no analytic hypothesis. -/ @@ -251,11 +251,12 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : example (x : Int) : ExpRealSpec.MulExpRayBracket 0 x 0 := mulExpRayBracket_zero_result x -/-- The value path returns the compiled arithmetic tree whenever the ABI word is canonical and the -guard word is zero. -/ -example (y x : Nat) (hy : Int128CalldataWord y) (hguard : mulExpGuardTree y x = 0) : +/-- The value path returns the compiled arithmetic tree whenever the input and result words are +canonical and the guard word is zero. -/ +example (y x : Nat) (hy : Int128Word y) + (hresult : Int128Word (mulExpTree y x)) (hguard : mulExpGuardTree y x = 0) : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := - run_mul_exp_ray_evm_eq_tree_of_guard y x hy.2 hguard + run_mul_exp_ray_evm_eq_tree_of_guard y x hy.2 hresult.2 hguard /-- The compiled runtime returns zero for a zero multiplier whenever the guard accepts. -/ example (x : Nat) (hguard : mulExpGuardTree 0 x = 0) : run_mul_exp_ray_evm 0 x = .ok 0 := @@ -282,19 +283,19 @@ example {y x : Nat} (h : MulExpRayPanicDomain y x) : run_mul_exp_ray_evm_revert h /-- The accepted scale point returns the multiplier exactly. -/ -example {y : Nat} (hy : Int128CalldataWord y) (habs : absTree y ≤ scaleMax) +example {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := run_mul_exp_ray_evm_scale_point hy habs hshift /-- The scale-point result satisfies the public bracket. -/ -example {y : Nat} (hy : Int128CalldataWord y) (habs : absTree y ≤ scaleMax) +example {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := mulExpRay_run_bracket_scale_point hy habs hshift /-- At or below the zero cutoff, every accepted magnitude returns zero. -/ -example {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) +example {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : @@ -302,7 +303,7 @@ example {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp /-- The clamped result satisfies the public bracket. -/ -example {y x : Nat} (hy : Int128CalldataWord y) (hx : x < 2 ^ 256) +example {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 4376599cb..bdb1ae083 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -47,7 +47,7 @@ library Exp { /// 1414213562373095048, `expRayToWad(lnWadToRay(w)) == w - 1`, except at w = 10¹⁸ where it /// returns w. Reverts with `Panic(17)` when x is large enough to leave the supported range /// (x ≥ 0x92b2f16cc66c5a4ae96e80d4 ≈ 45.40 ⋅ 10²⁷, i.e. E ≳ 5.22 ⋅ 10³⁷). - function expRayToWad(int256 x) internal pure returns (int256) { + function expRayToWad(int256 x) internal pure returns (int128) { // At this input the octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, where the deficit // envelope below exceeds 1ulp. if (x >= _EXP_RAY_TO_WAD_HI) { @@ -56,7 +56,7 @@ library Exp { int256 k = _octave(x); unchecked { - return int256(_expRayKernel(x, k, _WAD_SCALE, uint256(int256(67) - k), _WAD_ZERO_MAX)); + return int128(int256(_expRayKernel(x, k, _WAD_SCALE, uint256(int256(67) - k), _WAD_ZERO_MAX))); } } @@ -82,7 +82,7 @@ library Exp { /// x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap /// boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to /// zero, either of which is sound (A < 1 there at every supported magnitude). - function mulExpRay(int128 y, int256 x) internal pure returns (int256) { + function mulExpRay(int128 y, int256 x) internal pure returns (int128) { uint256 ay; uint256 sign; // Split y into a sign mask and a magnitude without negating `type(int128).min`: @@ -131,7 +131,7 @@ library Exp { assembly ("memory-safe") { m := mul(m, or(sign, lt(0, ay))) } - return int256(m); + return int128(int256(m)); } } diff --git a/src/wrappers/ExpWrapper.sol b/src/wrappers/ExpWrapper.sol index 3187cfd77..a1e542fce 100644 --- a/src/wrappers/ExpWrapper.sol +++ b/src/wrappers/ExpWrapper.sol @@ -7,11 +7,11 @@ import {Exp} from "src/vendor/Exp.sol"; /// Function names are prefixed with `wrap_` to avoid Yul name collisions with the /// library functions, keeping the IR unambiguous for the formal-proof code generator. contract ExpWrapper { - function wrap_expRayToWad(int256 x) external pure returns (int256) { + function wrap_expRayToWad(int256 x) external pure returns (int128) { return Exp.expRayToWad(x); } - function wrap_mulExpRay(int128 y, int256 x) external pure returns (int256) { + function wrap_mulExpRay(int128 y, int256 x) external pure returns (int128) { return Exp.mulExpRay(y, x); } } diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index c69a2cf49..29c966982 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -25,15 +25,15 @@ contract ExpTest is Test { uint256 private constant _W_LO = 707106781186547525; uint256 private constant _W_HI = 1414213562373095048; - function expRayToWadExternal(int256 x) external pure returns (int256) { + function expRayToWadExternal(int256 x) external pure returns (int128) { return Exp.expRayToWad(x); } - function mulExpRayExternal(int128 y, int256 x) external pure returns (int256) { + function mulExpRayExternal(int128 y, int256 x) external pure returns (int128) { return Exp.mulExpRay(y, x); } - function mulExpRayDirtyY(uint256 dirtyY, int256 x) public pure returns (int256) { + function mulExpRayDirtyY(uint256 dirtyY, int256 x) public pure returns (int128) { int128 y; // Solidity cannot construct a narrow signed value with dirty upper bits. // Equivalent value: y = int128(uint128(dirtyY)). @@ -136,7 +136,7 @@ contract ExpTest is Test { 31034722391555079924522474771845545397 ]; for (uint256 i; i < xs.length; ++i) { - int256 r = Exp.expRayToWad(xs[i]); + int128 r = Exp.expRayToWad(xs[i]); assertLe(r, floors[i], "overestimates exp"); assertGe(r, floors[i] - 1, "below floor minus one"); } @@ -169,7 +169,7 @@ contract ExpTest is Test { /// k = 64, frac(E) ~= 0.52 exceeds that octave's envelope (~0.50) and the floor is exact. function testExpRayToWadSupportedEdge() external pure { int256 floorE = 52175271301331128849398287198371155181; - int256 r = Exp.expRayToWad(_TOO_BIG - 1); + int128 r = Exp.expRayToWad(_TOO_BIG - 1); assertLe(r, floorE, "overestimates exp"); assertGe(r, floorE - 1, "below floor minus one"); assertEq( @@ -195,7 +195,7 @@ contract ExpTest is Test { /// interiors and the clamp seam without an external reference. function testFuzzExpRayToWadMonotoneNonNegative(int256 x) external pure { x = bound(x, _ZERO_MAX - 1e27, _TOO_BIG - 2); - int256 r = Exp.expRayToWad(x); + int128 r = Exp.expRayToWad(x); assertGe(r, 0, "negative result"); assertGe(Exp.expRayToWad(x + 1), r, "adjacent monotonicity"); } @@ -239,7 +239,7 @@ contract ExpTest is Test { function testMulExpRayScaleCapLive() external pure { int256 x = _octaveStart(-2); int256 floorA = 30076996146000563943129221579116071223; - int256 r = Exp.mulExpRay(_Y_MAX, x); + int128 r = Exp.mulExpRay(_Y_MAX, x); assertLe(r, floorA, "overestimates"); assertGe(r, floorA - 1, "below floor minus one"); assertEq(Exp.mulExpRay(-_Y_MAX, x), -r, "negative mirror"); From c27411830334e0428f44cdff2a2ffb24d37f0c20 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 19:25:30 +0200 Subject: [PATCH 085/107] Support int128 minimum in mulExpRay Normalize the inclusive signed-magnitude endpoint and certify the generated-Yul value path through the 2^127 kernel scale. Co-Authored-By: OpenAI Codex --- formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean | 105 ++++---- .../ExpProof/ExpProof/Floor/R0ExpUnder.lean | 102 ++++---- .../ExpProof/Floor/UnderCarryDefs.lean | 4 +- formal/exp/ExpProof/ExpProof/Mono/Consts.lean | 26 +- formal/exp/ExpProof/ExpProof/Mono/Cross.lean | 35 +-- .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 11 +- formal/exp/ExpProof/ExpProof/Mono/Quot.lean | 34 +-- .../exp/ExpProof/ExpProof/Mono/StepMono.lean | 2 +- formal/exp/ExpProof/ExpProof/Mul/Accum.lean | 36 +-- formal/exp/ExpProof/ExpProof/Mul/Domain.lean | 49 ++-- formal/exp/ExpProof/ExpProof/Mul/Joint.lean | 73 +----- formal/exp/ExpProof/ExpProof/Mul/Shell.lean | 182 ++++++++----- .../exp/ExpProof/ExpProof/Mul/Transport.lean | 242 ++++++++++-------- .../exp/ExpProof/ExpProof/Mul/WordBridge.lean | 44 ++++ formal/exp/ExpProof/ExpProof/Mul/XMono.lean | 33 ++- formal/exp/ExpProof/ExpProof/Mul/YMono.lean | 159 ++++-------- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 161 +++++++++++- .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 106 ++++---- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 121 +++++---- formal/exp/ExpProof/ExpProof/Theorems.lean | 140 +++++----- formal/yul/YulImporter.lean | 5 +- src/vendor/Exp.sol | 44 ++-- test/0.8.34/Exp.t.sol | 61 +++-- 23 files changed, 966 insertions(+), 809 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean index c7d32ce03..d3df07371 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0Exp.lean @@ -9,7 +9,7 @@ import Mathlib.Analysis.SpecialFunctions.Pow.Real # The per-point `r0`-vs-`exp` bridge (never-over side) This module bounds the scaled quotient `r0ScaledTree scale x` above by `scale·exp(rt)` -plus twice the Q126 never-over budget, for any scale `2¹²⁵ ≤ scale ≤ scaleMax = 2¹²⁷ − 1` +plus twice the Q126 never-over budget, for any scale `2¹²⁵ ≤ scale ≤ kernelScaleMax = 2¹²⁷` (the budget is certified at the maximal scale; smaller scales only shrink the true error) (`rt = X/RAY − k·ln2` the reduced argument), the analytic content the floor brackets (`Floor.R0BoundHolds`) consume. The chain has four links: @@ -25,8 +25,8 @@ plus twice the Q126 never-over budget, for any scale `2¹²⁵ ≤ scale ≤ sca 4. **`exp(t/2¹²⁸)` vs `exp(rt)`** — the reduced-argument gap (`Floor.Reduce`), `≤ 55242717280199026/10¹⁹`. -The nonnegative-half total is `4668745981919039833/10¹⁹ < 1/2`, so doubling it for every -`scale < 2¹²⁷` stays below `MARGIN = 1`. On the `t ≤ 0` half link 2 is free (the grain moves `ê` +The nonnegative-half total is `4668745981919039833/10¹⁹ < 1/2`, so its image at every +`scale ≤ 2¹²⁷` stays below `MARGIN = 1`. On the `t ≤ 0` half link 2 is free (the grain moves `ê` the other way) and links 3–4 shrink (`ê ≤ 1`), giving the smaller total `2446770622956801280/10¹⁹`. -/ @@ -44,8 +44,8 @@ set_option exponentiation.threshold 2000 /-! ## The `div` floor sandwich -/ /-- The scaled quotient is the integer floor: `r0·den_rt ≤ scale·num_rt < (r0+1)·den_rt` with -`num_rt = ev + tod`, `den_rt = ev − tod`, at any `scale ≤ scaleMax`. -/ -theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) +`num_rt = ev + tod`, `den_rt = ev − tod`, at any `scale ≤ kernelScaleMax`. -/ +theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (r0ScaledTree scale x) * ((evTree x : Int) - int256 (todTree x)) ≤ (scale : Int) * ((evTree x : Int) + int256 (todTree x)) ∧ @@ -68,17 +68,15 @@ theorem r0_floor_sandwich {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < have hevhiI : (evTree x : Int) < 3 * 2 ^ 127 := by exact_mod_cast hevhi have ht126 : int256 (todTree x) < 2 ^ 126 := htod_hi have hp126 : (2:Int) ^ 126 = 85070591730234615865843651857942052864 := by norm_num - have hnumlt128 : int256 num < 2 ^ 129 := by + have hnumlt129 : int256 num < 2 ^ 129 := by rw [hnumi] nlinarith [hevhiI, ht126] - have hnumnat128 : num < 2 ^ 129 := by - have hh : ((num : Nat) : Int) < 2 ^ 129 := by rw [hnumeq] at hnumlt128; exact hnumlt128 + have hnumnat129 : num < 2 ^ 129 := by + have hh : ((num : Nat) : Int) < 2 ^ 129 := by rw [hnumeq] at hnumlt129; exact hnumlt129 exact_mod_cast hh - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) - have hfit : scale * num < 2 ^ 256 := by - have h1 : scale * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hnumnat128) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega + have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold kernelScaleMax; norm_num) + have hfit : scale * num < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi hnumnat129 have hmulval : evmMul scale num = scale * num := evmMul_eq_nat hsw hnumw hfit have hdennat : 0 < den := by have hh : (0:Int) < ((den : Nat) : Int) := by rw [← hdeneq, hdeni]; exact hden_pos @@ -143,7 +141,7 @@ theorem den_ge_194 {x : Nat} (hx : x < 2 ^ 256) omega /-- On the nonpositive half `tod ≤ 0` and hence `r0 ≤ scale` (num ≤ den). -/ -theorem r0_le_scale_neg {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) +theorem r0_le_scale_neg {scale x : Nat} (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (r0ScaledTree scale x) ≤ (scale : Int) := by @@ -247,7 +245,7 @@ theorem tOd_bracket_neg {x : Nat} (hx : x < 2 ^ 256) /-- **Joint link-1 over (nonnegative half, `r0 ≥ scale`)**: the shared even truncation cancels through the floor, `r0·DENv − scale·NUMv ≤ Wev·2⁵⁹⁰·(r0 − scale)`. -/ -theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) (hr0ge : (scale : Int) ≤ int256 (r0ScaledTree scale x)) : @@ -281,7 +279,7 @@ theorem link1_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scal nlinarith [hterm1, hterm2, hfloor638] /-- **Link-1 over (nonnegative half, `r0 ≤ scale`)**: the residue is nonpositive outright. -/ -theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) (hr0le : int256 (r0ScaledTree scale x) ≤ (scale : Int)) : @@ -318,7 +316,7 @@ theorem link1_over_small {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scal /-- **Link-1 over (nonpositive half)**: the even truncation drops (`r0 ≤ scale`); the odd truncation survives attenuated to the `t`-scale: `r0·DENv − scale·NUMv ≤ Wod·2⁴⁸⁰·(−t)·(r0 + scale)`. -/ -theorem link1_over_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem link1_over_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) - @@ -751,7 +749,7 @@ theorem num_le_145_den {x : Nat} (hx : x < 2 ^ 256) nlinarith [hceil, hden] /-- The quotient cap: `10⁴·(r0 − scale) ≤ 4146·scale` on the nonneg half. -/ -theorem r0_cap {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) +theorem r0_cap {scale x : Nat} (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : 10000 * (int256 (r0ScaledTree scale x) - (scale : Int)) ≤ 4146 * (scale : Int) := by @@ -776,7 +774,7 @@ theorem r0_cap {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) /-! ## The per-point never-over (nonnegative half) -/ /-- The link-1 jitter divided by `DENv` stays inside its budget on the nonnegative half. -/ -theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) +theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (72572599271425 : Real) * 2 ^ 591 * ((int256 (r0ScaledTree scale x) : Real) - (scale : Real)) / @@ -784,12 +782,7 @@ theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 * 1102011232081646123 / 10000000000000000000 := by obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW - have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by - unfold scaleMax; norm_num - rw [hs] at h - exact h + have hshiR : (scale : Real) ≤ (kernelScaleMax : Real) := by exact_mod_cast hshi set r0 := int256 (r0ScaledTree scale x) with hr0def set t := int256 (tTree x) with htdef set v := vTree x with hvdef @@ -807,10 +800,15 @@ theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < · rw [div_le_iff₀ hDR] have hcap := r0_cap hshi hx hW htnn have hcapR : (r0 : Real) - (scale : Real) ≤ - 4146 * 0x7fffffffffffffffffffffffffffffff / 10000 := by + 4146 * kernelScaleMax / 10000 := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hcap push_cast at h - linarith [h, hshiR] + rw [← hr0def] at h + have hscale : 4146 * (scale : Real) / 10000 ≤ + 4146 * kernelScaleMax / 10000 := by + apply div_le_div_of_nonneg_right ?_ (by norm_num) + exact mul_le_mul_of_nonneg_left hshiR (by norm_num) + nlinarith [h, hscale] obtain ⟨hDEN_ge, _⟩ := DENv_runtime_bracket hx hW htnn have hden := den_ge_194 hx hW have hDENlow : (2:Int) ^ 637 * (330077261860684142693791478386293573392 - 2) ≤ DENv v t := by @@ -825,23 +823,23 @@ theorem jitter_over_budget {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < linarith [h] have hnum_le : (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) ≤ (72572599271425 : Real) * 2 ^ 591 * - (4146 * 0x7fffffffffffffffffffffffffffffff / 10000) := + (4146 * kernelScaleMax / 10000) := mul_le_mul_of_nonneg_left hcapR (by positivity) have hbudget : (72572599271425 : Real) * 2 ^ 591 * - (4146 * 0x7fffffffffffffffffffffffffffffff / 10000) ≤ + (4146 * kernelScaleMax / 10000) ≤ (2 * 1102011232081646123 / 10000000000000000000) * ((2:Real) ^ 637 * (330077261860684142693791478386293573392 - 2)) := by norm_num calc (72572599271425 : Real) * 2 ^ 591 * ((r0 : Real) - (scale : Real)) ≤ (72572599271425 : Real) * 2 ^ 591 * - (4146 * 0x7fffffffffffffffffffffffffffffff / 10000) := hnum_le + (4146 * kernelScaleMax / 10000) := hnum_le _ ≤ (2 * 1102011232081646123 / 10000000000000000000) * ((2:Real) ^ 637 * (330077261860684142693791478386293573392 - 2)) := hbudget _ ≤ (2 * 1102011232081646123 / 10000000000000000000) * (DENv v t : Real) := mul_le_mul_of_nonneg_left hDENlowR (by norm_num) /-- **The per-point never-over on the nonnegative half.** -/ -theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + @@ -849,12 +847,7 @@ theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : sc obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by - unfold scaleMax; norm_num - rw [hs] at h - exact h + have hshiR : (scale : Real) ≤ (kernelScaleMax : Real) := by exact_mod_cast hshi set t := int256 (tTree x) with htdef set v := vTree x with hvdef have htdom : t ≤ (ExpCertV.H129 : Int) := by @@ -959,7 +952,7 @@ theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : sc linarith [hgran, hNEMp, hcMp, hEtErt] have h234S := mul_le_mul_of_nonneg_left h234 hsRnn have hCs : (scale : Real) * (3566734749837393710 / 10000000000000000000) ≤ - (0x7fffffffffffffffffffffffffffffff : Real) * + (kernelScaleMax : Real) * (3566734749837393710 / 10000000000000000000) := mul_le_mul_of_nonneg_right hshiR (by positivity) rw [hErtdef] at * @@ -969,7 +962,7 @@ theorem r0_real_over_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : sc /-- The link-1 jitter budget on the nonpositive half. -/ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) + (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (269746241 : Real) * 2 ^ 480 * (-(int256 (tTree x) : Real)) * @@ -980,12 +973,7 @@ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW have hDEN_ge := DENv_ge_ev_neg hx hW htneg obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 - have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by - unfold scaleMax; norm_num - rw [hs] at h - exact h + have hshiR : (scale : Real) ≤ (kernelScaleMax : Real) := by exact_mod_cast hshi set r0 := int256 (r0ScaledTree scale x) with hr0def set t := int256 (tTree x) with htdef set v := vTree x with hvdef @@ -1017,13 +1005,13 @@ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) have hsnn : (0:Real) ≤ (scale : Real) := by positivity linarith [this, hsnn] have hr0pH : (r0 : Real) + (scale : Real) ≤ - 2 * 0x7fffffffffffffffffffffffffffffff := by + 2 * kernelScaleMax := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h linarith [h, hshiR] have hnum_le : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * - (2 * (0x7fffffffffffffffffffffffffffffff : Real)) := by + (2 * (kernelScaleMax : Real)) := by have h1 : (269746241 : Real) * 2 ^ 480 * (-(t : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 := mul_le_mul_of_nonneg_left hntH (by positivity) @@ -1033,13 +1021,13 @@ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) push_cast at h linarith [h] have hbudget : (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * - (2 * (0x7fffffffffffffffffffffffffffffff : Real)) ≤ + (2 * (kernelScaleMax : Real)) ≤ (2 * 2170557036555806152 / 10000000000000000000) * ((2:Real) ^ 637 * 415147853590918758559635130244235626256) := by norm_num calc (269746241 : Real) * 2 ^ 480 * (-(t : Real)) * ((r0 : Real) + (scale : Real)) ≤ (269746241 : Real) * 2 ^ 480 * 235865763225513294137944142764154484399 * - (2 * (0x7fffffffffffffffffffffffffffffff : Real)) := + (2 * (kernelScaleMax : Real)) := hnum_le _ ≤ (2 * 2170557036555806152 / 10000000000000000000) * ((2:Real) ^ 637 * 415147853590918758559635130244235626256) := hbudget @@ -1049,7 +1037,7 @@ theorem jitter_over_budget_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) /-- **The per-point never-over on the nonpositive half.** The granularity is free here; the `Mp` factor and reduced-argument gap shrink because `Et ≤ 1`. -/ theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) + (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + @@ -1057,12 +1045,7 @@ theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) have htdom := tdom_neg hx hW htneg have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (0x7fffffffffffffffffffffffffffffff : Real) := by - have h : ((scale : Nat) : Real) ≤ ((scaleMax : Nat) : Real) := by exact_mod_cast hshi - have hs : ((scaleMax : Nat) : Real) = 0x7fffffffffffffffffffffffffffffff := by - unfold scaleMax; norm_num - rw [hs] at h - exact h + have hshiR : (scale : Real) ≤ (kernelScaleMax : Real) := by exact_mod_cast hshi set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -1149,7 +1132,7 @@ theorem r0_real_over_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) linarith [hgranR, hNEMp, hcMp, hEtErt] have h234S := mul_le_mul_of_nonneg_left h234 hsRnn have hCs : (scale : Real) * (276213586400995128 / 10000000000000000000) ≤ - (0x7fffffffffffffffffffffffffffffff : Real) * + (kernelScaleMax : Real) * (276213586400995128 / 10000000000000000000) := mul_le_mul_of_nonneg_right hshiR (by positivity) rw [hErtdef] at * @@ -1167,10 +1150,10 @@ theorem over_budget_image_lt_one : (2 * 4668745981919039833 / 10000000000000000000 : Real) < 1 := by norm_num -/-- **Per-point never-over, for either sign.** The Q126 budget is below one half, and -`scale < 2¹²⁷`, so its image is below the one-unit runtime margin. -/ +/-- **Per-point never-over, for either sign.** The Q126 budget is below one half, so its image +at every `scale ≤ 2¹²⁷` is below the one-unit runtime margin. -/ theorem r0Scaled_real_over_within {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : + (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : (int256 (r0ScaledTree scale x) : Real) ≤ (scale : Real) * Real.exp (reducedArg x) + 2 * 4668745981919039833 / 10000000000000000000 := by @@ -1184,7 +1167,7 @@ theorem r0_real_over_within_wide {x : Nat} (hx : x < 2 ^ 256) (int256 (r0Tree x) : Real) ≤ (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) + 2 * 4668745981919039833 / 10000000000000000000 := by have h := r0Scaled_real_over_within (scale := scaleQ67) (by unfold scaleQ67; norm_num) - scaleQ67_le_scaleMax hx hW + scaleQ67_le_kernelScaleMax hx hW rw [r0Tree_eq_scaled] have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by unfold scaleQ67; norm_num diff --git a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean index cd12ec9b2..75f1d6fae 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/R0ExpUnder.lean @@ -6,7 +6,7 @@ import ExpProof.Cert.ExpUnderCarry This module contains the counterpart to the never-over `r0Scaled_real_over_within`: the per-point deficit `scale·exp(rt) ≤ r0 + 2993/1000` (`r0Scaled_real_under_within`), for both signs and every -scale in `2¹²⁵ ≤ scale ≤ scaleMax`. +scale in `2¹²⁵ ≤ scale ≤ kernelScaleMax`. On the nonnegative half, generated carry certificates bound the quotient deficit by `258857/100000`; the proof retains the quotient-factor and reduced-argument terms at their exact @@ -77,7 +77,7 @@ theorem exp_reducedArg_le_sqrt2bound {x : Nat} (hx : x < 2 ^ 256) /-! ## The `r0` bracket on the nonneg half -/ /-- `r0` is bracketed on the nonnegative half: `scale ≤ r0` and `100·r0 ≤ 145·scale`. -/ -theorem r0_bracket_nonneg {scale x : Nat} (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) +theorem r0_bracket_nonneg {scale x : Nat} (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : (scale : Int) ≤ int256 (r0ScaledTree scale x) ∧ @@ -243,7 +243,7 @@ theorem underCarryPieces_cover : /-- **Link-1 under (nonnegative half).** The quotient floor costs one denominator. The remaining carry is bounded jointly with the exact denominator polynomial on each square-grid interval; the largest checked row coefficient is `158857/100000` denominators. -/ -theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : @@ -255,7 +255,7 @@ theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale obtain ⟨htOp_lo, htOp_hi⟩ := tOd_bracket_nonneg hx hW htnn obtain ⟨hr0lo, hr0hi145⟩ := r0_bracket_nonneg hshi hx hW htnn obtain ⟨hDEN_lo, hDEN_up⟩ := DENv_runtime_bracket hx hW htnn - have hshiI : (scale : Int) ≤ (scaleMax : Int) := by exact_mod_cast hshi + have hshiI : (scale : Int) ≤ (kernelScaleMax : Int) := by exact_mod_cast hshi have hLHS : (scale : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) ≤ 2 ^ 637 * ((evTree x : Int) - int256 (todTree x)) + @@ -305,7 +305,7 @@ theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale have hSpos : (0 : Int) < S := by rw [hSdef] exact_mod_cast lt_of_lt_of_le (by norm_num : (0:Nat) < 2 ^ 125) hslo - have hSmax : S ≤ (scaleMax : Int) := by rw [hSdef]; exact hshiI + have hSmax : S ≤ (kernelScaleMax : Int) := by rw [hSdef]; exact hshiI have hr0nn : (0 : Int) ≤ r0 := le_trans (le_of_lt hSpos) hr0lo -- The row's square cap implies `t ≤ T` on the nonnegative half. have htT : t ≤ T := by @@ -383,19 +383,19 @@ theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale have hrow_s : 1000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (200 * S * Dc + 200 * S * T * Op + 800 * S * 2 ^ 637)) + 200000 * 2 ^ 637 * Dc ≤ R * (Dc * Dc) := by - have hSmaxS_nn : (0 : Int) ≤ (scaleMax : Int) - S := by linarith [hSmax] - have h1 : 200 * S * Dc ≤ 200 * (scaleMax : Int) * Dc := by + have hSmaxS_nn : (0 : Int) ≤ (kernelScaleMax : Int) - S := by linarith [hSmax] + have h1 : 200 * S * Dc ≤ 200 * (kernelScaleMax : Int) * Dc := by nlinarith [mul_nonneg hSmaxS_nn (le_of_lt hDcpos)] - have h2 : 200 * S * T * Op ≤ 200 * (scaleMax : Int) * T * Op := by + have h2 : 200 * S * T * Op ≤ 200 * (kernelScaleMax : Int) * T * Op := by nlinarith [mul_nonneg hSmaxS_nn (mul_nonneg hTnn hOpnn)] have h3 : 800 * S * 2 ^ 637 ≤ - 800 * (scaleMax : Int) * 2 ^ 637 := by nlinarith [hSmaxS_nn] + 800 * (kernelScaleMax : Int) * 2 ^ 637 := by nlinarith [hSmaxS_nn] have hsum_le : 200 * S * Dc + 200 * S * T * Op + 800 * S * 2 ^ 637 ≤ - 200 * (scaleMax : Int) * Dc + 200 * (scaleMax : Int) * T * Op + - 800 * (scaleMax : Int) * 2 ^ 637 := by + 200 * (kernelScaleMax : Int) * Dc + 200 * (kernelScaleMax : Int) * T * Op + + 800 * (kernelScaleMax : Int) * 2 ^ 637 := by linarith [h1, h2, h3] have hmul_le := mul_le_mul_of_nonneg_left hsum_le hcoefT_nn - norm_num [scaleMax] at hmul_le + norm_num [kernelScaleMax] at hmul_le linarith [hrow, hmul_le] have hXY : (100000 * ((2 ^ 637 + 269746241 * 2 ^ 480 * T) * (S + r0)) + 200000 * 2 ^ 637) * Dc ≤ (R * Dc) * Dc := by @@ -415,7 +415,7 @@ theorem link1_under_int {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale /-- **Link-1 under (nonpositive half)**: the same `2378/1000` budget, with no piece machinery: on this half `DENv = Ep·2¹¹¹ − t·Op ≥ 2⁶³⁷·ev`, so the even-truncation width and the `tod`-floor unit are absorbed against `2⁶³⁷·ev ≥ 2⁶³⁷·A0`. -/ -theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : @@ -429,7 +429,7 @@ theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW obtain ⟨hev_lo, _⟩ := evTree_facts (vTree_eq_wide hx hW).2 obtain ⟨htod_lo126, _, _, _⟩ := todTree_bound_wide hx hW - have hshiI : (scale : Int) ≤ (scaleMax : Int) := by exact_mod_cast hshi + have hshiI : (scale : Int) ≤ (kernelScaleMax : Int) := by exact_mod_cast hshi have hSnn : (0:Int) ≤ (scale : Int) := Int.natCast_nonneg _ have hLHS : (scale : Int) * NUMv (vTree x) (int256 (tTree x)) - int256 (r0ScaledTree scale x) * DENv (vTree x) (int256 (tTree x)) ≤ @@ -505,21 +505,21 @@ theorem link1_under_int_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s -- literal maximal one first have hSrelax : 1000 * (72572599271425 * 2 ^ 591 * (scale : Int) + 2 * 2 ^ 637 * (scale : Int)) ≤ - 1000 * (72572599271425 * 2 ^ 591 * (scaleMax : Int) + - 2 * 2 ^ 637 * (scaleMax : Int)) := by + 1000 * (72572599271425 * 2 ^ 591 * (kernelScaleMax : Int) + + 2 * 2 ^ 637 * (kernelScaleMax : Int)) := by nlinarith [hshiI] have hlit : 1000 * (2 ^ 637 : Int) + - 1000 * (72572599271425 * 2 ^ 591 * (scaleMax : Int) + - 2 * 2 ^ 637 * (scaleMax : Int)) ≤ + 1000 * (72572599271425 * 2 ^ 591 * (kernelScaleMax : Int) + + 2 * 2 ^ 637 * (kernelScaleMax : Int)) ≤ (1378 : Int) * (2 ^ 637 * 415147853590918758559635130244235626256) := by - norm_num [scaleMax] + norm_num [kernelScaleMax] linarith [hLHS, hDden, hD_A, hlit, hSrelax] /-! ## The per-point deficit (nonneg half) -/ /-- **The per-point deficit (nonnegative half).** The carry, quotient-factor excess, and reduced- argument gap retain their exact rational budgets until the final sum. -/ -theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htnn : 0 ≤ int256 (tTree x)) : @@ -527,7 +527,7 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s obtain ⟨_, hthi⟩ := tTree_in_cert_domain_wide hx hW have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (scaleMax : Real) := by exact_mod_cast hshi + have hshiR : (scale : Real) ≤ (kernelScaleMax : Real) := by exact_mod_cast hshi set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -571,14 +571,14 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s le_trans hEt_le (mul_le_mul_of_nonneg_right hgran1 hMpp_nn) have hMpp1 : Mpp - 1 = 1 / (2 ^ 132 : Real) := by rw [hMppdef]; field_simp obtain ⟨_, hr0hi145⟩ := r0_bracket_nonneg hshi hx hW htnn - have hr0R : (r0 : Real) ≤ (145 / 100) * (scaleMax : Real) := by + have hr0R : (r0 : Real) ≤ (145 / 100) * (kernelScaleMax : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0hi145 push_cast at h calc (r0 : Real) ≤ (145 / 100) * (scale : Real) := by nlinarith [h] - _ ≤ (145 / 100) * (scaleMax : Real) := + _ ≤ (145 / 100) * (kernelScaleMax : Real) := mul_le_mul_of_nonneg_left hshiR (by norm_num) have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 258857 / 100000 + - ((145 / 100) * (scaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) := by + ((145 / 100) * (kernelScaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) := by have h1 : (scale : Real) * Et ≤ (scale : Real) * (((NUMv v t : Real) / (DENv v t : Real)) * Mpp) := mul_le_mul_of_nonneg_left hEt_le_Qv hsRnn @@ -587,10 +587,10 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) := by ring have h3 : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mpp - 1) ≤ - ((145 / 100) * (scaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) := by + ((145 / 100) * (kernelScaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) := by rw [hMpp1] have hcap : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ - (145 / 100) * (scaleMax : Real) + 258857 / 100000 := by + (145 / 100) * (kernelScaleMax : Real) + 258857 / 100000 := by linarith [hQv_le, hr0R] have := mul_le_mul_of_nonneg_right hcap (by positivity : (0:Real) ≤ 1 / (2 ^ 132 : Real)) simpa [div_eq_mul_inv] using this @@ -603,7 +603,7 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s rw [← hErtdef] at hErt_le have hErt_nn : (0:Real) ≤ Ert := le_of_lt (Real.exp_pos _) have hgap126 : (scale : Real) * (Ert - Et) ≤ - (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := by + (kernelScaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := by have hgap : Ert - Et ≤ (1025 / (1024 * (2 ^ 129 : Real))) * Ert := le_trans hExp_diff (mul_le_mul_of_nonneg_right (le_of_lt hgapunder) hErt_nn) have h1 : (scale : Real) * (Ert - Et) ≤ (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := @@ -612,17 +612,17 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) hsRnn have h2' : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ - (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := + (kernelScaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) := mul_le_mul_of_nonneg_right hshiR (by positivity) linarith [h1, h2, h2'] have hdist : (scale : Real) * Ert = (scale : Real) * Et + (scale : Real) * (Ert - Et) := by ring show (scale : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 have hsum : (258857 : Real) / 100000 + - ((145 / 100) * (scaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) + - (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ + ((145 / 100) * (kernelScaleMax : Real) + 258857 / 100000) / (2 ^ 132 : Real) + + (kernelScaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (14143 / 10000)) ≤ 2993 / 1000 := by - norm_num [scaleMax] + norm_num [kernelScaleMax] linarith [hEt_bound, hgap126, hdist, hsum] /-! ## The per-point deficit (nonpositive half) -/ @@ -630,14 +630,14 @@ theorem r0_real_under_tight {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : s /-- **The per-point deficit (nonpositive half).** The quotient floor, quotient-factor excess, granularity envelope, and reduced-argument gap retain their exact maximal-scale images. -/ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) + (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (htneg : int256 (tTree x) ≤ 0) : (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by have htdom := tdom_neg hx hW htneg have hvle := vTree_le_vmax_wide hx hW have hsRnn : (0:Real) ≤ (scale : Real) := by positivity - have hshiR : (scale : Real) ≤ (scaleMax : Real) := by exact_mod_cast hshi + have hshiR : (scale : Real) ≤ (kernelScaleMax : Real) := by exact_mod_cast hshi set t := int256 (tTree x) with htdef set v := vTree x with hvdef set r0 := int256 (r0ScaledTree scale x) with hr0def @@ -674,7 +674,7 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) positivity have hMp1 : Mp - 1 = 1 / ((2 ^ 132 : Real) - 1) := by rw [hMpdef]; field_simp have hr0le := r0_le_scale_neg hshi hx hW htneg - have hr0R : (r0 : Real) ≤ (scaleMax : Real) := by + have hr0R : (r0 : Real) ≤ (kernelScaleMax : Real) := by have h := (@Int.cast_le Real _ _ _ _ _ _ _).mpr hr0le push_cast at h linarith [h, hshiR] @@ -682,7 +682,7 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) -- scale and relaxed to the literal maximal-scale budget have hgran2S : (scale : Real) * Mp * ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) ≤ - (scaleMax : Real) * 1644901622230542074 / + (kernelScaleMax : Real) * 1644901622230542074 / (10000000000000000000 * (2 ^ 126 : Real)) := by have hdiff_nn : (0:Real) ≤ (NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real) := by linarith [hgran1] @@ -697,12 +697,12 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_left hMp' hsRnn) hdiff_nn have h2 := mul_le_mul_of_nonneg_left hgran2 hsRnn have h3 : (scale : Real) * (1644901622230542074 / 10000000000000000000) ≤ - (scaleMax : Real) * (1644901622230542074 / 10000000000000000000) := + (kernelScaleMax : Real) * (1644901622230542074 / 10000000000000000000) := mul_le_mul_of_nonneg_right hshiR (by positivity) nlinarith [h1, h2, h3] have hEt_bound : (scale : Real) * Et ≤ (r0 : Real) + 2378 / 1000 + - ((scaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) + - (scaleMax : Real) * 1644901622230542074 / + ((kernelScaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) + + (kernelScaleMax : Real) * 1644901622230542074 / (10000000000000000000 * (2 ^ 126 : Real)) := by have h1 : (scale : Real) * Et ≤ (scale : Real) * (((NE : Real) / (DE : Real)) * Mp) := mul_le_mul_of_nonneg_left hEt_le hsRnn @@ -713,10 +713,10 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (scale : Real) * Mp * ((NE : Real) / (DE : Real) - (NUMv v t : Real) / (DENv v t : Real)) := by ring have hMpterm : ((scale : Real) * ((NUMv v t : Real) / (DENv v t : Real))) * (Mp - 1) ≤ - ((scaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) := by + ((kernelScaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) := by rw [hMp1] have hcap : (scale : Real) * ((NUMv v t : Real) / (DENv v t : Real)) ≤ - (scaleMax : Real) + 2378 / 1000 := by + (kernelScaleMax : Real) + 2378 / 1000 := by exact le_trans hQv_le (add_le_add_right hr0R _) have := mul_le_mul_of_nonneg_right hcap (by positivity : (0:Real) ≤ 1 / ((2 ^ 132 : Real) - 1)) @@ -753,7 +753,7 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) rw [div_le_div_iff₀ h1u (by norm_num)]; nlinarith [husmall] linarith [hmono, hexpu, hfin] have hgap126 : (scale : Real) * (Ert - Et) ≤ - (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := by + (kernelScaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := by have hgap : Ert - Et ≤ (1025 / (1024 * (2 ^ 129 : Real))) * Ert := le_trans hExp_diff (mul_le_mul_of_nonneg_right (le_of_lt hgapunder) hErt_nn) have h1 : (scale : Real) * (Ert - Et) ≤ (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * Ert) := @@ -762,25 +762,25 @@ theorem r0_real_under_tight_neg {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := mul_le_mul_of_nonneg_left (mul_le_mul_of_nonneg_left hErt_le (by positivity)) hsRnn have h2' : (scale : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ - (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := + (kernelScaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) := mul_le_mul_of_nonneg_right hshiR (by positivity) linarith [h1, h2, h2'] have hdist : (scale : Real) * Ert = (scale : Real) * Et + (scale : Real) * (Ert - Et) := by ring show (scale : Real) * Ert ≤ (r0 : Real) + 2993 / 1000 have hsum : (2378 : Real) / 1000 + - ((scaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) + - (scaleMax : Real) * 1644901622230542074 / + ((kernelScaleMax : Real) + 2378 / 1000) / ((2 ^ 132 : Real) - 1) + + (kernelScaleMax : Real) * 1644901622230542074 / (10000000000000000000 * (2 ^ 126 : Real)) + - (scaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ + (kernelScaleMax : Real) * ((1025 / (1024 * (2 ^ 129 : Real))) * (10001 / 10000)) ≤ 2993 / 1000 := by - norm_num [scaleMax] + norm_num [kernelScaleMax] linarith [hEt_bound, hgap126, hdist, hsum] /-- **Per-point deficit (tight, any sign):** `scale·exp(rt) ≤ r0 + 2993/1000` (the deficit budget is certified at the maximal scale, and smaller scales only shrink the true deficit). -/ theorem r0Scaled_real_under_within {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : + (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : (scale : Real) * Real.exp (reducedArg x) ≤ (int256 (r0ScaledTree scale x) : Real) + 2993 / 1000 := by rcases le_or_gt 0 (int256 (tTree x)) with htnn | htneg · exact r0_real_under_tight hslo hshi hx hW htnn @@ -790,7 +790,7 @@ theorem r0_real_under_within_wide {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : (0x6f05b59d3b2000000000000000000000 : Real) * Real.exp (reducedArg x) ≤ (int256 (r0Tree x) : Real) + 2993 / 1000 := by have h := r0Scaled_real_under_within (scale := scaleQ67) (by unfold scaleQ67; norm_num) - scaleQ67_le_scaleMax hx hW + scaleQ67_le_kernelScaleMax hx hW rw [r0Tree_eq_scaled] have hs : ((scaleQ67 : Nat) : Real) = 0x6f05b59d3b2000000000000000000000 := by unfold scaleQ67; norm_num @@ -813,8 +813,8 @@ theorem r0Tree_gt_2126 {x : Nat} (hx : x < 2 ^ 256) have h2 : (2 : Real) ^ 123 < ((2 ^ 124 : Int) : Real) := by norm_num linarith [h, h2] -/-- `2¹²² < r0ScaledTree scale x` on the region, for `2^125 ≤ scale ≤ scaleMax`. -/ -theorem r0Scaled_gt_2122 {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +/-- `2¹²² < r0ScaledTree scale x` on the region, for `2^125 ≤ scale ≤ kernelScaleMax`. -/ +theorem r0Scaled_gt_2122 {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : (2 : Real) ^ 122 < (int256 (r0ScaledTree scale x) : Real) := by obtain ⟨hr0lo, _⟩ := r0Scaled_bounds hslo hshi hx hW @@ -927,7 +927,7 @@ theorem r0_seam_double {x1 x2 : Nat} the seam slack `exp(−1/RAY) < 1` against `r0₂ > 2¹²²` (worth `≈ 5·10⁹` grid units at the minimal scale) still dwarfs the per-point envelopes and the three integer units. -/ theorem r0Scaled_seam_double {scale x1 x2 : Nat} - (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) + (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ kernelScaleMax) (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hk : int256 (kTree x2) = int256 (kTree x1) + 1) diff --git a/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean b/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean index d15b7d56b..df0fd40d2 100644 --- a/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean +++ b/formal/exp/ExpProof/ExpProof/Floor/UnderCarryDefs.lean @@ -2,7 +2,7 @@ import ExpProof.Floor.CertDefsV import ExpProof.Floor.GranPieces /-! -# Positive-under carry certificates at the signed 128-bit magnitude bound +# Positive-under carry certificates at the inclusive kernel scale bound The carry budget is reduced to one degree-ten integer polynomial on each granularity interval. Every row records the interval, its argument cap, and @@ -13,7 +13,7 @@ namespace ExpCertV open Common.Poly -def S2 : Int := 2 ^ 127 - 1 +def S2 : Int := 2 ^ 127 def denAtCap (T : Int) : List Int := polySub (polyScale (2 ^ 111) evVPoly) (polyScale T odVPoly) diff --git a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean index cf3262fc2..ea8c4492c 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Consts.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Consts.lean @@ -41,8 +41,9 @@ abbrev odShift4 : Nat := 0x80 abbrev todShift : Nat := 0x81 abbrev foldShift : Nat := 0x43 abbrev scaleQ67 : Nat := 0x6f05b59d3b2000000000000000000000 -abbrev scaleMax : Nat := 0x7fffffffffffffffffffffffffffffff -abbrev scaleMaxClz : Nat := 0x81 +abbrev int128Max : Nat := 0x7fffffffffffffffffffffffffffffff +abbrev kernelScaleMax : Nat := 0x80000000000000000000000000000000 +abbrev scaleClzBias : Nat := 0x81 abbrev marginWord : Nat := 0x1 abbrev mulExpRayHi : Nat := 0x119146ae9d22b7454e84ce34c abbrev mulExpRayZeroMax : Nat := 0xfffffffffffffffffffffffffffffffffffffffee270ddd64709e8aac2676ec3 @@ -52,18 +53,27 @@ theorem scaleQ67_eq : (scaleQ67 : Int) = 3814697265625 * 2 ^ 85 := by theorem scaleQ67_lt_2127 : scaleQ67 < 2 ^ 127 := by unfold scaleQ67; norm_num -theorem scaleMax_eq : scaleMax = 2 ^ 127 - 1 := by - unfold scaleMax +theorem int128Max_eq : int128Max = 2 ^ 127 - 1 := by + unfold int128Max norm_num -theorem scaleMax_lt_2127 : scaleMax < 2 ^ 127 := by - unfold scaleMax +theorem kernelScaleMax_eq : kernelScaleMax = 2 ^ 127 := by + unfold kernelScaleMax norm_num -theorem scaleQ67_le_scaleMax : scaleQ67 ≤ scaleMax := by - unfold scaleQ67 scaleMax +theorem scaleQ67_le_kernelScaleMax : scaleQ67 ≤ kernelScaleMax := by + unfold scaleQ67 kernelScaleMax norm_num +theorem mul_lt_2256_of_scale_le_kernelScaleMax {scale n : Nat} + (hscale : scale ≤ kernelScaleMax) (hn : n < 2 ^ 129) : scale * n < 2 ^ 256 := by + calc + scale * n ≤ kernelScaleMax * n := Nat.mul_le_mul_right n hscale + _ < kernelScaleMax * 2 ^ 129 := Nat.mul_lt_mul_of_pos_left hn (by + unfold kernelScaleMax + norm_num) + _ = 2 ^ 256 := by rw [kernelScaleMax_eq, ← pow_add] + theorem int256_Cmask : int256 Cmask = -41446531673892822312323846185 := by unfold Cmask int256 norm_num diff --git a/formal/exp/ExpProof/ExpProof/Mono/Cross.lean b/formal/exp/ExpProof/ExpProof/Mono/Cross.lean index 392c4bc59..8140f0f24 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Cross.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Cross.lean @@ -43,9 +43,9 @@ theorem numSum_lt {W : Nat} {ev tod : Int} (hW : int256 W = ev + tod) rw [hW, show (2:Int)^129 = 3 * 2^127 + 2^127 from by ring]; omega /-- The `mul scale N` dividend as a plain `Nat` product when `N`'s signed value is in -`[0, 2^129)` and `scale ≤ scaleMax`: `evmMul scale N = scale * N` (no wrap), and `N` is its own -signed value. -/ -theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ scaleMax) +`[0, 2^129)` and `scale ≤ kernelScaleMax`: `evmMul scale N = scale * N` (no wrap), and `N` is +its own signed value. -/ +theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ kernelScaleMax) (hNw : N < 2 ^ 256) (hNnn : 0 ≤ int256 N) (hNlt : int256 N < 2 ^ 129) : evmMul scale N = scale * N ∧ N < 2 ^ 129 := by @@ -53,18 +53,16 @@ theorem mulScale_transport {scale N : Nat} (hshi : scale ≤ scaleMax) have hNnat : N < 2 ^ 129 := by have : ((N : Nat) : Int) < 2 ^ 129 := by rw [← hNi]; exact hNlt exact_mod_cast this - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) - have hfit : scale * N < 2 ^ 256 := by - have h1 : scale * N ≤ scaleMax * 2 ^ 129 := - Nat.mul_le_mul hshi (le_of_lt hNnat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega + have hsw : scale < 2 ^ 256 := + lt_of_le_of_lt hshi (by unfold kernelScaleMax; norm_num) + have hfit : scale * N < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi hNnat exact ⟨evmMul_eq_nat hsw hNw hfit, hNnat⟩ /-- Abstract `r0` monotonicity from the `tod·ev` cross inequality, over opaque even/odd words. Given the numerator/denominator positivity and `tod1·ev2 ≤ tod2·ev1`, the two `div` quotients are `≤`-ordered. -/ -theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleMax) +theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ kernelScaleMax) (hE1 : E1 < 2 ^ 256) (hTD1 : TD1 < 2 ^ 256) (hE2 : E2 < 2 ^ 256) (hTD2 : TD2 < 2 ^ 256) (hev1_lo : (415147853590918758559635130244235626256 : Int) ≤ (E1 : Int)) (hev1_hi : (E1 : Int) < 3 * 2 ^ 127) @@ -86,7 +84,7 @@ theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleMax) have htod2_hi' : int256 TD2 < 2 ^ 126 := by have : (85070591730234615865843651857942052864 : Int) = 2 ^ 126 := by norm_num omega - -- numerator/denominator are positive and below 2^128 (signed) + -- The numerator is below 2^129 and the denominator is below 2^128. have hN1lt : int256 (evmAdd E1 TD1) < 2 ^ 129 := numSum_lt hadd1 hev1_hi htod1_hi' have hN2lt : int256 (evmAdd E2 TD2) < 2 ^ 129 := numSum_lt hadd2 hev2_hi htod2_hi' -- denominator positivity in `int256 (evmSub …)` form @@ -108,17 +106,10 @@ theorem r0_mono_of_cross {scale E1 TD1 E2 TD2 : Nat} (hshi : scale ≤ scaleMax) exact_mod_cast h have hD1nz : evmSub E1 TD1 ≠ 0 := Nat.pos_iff_ne_zero.mp hD1posN have hD2nz : evmSub E2 TD2 ≠ 0 := Nat.pos_iff_ne_zero.mp hD2posN - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) - have hfit1 : scale * evmAdd E1 TD1 < 2 ^ 256 := by - have h1 : scale * evmAdd E1 TD1 ≤ scaleMax * 2 ^ 129 := - Nat.mul_le_mul hshi (le_of_lt hN1nat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega - have hfit2 : scale * evmAdd E2 TD2 < 2 ^ 256 := by - have h1 : scale * evmAdd E2 TD2 ≤ scaleMax * 2 ^ 129 := - Nat.mul_le_mul hshi (le_of_lt hN2nat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega + have hfit1 : scale * evmAdd E1 TD1 < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi hN1nat + have hfit2 : scale * evmAdd E2 TD2 < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi hN2nat -- the two quotients as plain Nat floor divisions have hq1 : evmDiv (evmMul scale (evmAdd E1 TD1)) (evmSub E1 TD1) = scale * evmAdd E1 TD1 / evmSub E1 TD1 := by diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean index 8dd59e7af..6635ab987 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -26,9 +26,10 @@ def signTree (y : Nat) : Nat := def absTree (y : Nat) : Nat := evmSub (evmXor y (signTree y)) (signTree y) -/-- The scale headroom computed from the magnitude's bit length. -/ +/-- The scale headroom computed from the magnitude's bit length, with the `int128.min` +magnitude's wrapping subtraction saturated back to zero. -/ def scaleShiftTree (ay : Nat) : Nat := - evmSub (evmClz ay) scaleMaxClz + evmAdd (evmSub (evmClz ay) scaleClzBias) (evmShr 127 ay) /-- Dynamic pre-shift scale `abs(y) << S`. -/ def mulScaleTree (y : Nat) : Nat := @@ -40,9 +41,7 @@ def mulShiftTree (y x : Nat) : Nat := /-- The branch word for the `Panic(17)` guard. -/ def mulExpGuardTree (y x : Nat) : Nat := - let outOfRange := evmOr (evmGt (scaleShiftTree (absTree y)) 127) - (evmSgt x (evmSub mulExpRayHi 1)) - evmOr outOfRange (evmSlt (mulShiftTree y x) 2) + evmOr (evmSgt x (evmSub mulExpRayHi 1)) (evmSlt (mulShiftTree y x) 2) /-- The dynamic-scaled quotient before the closing shift. -/ def r0MulTree (y x : Nat) : Nat := @@ -73,7 +72,7 @@ theorem absTree_lt (y : Nat) : absTree y < 2 ^ 256 := by theorem scaleShiftTree_lt (ay : Nat) : scaleShiftTree ay < 2 ^ 256 := by unfold scaleShiftTree - exact evmSub_lt _ _ + exact evmAdd_lt _ _ theorem mulScaleTree_lt (y : Nat) : mulScaleTree y < 2 ^ 256 := by unfold mulScaleTree diff --git a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean index d6132bc3d..3f3e2b2c0 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/Quot.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/Quot.lean @@ -266,10 +266,11 @@ theorem r0Tree_bounds {x : Nat} (hx : x < 2 ^ 256) /-! ## The scaled quotient at a symbolic scale -/ -/-- Abstract scaled-quotient bounds at a symbolic scale `2^125 ≤ scale ≤ scaleMax`: `⌊scale·N/D⌋` +/-- Abstract scaled-quotient bounds at a symbolic scale `2^125 ≤ scale ≤ kernelScaleMax`: `⌊scale·N/D⌋` lies in `[2^123, 2^129)`. The lower bound is tight at the minimal scale: `2^123·D < 2^123·2^129 = 2^125·2^127 ≤ scale·N`. -/ -theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ kernelScaleMax) (hN : N < 2 ^ 129) (hDlt : D < 2 ^ 129) (hD : D < 2 ^ 256) (hDi : int256 D = (D : Int)) (hNpos : 0 < (N : Int)) (hDpos : 0 < (D : Int)) @@ -280,11 +281,10 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : have hNw : N < 2 ^ 256 := by have : (2:Nat) ^ 128 < 2 ^ 256 := by norm_num omega - have hsw : scale < 2 ^ 256 := lt_of_le_of_lt hshi (by unfold scaleMax; norm_num) - have hfit : scale * N < 2 ^ 256 := by - have h1 : scale * N ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi (le_of_lt hN) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega + have hsw : scale < 2 ^ 256 := + lt_of_le_of_lt hshi (by unfold kernelScaleMax; norm_num) + have hfit : scale * N < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi hN have hmul : evmMul scale N = scale * N := evmMul_eq_nat hsw hNw hfit have hDnat_pos : 0 < D := by exact_mod_cast hDpos have hdiv : evmDiv (evmMul scale N) D = scale * N / D := by @@ -297,10 +297,12 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : have h4 : ((4 * D : Nat) : Int) = 4 * (D : Int) := by push_cast; ring rw [← h4] at hND; exact_mod_cast hND have h1 : scale * N < scale * (4 * D) := (Nat.mul_lt_mul_left hspos).mpr hND' - have h2 : scale * (4 * D) ≤ scaleMax * (4 * D) := Nat.mul_le_mul_right _ hshi - have h3 : scaleMax * (4 * D) ≤ 2 ^ 129 * D := by - have h4S : (4:Nat) * scaleMax ≤ 2 ^ 129 := by unfold scaleMax; norm_num - calc scaleMax * (4 * D) = (4 * scaleMax) * D := by ring + have h2 : scale * (4 * D) ≤ kernelScaleMax * (4 * D) := Nat.mul_le_mul_right _ hshi + have h3 : kernelScaleMax * (4 * D) ≤ 2 ^ 129 * D := by + have h4S : (4 : Nat) * kernelScaleMax ≤ 2 ^ 129 := by + unfold kernelScaleMax + norm_num + calc kernelScaleMax * (4 * D) = (4 * kernelScaleMax) * D := by ring _ ≤ 2 ^ 129 * D := Nat.mul_le_mul_right _ h4S omega have hq_ge : 2 ^ 123 ≤ q := by @@ -318,9 +320,9 @@ theorem r0Scaled_bounds_of {scale N D : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : exact ⟨by exact_mod_cast hq_ge, by exact_mod_cast hq_lt⟩ /-- Abstract scaled `r0` bounds over opaque even/odd words: `2^123 ≤ r0 < 2^129` with -`r0 = div(scale·(E+TD), E−TD)` at any `2^125 ≤ scale ≤ scaleMax`. -/ +`r0 = div(scale·(E+TD), E−TD)` at any `2^125 ≤ scale ≤ kernelScaleMax`. -/ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) - (hshi : scale ≤ scaleMax) (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) + (hshi : scale ≤ kernelScaleMax) (hevw : E < 2 ^ 256) (htodw : TD < 2 ^ 256) (hev_lo : (415147853590918758559635130244235626256 : Int) ≤ (E : Int)) (hev_hi : (E : Int) < 3 * 2 ^ 127) (htod_lo : -(85070591730234615865843651857942052864 : Int) ≤ int256 TD) @@ -352,8 +354,10 @@ theorem r0Scaled_bounds_ofEvTod {scale E TD : Nat} (hslo : 2 ^ 125 ≤ scale) have hDpos : 0 < ((evmSub E TD : Nat) : Int) := by rw [← hDi, hsub]; omega exact r0Scaled_bounds_of hslo hshi hNlt129 hDlt129 hDwlt hDi hNpos hDpos hNlo hND -/-- `2^123 ≤ r0ScaledTree scale x < 2^129` on the wide region, for `2^125 ≤ scale ≤ scaleMax`. -/ -theorem r0Scaled_bounds {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) (hshi : scale ≤ scaleMax) +/-- `2^123 ≤ r0ScaledTree scale x < 2^129` on the wide region, for +`2^125 ≤ scale ≤ kernelScaleMax`. -/ +theorem r0Scaled_bounds {scale x : Nat} (hslo : 2 ^ 125 ≤ scale) + (hshi : scale ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : 2 ^ 123 ≤ int256 (r0ScaledTree scale x) ∧ int256 (r0ScaledTree scale x) < 2 ^ 129 := by obtain ⟨_, hvlt⟩ := vTree_eq_wide hx hW diff --git a/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean b/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean index 74afe71df..3a3ebe9b3 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/StepMono.lean @@ -51,7 +51,7 @@ theorem r0_mono_adjacent {x1 x2 : Nat} (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) have hr02 : r0Tree x2 = evmDiv (evmMul scaleQ67 (evmAdd (evTree x2) (todTree x2))) (evmSub (evTree x2) (todTree x2)) := rfl rw [hr01, hr02] - exact r0_mono_of_cross scaleQ67_le_scaleMax hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo + exact r0_mono_of_cross scaleQ67_le_kernelScaleMax hevw1 htodw1 hevw2 htodw2 hev1lo hev1hi htod1lo htod1hi hev2lo hev2hi htod2lo htod2hi hcross /-- The closing shift words coincide across an octave. -/ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean index ea241bf41..7bfa60ecc 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Accum.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Accum.lean @@ -9,7 +9,8 @@ magnitude, and at least two bits of closing shift — the kernel magnitude is th the decremented dynamic-scale quotient. The scale-symbolic per-point brackets (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) confine that quotient to `(scale·exp(rt) − 2993/1000 − 1, scale·exp(rt) + 1)` at `scale = mulScaleTree y ∈ -[2^125, scaleMax]`, and the target fold `A·2^shift = scale·exp(rt)` (`A = abs(y)·exp(x/10²⁷)`) +[2^125, kernelScaleMax]`, and the target fold `A·2^shift = scale·exp(rt)` +(`A = abs(y)·exp(x/10²⁷)`) turns the `shr` floor sandwich into the two-unit magnitude bracket `0 ≤ m ≤ A < m + 2`. Sign reapplication then yields the public signed bracket on the whole value domain, with the floor membership `m ∈ {⌊A⌋, ⌊A⌋ − 1}` and the `A < 1 → m = 0` pin as corollaries. @@ -81,7 +82,7 @@ noncomputable section /-- **Live-region magnitude bracket.** On the live region the kernel magnitude `m` is a nonnegative value below `2^127` with `m ≤ A < m + 2`. -/ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) + (hy0 : y ≠ 0) (habs : absTree y ≤ kernelScaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : 0 ≤ int256 (mulMagnitudeTree y x) ∧ @@ -89,7 +90,7 @@ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 2 (int256 (mulMagnitudeTree y x) : Real) ≤ mulExpRayMagnitudeTarget (int256 y) (int256 x) ∧ mulExpRayMagnitudeTarget (int256 y) (int256 x) < (int256 (mulMagnitudeTree y x) : Real) + 2 := by - -- the dynamic scale is live: 2^125 ≤ scale ≤ scaleMax + -- the dynamic scale is live: 2^125 ≤ scale ≤ kernelScaleMax have hpos : 1 ≤ absTree y := absTree_pos hy hy0 have hslo : 2 ^ 125 ≤ mulScaleTree y := mulScaleTree_lower hy hpos habs obtain ⟨hs256, hscale_eq, hshi⟩ := mulScaleTree_spec hy habs @@ -210,7 +211,7 @@ theorem mulMagnitude_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 2 /-- Live-region signed bracket for the tree result. -/ theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) + (hy0 : y ≠ 0) (habs : absTree y ≤ kernelScaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : MulExpRayBracket (int256 y) (int256 x) (int256 (mulExpTree y x)) := by @@ -269,7 +270,7 @@ theorem mulExpTree_bracket_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256 /-! ## Result range -/ theorem mulExpTree_int128_range_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (hy0 : y ≠ 0) (habs : absTree y ≤ scaleMax) + (hy0 : y ≠ 0) (habs : absTree y ≤ kernelScaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : -(2 ^ 127 : Int) ≤ int256 (mulExpTree y x) ∧ @@ -309,9 +310,8 @@ theorem mulExpTree_int128_range_live {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 theorem mulExpTree_int128_range {y x : Nat} (h : MulExpRayValueDomain y x) : -(2 ^ 127 : Int) ≤ int256 (mulExpTree y x) ∧ int256 (mulExpTree y x) < 2 ^ 127 := by - obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ := h - have habs : absTree y ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale + obtain ⟨⟨hy, hx⟩, hxhi, hlive⟩ := h + have habs : absTree y ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy rcases Nat.eq_zero_or_pos y with hy0 | hypos · subst hy0 rw [mulExpTree_zero, int256_zero_word] @@ -323,16 +323,7 @@ theorem mulExpTree_int128_range {y x : Nat} (h : MulExpRayValueDomain y x) : · have hxw0 : x = 0 := (int256_zero_iff_of_canonical hx).mp hx0 subst hxw0 rw [mulExpTree_scale_point hy.1 habs] - have habsNat : (int256 y).natAbs < 2 ^ 127 := by - rw [← absTree_eq_natAbs hy.1] - exact lt_of_le_of_lt habs scaleMax_lt_2127 - have habsInt : (((int256 y).natAbs : Nat) : Int) < 2 ^ 127 := by - exact_mod_cast habsNat - by_cases hyneg : int256 y < 0 - · rw [Int.ofNat_natAbs_of_nonpos (le_of_lt hyneg)] at habsInt - omega - · rw [Int.natAbs_of_nonneg (not_lt.mp hyneg)] at habsInt - omega + exact int256_range_of_signextend_15_eq_self hy.1 hy.2 · exact mulExpTree_int128_range_live hy.1 hx (by omega) habs hx0 ⟨by omega, hxhi⟩ hlive @@ -353,13 +344,12 @@ theorem run_mul_exp_ray_evm_eq_tree {y x : Nat} (h : MulExpRayValueDomain y x) : satisfying the signed two-unit magnitude bracket. -/ theorem mulExpRay_run_bracket {y x : Nat} (h : MulExpRayValueDomain y x) : MulExpRayRunBracket y x := by - obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ := h - have habs : absTree y ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale + obtain ⟨⟨hy, hx⟩, hxhi, hlive⟩ := h + have habs : absTree y ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy rcases Nat.eq_zero_or_pos y with hy0 | hypos · subst hy0 exact mulExpRay_run_bracket_zero x - ((valueDomain_iff_guard_eq_zero ⟨hy, hx⟩).mp ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩) + ((valueDomain_iff_guard_eq_zero ⟨hy, hx⟩).mp ⟨⟨hy, hx⟩, hxhi, hlive⟩) by_cases hclamp : int256 x ≤ int256 mulExpRayZeroMax · exact mulExpRay_run_bracket_clamped hy hx habs hlive hclamp by_cases hx0 : int256 x = 0 @@ -371,7 +361,7 @@ theorem mulExpRay_run_bracket {y x : Nat} (h : MulExpRayValueDomain y x) : · -- the live region have hWx : WideRegion x := ⟨by omega, hxhi⟩ have hrun : run_mul_exp_ray_evm y x = .ok (mulExpTree y x) := - run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, hscale, hxhi, hlive⟩ + run_mul_exp_ray_evm_eq_tree ⟨⟨hy, hx⟩, hxhi, hlive⟩ exact ⟨mulExpTree y x, hrun, mulExpTree_bracket_live hy.1 hx (by omega) habs hx0 hWx hlive⟩ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean index 2c728b58c..2d3b59ef1 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Domain.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Domain.lean @@ -5,10 +5,9 @@ import ExpProof.Mul.WordBridge # `mulExpRay` value and panic domains The runtime guard partitions canonical calldata into a value path and a `Panic(17)` path. Every -multiplier takes the same guard: the magnitude bound, the unconditional upper fence at the first -octave past the deficit envelope, and the accuracy test on the closing shift. Each predicate mirrors -one comparison of the compiled guard; `int256 (mulShiftTree y x) < 2` is exactly the runtime's -`slt(shift, 2)`. +multiplier takes the same guard: the unconditional upper fence at the first octave past the deficit +envelope and the accuracy test on the closing shift. Each predicate mirrors one comparison of the +compiled guard; `int256 (mulShiftTree y x) < 2` is exactly the runtime's `slt(shift, 2)`. -/ namespace ExpYul @@ -27,7 +26,7 @@ theorem int128Word_zero : Int128Word 0 := by unfold Int128Word decide -theorem int128Word_scaleMax : Int128Word scaleMax := by +theorem int128Word_max : Int128Word int128Max := by unfold Int128Word decide @@ -42,34 +41,28 @@ def MulExpRayCanonical (y x : Nat) : Prop := /-- The exact successful-input domain induced by the implementation guard. -/ def MulExpRayValueDomain (y x : Nat) : Prop := MulExpRayCanonical y x ∧ - scaleShiftTree (absTree y) ≤ 127 ∧ - int256 x < int256 mulExpRayHi ∧ 2 ≤ int256 (mulShiftTree y x) + int256 x < int256 mulExpRayHi ∧ 2 ≤ int256 (mulShiftTree y x) /-- The exact panic domain induced by the implementation guard. -/ def MulExpRayPanicDomain (y x : Nat) : Prop := MulExpRayCanonical y x ∧ - (127 < scaleShiftTree (absTree y) ∨ - int256 mulExpRayHi ≤ int256 x ∨ - int256 (mulShiftTree y x) < 2) + (int256 mulExpRayHi ≤ int256 x ∨ int256 (mulShiftTree y x) < 2) /-- Canonical inputs are either accepted by the value guard or rejected by the panic guard. -/ theorem mulExpRay_value_or_panic_of_canonical {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := by - by_cases hscale : scaleShiftTree (absTree y) ≤ 127 - · by_cases hxhi : int256 x < int256 mulExpRayHi - · by_cases hshift : 2 ≤ int256 (mulShiftTree y x) - · exact Or.inl ⟨hcanon, hscale, hxhi, hshift⟩ - · exact Or.inr ⟨hcanon, Or.inr (Or.inr (by omega))⟩ - · exact Or.inr ⟨hcanon, Or.inr (Or.inl (by omega))⟩ + by_cases hxhi : int256 x < int256 mulExpRayHi + · by_cases hshift : 2 ≤ int256 (mulShiftTree y x) + · exact Or.inl ⟨hcanon, hxhi, hshift⟩ + · exact Or.inr ⟨hcanon, Or.inr (by omega)⟩ · exact Or.inr ⟨hcanon, Or.inl (by omega)⟩ /-- The accepted and rejected guard domains are disjoint. -/ theorem mulExpRay_value_not_panic {y x : Nat} : MulExpRayValueDomain y x → ¬ MulExpRayPanicDomain y x := by intro hv hp - obtain ⟨_, hscale, hxhi, hlive⟩ := hv - obtain ⟨_, hbadScale | hbadHi | hbadShift⟩ := hp - · omega + obtain ⟨_, hxhi, hlive⟩ := hv + obtain ⟨_, hbadHi | hbadShift⟩ := hp · omega · omega @@ -89,11 +82,8 @@ theorem mulExpRay_value_iff_not_panic {y x : Nat} (hcanon : MulExpRayCanonical y /-- The guard word is the `if`-encoding of the exact panic condition. -/ theorem mulExpGuardTree_eq_ite {y x : Nat} (hx : x < 2 ^ 256) : mulExpGuardTree y x = - if 127 < scaleShiftTree (absTree y) ∨ int256 mulExpRayHi ≤ int256 x ∨ - int256 (mulShiftTree y x) < 2 then 1 else 0 := by + if int256 mulExpRayHi ≤ int256 x ∨ int256 (mulShiftTree y x) < 2 then 1 else 0 := by have hux : u256 x = x := u256_of_lt_pow256 hx - have hs : u256 (scaleShiftTree (absTree y)) = scaleShiftTree (absTree y) := - u256_of_lt_pow256 (scaleShiftTree_lt _) have hsh : u256 (mulShiftTree y x) = mulShiftTree y x := u256_of_lt_pow256 (mulShiftTree_lt y x) have hhim1 : evmSub mulExpRayHi 1 = mulExpRayHi - 1 := by @@ -102,16 +92,12 @@ theorem mulExpGuardTree_eq_ite {y x : Nat} (hx : x < 2 ^ 256) : have hhim1w : evmSub mulExpRayHi 1 < 2 ^ 256 := evmSub_lt _ _ have hhim1u : u256 (evmSub mulExpRayHi 1) = evmSub mulExpRayHi 1 := u256_of_lt_pow256 hhim1w - have h127 : u256 127 = 127 := u256_of_lt_pow256 (by norm_num) have h2 : u256 2 = 2 := u256_of_lt_pow256 (by norm_num) have hint2 : int256 (u256 2) = 2 := by rw [h2]; unfold int256; norm_num have hhi : int256 (evmSub mulExpRayHi 1) = int256 mulExpRayHi - 1 := by rw [hhim1, int256_mulExpRayHi] unfold mulExpRayHi int256 norm_num - have hscaleCmp : evmGt (scaleShiftTree (absTree y)) 127 = - if 127 < scaleShiftTree (absTree y) then 1 else 0 := by - rw [evmGt_eq_ite, hs, h127] have hxCmp : evmSgt x (evmSub mulExpRayHi 1) = if int256 mulExpRayHi ≤ int256 x then 1 else 0 := by rw [evmSgt_eq_evmSlt_swap, evmSlt_eq_ite, hhim1u, hux, hhi] @@ -120,14 +106,12 @@ theorem mulExpGuardTree_eq_ite {y x : Nat} (hx : x < 2 ^ 256) : if int256 (mulShiftTree y x) < 2 then 1 else 0 := by rw [evmSlt_eq_ite, hsh, hint2] unfold mulExpGuardTree - rw [hscaleCmp, hxCmp, evmOr_ite, hshiftCmp, evmOr_ite] - simp only [or_assoc] + rw [hxCmp, hshiftCmp, evmOr_ite] /-- The guard word is zero exactly on the accepted inputs. -/ theorem mulExpGuardTree_eq_zero_iff {y x : Nat} (hx : x < 2 ^ 256) : mulExpGuardTree y x = 0 ↔ - scaleShiftTree (absTree y) ≤ 127 ∧ int256 x < int256 mulExpRayHi ∧ - 2 ≤ int256 (mulShiftTree y x) := by + int256 x < int256 mulExpRayHi ∧ 2 ≤ int256 (mulShiftTree y x) := by rw [mulExpGuardTree_eq_ite hx, ite_one_zero_eq_zero_iff] push_neg omega @@ -135,8 +119,7 @@ theorem mulExpGuardTree_eq_zero_iff {y x : Nat} (hx : x < 2 ^ 256) : /-- The guard word is one exactly on the rejected inputs. -/ theorem mulExpGuardTree_eq_one_iff {y x : Nat} (hx : x < 2 ^ 256) : mulExpGuardTree y x = 1 ↔ - 127 < scaleShiftTree (absTree y) ∨ int256 mulExpRayHi ≤ int256 x ∨ - int256 (mulShiftTree y x) < 2 := by + int256 mulExpRayHi ≤ int256 x ∨ int256 (mulShiftTree y x) < 2 := by rw [mulExpGuardTree_eq_ite hx, ite_one_zero_eq_one_iff] /-- The value domain is exactly the guard word being zero. -/ diff --git a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean index 3f9e93450..720cdbd2e 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Joint.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Joint.lean @@ -9,9 +9,8 @@ in the magnitude: shrinking the magnitude only grows the accepted exponent set. case needs no intermediate — a nonpositive multiplier's result is nonpositive and a nonnegative multiplier's is nonnegative, directly from the signed bracket's shape. -The guard also admits the magnitude vocabulary of the natspec: on canonical inputs, rejection -is exactly a magnitude above `scaleMax`, an exponent at or beyond the unconditional fence, or -an unconditional closing shift below two. +The guard rejects at the unconditional exponent fence or when fewer than two closing-shift bits +remain. Canonical `int128` multipliers already bound every magnitude by the inclusive analytic cap. -/ namespace ExpYul @@ -26,13 +25,13 @@ set_option maxHeartbeats 1600000 /-! ## Acceptance transfers along the antitone headroom -/ /-- The headroom shift is antitone in the magnitude, including the zero magnitude. -/ -theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleMax) : +theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ kernelScaleMax) : scaleShiftTree b ≤ scaleShiftTree a := by rcases Nat.eq_zero_or_pos a with h0 | hpos · subst h0 rw [scaleShiftTree_zero] have hb' : absTree b = b := - absTree_nonneg (lt_of_le_of_lt hb (by unfold scaleMax; norm_num)) + absTree_nonneg (lt_of_le_of_lt hb (by unfold kernelScaleMax; norm_num)) have h := scaleShiftTree_le_127 (y := b) (by rw [hb']; exact hb) rw [hb'] at h exact h @@ -42,13 +41,10 @@ theorem scaleShift_antitone' {a b : Nat} (hab : a ≤ b) (hb : b ≤ scaleMax) : theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : Int128Word y1) (h2 : MulExpRayValueDomain y2 x) (hab : absTree y1 ≤ absTree y2) : MulExpRayValueDomain y1 x := by - obtain ⟨⟨_, hx⟩, hscale2, hxhi, hlv2⟩ := h2 - have habs2 : absTree y2 ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y2)).mp hscale2 - have habs1 : absTree y1 ≤ scaleMax := le_trans hab habs2 - have hscale1 : scaleShiftTree (absTree y1) ≤ 127 := - (scaleShiftTree_le_127_iff (absTree_lt y1)).mpr habs1 - refine ⟨⟨hy1, hx⟩, hscale1, hxhi, ?_⟩ + obtain ⟨⟨hy2, hx⟩, hxhi, hlv2⟩ := h2 + have habs2 : absTree y2 ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy2 + have habs1 : absTree y1 ≤ kernelScaleMax := le_trans hab habs2 + refine ⟨⟨hy1, hx⟩, hxhi, ?_⟩ have ht1 := mulShiftTree_transport_global (y := y1) (x := x) habs1 have ht2 := mulShiftTree_transport_global (y := y2) (x := x) habs2 have hanti : scaleShiftTree (absTree y2) ≤ scaleShiftTree (absTree y1) := @@ -64,9 +60,8 @@ theorem valueDomain_of_abs_le {y1 y2 x : Nat} (hy1 : Int128Word y1) /-- A nonnegative multiplier's accepted result is nonnegative. -/ theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) (hyw : y < 2 ^ 255) : 0 ≤ int256 (mulExpTree y x) := by - obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlv⟩ := h - have habs : absTree y ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale + obtain ⟨⟨hy, hx⟩, hxhi, hlv⟩ := h + have habs : absTree y ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy rcases Nat.eq_zero_or_pos y with h0 | hpos · subst h0 rw [mulExpTree_zero, int256_zero_word'] @@ -86,9 +81,8 @@ theorem mulExpTree_result_nonneg {y x : Nat} (h : MulExpRayValueDomain y x) /-- A nonpositive multiplier's accepted result is nonpositive. -/ theorem mulExpTree_result_nonpos {y x : Nat} (h : MulExpRayValueDomain y x) (hyneg : int256 y ≤ 0) : int256 (mulExpTree y x) ≤ 0 := by - obtain ⟨⟨hy, hx⟩, hscale, hxhi, hlv⟩ := h - have habs : absTree y ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale + obtain ⟨⟨hy, hx⟩, hxhi, hlv⟩ := h + have habs : absTree y ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy rcases Nat.eq_zero_or_pos y with h0 | hpos · subst h0 rw [mulExpTree_zero, int256_zero_word'] @@ -218,47 +212,4 @@ theorem run_mul_exp_ray_evm_mono_joint {y1 y2 x1 x2 : Nat} have h2nn := mulExpTree_result_nonneg h2 hy2small linarith [h1np, h2nn] -/-! ## The guard in magnitude vocabulary -/ - -/-- **The panic domain in magnitude language.** On canonical inputs, `mulExpRay` rejects exactly -when the magnitude exceeds `scaleMax`, the exponent reaches the unconditional upper fence, or -the unconditional closing-shift guard fails. -/ -theorem panicDomain_iff_magnitude_guard {y x : Nat} (hcanon : MulExpRayCanonical y x) : - MulExpRayPanicDomain y x ↔ - scaleMax < absTree y ∨ int256 mulExpRayHi ≤ int256 x ∨ - int256 (mulShiftTree y x) < 2 := by - obtain ⟨hy, hx⟩ := hcanon - constructor - · rintro ⟨_, hbad⟩ - rcases hbad with h | h | h - · have hiff := scaleShiftTree_le_127_iff (absTree_lt y) - exact Or.inl (by - by_contra hcap - have := hiff.mpr (by omega : absTree y ≤ scaleMax) - omega) - · exact Or.inr (Or.inl h) - · exact Or.inr (Or.inr h) - · rintro (h | h | h) - · have hiff := scaleShiftTree_le_127_iff (absTree_lt y) - refine ⟨⟨hy, hx⟩, Or.inl ?_⟩ - by_contra hshift - have := hiff.mp (by omega : scaleShiftTree (absTree y) ≤ 127) - omega - · exact ⟨⟨hy, hx⟩, Or.inr (Or.inl h)⟩ - · exact ⟨⟨hy, hx⟩, Or.inr (Or.inr h)⟩ - -/-- **The `type(int128).min` multiplier always reverts**: its magnitude is `2^127`, above -the maximal scale. -/ -theorem run_mul_exp_ray_evm_revert_int128_min {x : Nat} (hx : x < 2 ^ 256) : - run_mul_exp_ray_evm (2 ^ 256 - 2 ^ 127) x = .error "revert" := by - apply run_mul_exp_ray_evm_revert - refine ⟨⟨int128Word_min, hx⟩, Or.inl ?_⟩ - have hiff := scaleShiftTree_le_127_iff (absTree_lt (2 ^ 256 - 2 ^ 127)) - by_contra hshift - have hcap := hiff.mp - (by omega : scaleShiftTree (absTree (2 ^ 256 - 2 ^ 127)) ≤ 127) - rw [absTree_neg (by norm_num) (by norm_num)] at hcap - unfold scaleMax at hcap - norm_num at hcap - end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean index ae6f5664a..0ddeb584a 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean @@ -144,6 +144,20 @@ theorem absTree_eq_natAbs {y : Nat} (hy : y < 2 ^ 256) : have hyl : (2 ^ 255 : Int) ≤ (y : Int) := by exact_mod_cast (by omega : 2 ^ 255 ≤ y) omega +theorem absTree_le_kernelScaleMax_of_int128Word {y : Nat} (hy : Int128Word y) : + absTree y ≤ kernelScaleMax := by + rw [absTree_eq_natAbs hy.1, kernelScaleMax_eq] + obtain ⟨hlo, hhi⟩ := int256_range_of_signextend_15_eq_self hy.1 hy.2 + by_cases hneg : int256 y < 0 + · have hnatI : (((int256 y).natAbs : Nat) : Int) ≤ 2 ^ 127 := by + rw [Int.ofNat_natAbs_of_nonpos (le_of_lt hneg)] + exact neg_le_neg hlo + exact_mod_cast hnatI + · have hnatI : (((int256 y).natAbs : Nat) : Int) ≤ 2 ^ 127 := by + rw [Int.natAbs_of_nonneg (not_lt.mp hneg)] + exact le_of_lt hhi + exact_mod_cast hnatI + theorem sgnTree_pos {y : Nat} (hpos : 0 < y) (hy : y < 2 ^ 255) : sgnTree y = 1 := by unfold sgnTree rw [signTree_nonneg hy, absTree_nonneg hy] @@ -196,27 +210,26 @@ theorem mulExpTree_negative {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) /-! ## The scale headroom realizes the scale exactly -/ -theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) : +theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) + (habs : absTree y ≤ kernelScaleMax) : scaleShiftTree (absTree y) ≤ 127 ∧ mulScaleTree y = absTree y * 2 ^ scaleShiftTree (absTree y) ∧ - mulScaleTree y ≤ scaleMax := by + mulScaleTree y ≤ kernelScaleMax := by have haylt : absTree y < 2 ^ 256 := absTree_lt y - have hay127 : absTree y < 2 ^ 127 := - lt_of_le_of_lt habs scaleMax_lt_2127 rcases Nat.eq_zero_or_pos (absTree y) with h0 | hpos · have hclz : evmClz 0 = 256 := by unfold evmClz rw [u256_self (by norm_num)] simp - have hs : evmSub 256 scaleMaxClz = 127 := by - rw [evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] - unfold scaleMaxClz + have hs : evmSub 256 scaleClzBias = 127 := by + rw [evmSub_small (by unfold scaleClzBias; omega) (by norm_num)] + unfold scaleClzBias norm_num have hsst : scaleShiftTree (absTree y) = 127 := by rw [h0] unfold scaleShiftTree - rw [hclz] - exact hs + rw [hclz, hs] + norm_num [evmShr, evmAdd, u256, WORD_MOD] have hshl : evmShl 127 (0 : Nat) = 0 := by rw [evmShl_small (by norm_num) (by norm_num) (by norm_num)] ring @@ -225,44 +238,84 @@ theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) (habs : absTree y ≤ sc rw [hsst, h0, hshl] rw [hsst, hscale, h0] exact ⟨by norm_num, by ring, Nat.zero_le _⟩ - · have hlog : Nat.log2 (absTree y) ≤ 126 := by - have h1 : 2 ^ Nat.log2 (absTree y) ≤ absTree y := - Nat.log2_self_le (by omega) - by_contra h - push_neg at h - have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 (absTree y) := - Nat.pow_le_pow_right (by norm_num) h - omega - have hlt : absTree y < 2 ^ (Nat.log2 (absTree y) + 1) := - Nat.lt_log2_self - have hclz : evmClz (absTree y) = 255 - Nat.log2 (absTree y) := by - unfold evmClz - rw [u256_self haylt, if_neg (by omega)] - have hs : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) := by - unfold scaleShiftTree - rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] - unfold scaleMaxClz + · by_cases hend : absTree y = kernelScaleMax + · have hs : scaleShiftTree (absTree y) = 0 := by + rw [hend, kernelScaleMax_eq] + have hloglo : 127 ≤ Nat.log2 (2 ^ 127) := + (Nat.le_log2 (by norm_num)).2 (by norm_num) + have hloghi : Nat.log2 (2 ^ 127) < 128 := + (Nat.log2_lt (by norm_num)).2 (by norm_num) + have hlog : Nat.log2 (2 ^ 127) = 127 := by omega + have hclz : evmClz (2 ^ 127) = 128 := by + unfold evmClz + rw [u256_self (by norm_num), if_neg (by norm_num), hlog] + have hsub : evmSub 128 scaleClzBias = 2 ^ 256 - 1 := by + norm_num [evmSub, scaleClzBias, u256, WORD_MOD] + have hshr : evmShr 127 (2 ^ 127) = 1 := by + norm_num [evmShr, u256, WORD_MOD] + unfold scaleShiftTree + rw [hclz, hsub, hshr] + norm_num [evmAdd, u256, WORD_MOD] + have hscale : mulScaleTree y = kernelScaleMax := by + unfold mulScaleTree + rw [hs, hend] + norm_num [evmShl, u256, WORD_MOD] + rw [hs, hscale] + exact ⟨by norm_num, by rw [hend, kernelScaleMax_eq]; norm_num, le_refl _⟩ + · have hay127 : absTree y < 2 ^ 127 := by + rw [← kernelScaleMax_eq] + omega + have hlog : Nat.log2 (absTree y) ≤ 126 := by + have h1 : 2 ^ Nat.log2 (absTree y) ≤ absTree y := + Nat.log2_self_le (by omega) + by_contra h + push_neg at h + have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 (absTree y) := + Nat.pow_le_pow_right (by norm_num) h + omega + have hlt : absTree y < 2 ^ (Nat.log2 (absTree y) + 1) := + Nat.lt_log2_self + have hclz : evmClz (absTree y) = 255 - Nat.log2 (absTree y) := by + unfold evmClz + rw [u256_self haylt, if_neg (by omega)] + have hshr : evmShr 127 (absTree y) = 0 := by + unfold evmShr + rw [u256_self (by norm_num), u256_self haylt, if_pos (by norm_num)] + exact Nat.div_eq_of_lt hay127 + have hs : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) := by + unfold scaleShiftTree + have hsub : evmSub (255 - Nat.log2 (absTree y)) scaleClzBias = + 126 - Nat.log2 (absTree y) := by + rw [evmSub_small (by unfold scaleClzBias; omega) (by omega)] + unfold scaleClzBias + omega + rw [hclz, hshr, hsub] + unfold evmAdd + have hshiftlt : 126 - Nat.log2 (absTree y) < 2 ^ 256 := by + exact lt_of_le_of_lt (Nat.sub_le _ _) (by norm_num) + rw [show u256 (126 - Nat.log2 (absTree y)) = 126 - Nat.log2 (absTree y) from + u256_self hshiftlt, show u256 0 = 0 from u256_self (by norm_num)] + rw [Nat.add_zero, u256_self hshiftlt] + have hfit : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) < 2 ^ 127 := by + calc absTree y * 2 ^ (126 - Nat.log2 (absTree y)) + < 2 ^ (Nat.log2 (absTree y) + 1) * + 2 ^ (126 - Nat.log2 (absTree y)) := + mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) + _ = 2 ^ (Nat.log2 (absTree y) + 1 + + (126 - Nat.log2 (absTree y))) := by + rw [← pow_add] + _ ≤ 2 ^ 127 := Nat.pow_le_pow_right (by norm_num) (by omega) + have hshl : evmShl (126 - Nat.log2 (absTree y)) (absTree y) = + absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := + evmShl_small (by omega) haylt (lt_trans hfit (by norm_num)) + have hscale : mulScaleTree y = + absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := by + unfold mulScaleTree + rw [hs, hshl] + rw [hs, hscale] + refine ⟨by omega, rfl, ?_⟩ + rw [kernelScaleMax_eq] omega - have hfit : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) < 2 ^ 127 := by - calc absTree y * 2 ^ (126 - Nat.log2 (absTree y)) - < 2 ^ (Nat.log2 (absTree y) + 1) * - 2 ^ (126 - Nat.log2 (absTree y)) := - mul_lt_mul_of_pos_right hlt (Nat.two_pow_pos _) - _ = 2 ^ (Nat.log2 (absTree y) + 1 + - (126 - Nat.log2 (absTree y))) := by - rw [← pow_add] - _ ≤ 2 ^ 127 := Nat.pow_le_pow_right (by norm_num) (by omega) - have hshl : evmShl (126 - Nat.log2 (absTree y)) (absTree y) = - absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := - evmShl_small (by omega) haylt (lt_trans hfit (by norm_num)) - have hscale : mulScaleTree y = - absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := by - unfold mulScaleTree - rw [hs, hshl] - rw [hs, hscale] - refine ⟨by omega, rfl, ?_⟩ - rw [scaleMax_eq] - omega /-! ## The scale point `x = 0` -/ private theorem kTree_zero : kTree 0 = 0 := by @@ -295,7 +348,7 @@ private theorem todTree_zero : todTree 0 = 0 := by norm_num [evmSar, evmMul, u256, WORD_MOD] private theorem r0MulTree_scale_point {y : Nat} (hy : y < 2 ^ 256) - (habs : absTree y ≤ scaleMax) : r0MulTree y 0 = mulScaleTree y := by + (habs : absTree y ≤ kernelScaleMax) : r0MulTree y 0 = mulScaleTree y := by obtain ⟨_, _, hcap⟩ := mulScaleTree_spec hy habs unfold r0MulTree have hnum : evmAdd (evTree 0) (todTree 0) = ev4 := by @@ -308,8 +361,8 @@ private theorem r0MulTree_scale_point {y : Nat} (hy : y < 2 ^ 256) rw [hnum, hden] exact evmDiv_exact (by unfold ev4; norm_num) (mulScaleTree_lt y) (by unfold ev4; norm_num) (by - calc mulScaleTree y * ev4 ≤ scaleMax * ev4 := Nat.mul_le_mul_right _ hcap - _ < 2 ^ 256 := by unfold scaleMax ev4; norm_num) + calc mulScaleTree y * ev4 ≤ kernelScaleMax * ev4 := Nat.mul_le_mul_right _ hcap + _ < 2 ^ 256 := by unfold kernelScaleMax ev4; norm_num) private theorem mulShiftTree_scale_point (y : Nat) : mulShiftTree y 0 = scaleShiftTree (absTree y) := by @@ -318,10 +371,10 @@ private theorem mulShiftTree_scale_point (y : Nat) : omega theorem mulMagnitudeTree_scale_point {y : Nat} (hy : y < 2 ^ 256) - (hpos : 0 < absTree y) (habs : absTree y ≤ scaleMax) : + (hpos : 0 < absTree y) (habs : absTree y ≤ kernelScaleMax) : mulMagnitudeTree y 0 = absTree y := by obtain ⟨hs256, hscale, hcap⟩ := mulScaleTree_spec hy habs - have hQlt : scaleMax < 2 ^ 256 := by unfold scaleMax; norm_num + have hQlt : kernelScaleMax < 2 ^ 256 := by unfold kernelScaleMax; norm_num have hscalepos : 0 < mulScaleTree y := by rw [hscale] exact Nat.mul_pos hpos (Nat.two_pow_pos _) @@ -366,7 +419,8 @@ theorem mulMagnitudeTree_scale_point {y : Nat} (hy : y < 2 ^ 256) omega /-- **Scale point (tree).** At `x = 0`, the result word is the multiplier itself. -/ -theorem mulExpTree_scale_point {y : Nat} (hy : y < 2 ^ 256) (habs : absTree y ≤ scaleMax) : +theorem mulExpTree_scale_point {y : Nat} (hy : y < 2 ^ 256) + (habs : absTree y ≤ kernelScaleMax) : mulExpTree y 0 = y := by rcases Nat.eq_zero_or_pos y with h0 | hypos · subst h0 @@ -408,12 +462,11 @@ private theorem int256_zero_word : int256 (0 : Nat) = 0 := by unfold int256; nor /-- **Scale point.** `mulExpRay(y, 0)` returns `y` whenever the two-bit closing-shift guard accepts. -/ theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : Int128Word y) - (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : + (habs : absTree y ≤ kernelScaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := by - obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy.1 habs have hguard : mulExpGuardTree y 0 = 0 := by rw [mulExpGuardTree_eq_zero_iff (by norm_num)] - refine ⟨hs127, ?_, hshift⟩ + refine ⟨?_, hshift⟩ rw [int256_mulExpRayHi, int256_zero_word] norm_num have hresultClean : @@ -426,13 +479,12 @@ theorem run_mul_exp_ray_evm_scale_point {y : Nat} (hy : Int128Word y) /-- **Clamp.** An accepted `mulExpRay(y, x)` returns zero at or below the zero cutoff. -/ theorem run_mul_exp_ray_evm_clamped {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) + (hshift : 2 ≤ int256 (mulShiftTree y x)) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : run_mul_exp_ray_evm y x = .ok 0 := by - obtain ⟨hs127, _, _⟩ := mulScaleTree_spec hy.1 habs have hguard : mulExpGuardTree y x = 0 := by rw [mulExpGuardTree_eq_zero_iff hx] - refine ⟨hs127, ?_, hshift⟩ + refine ⟨?_, hshift⟩ rw [int256_mulExpRayHi] rw [int256_mulExpRayZeroMax] at hclamp omega @@ -450,7 +502,7 @@ noncomputable section /-- **Scale-point bracket.** The exact result `y` satisfies the public bracket at `x = 0`. -/ theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : Int128Word y) - (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : + (habs : absTree y ≤ kernelScaleMax) (hshift : 2 ≤ int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := by refine ⟨y, run_mul_exp_ray_evm_scale_point hy habs hshift, ?_⟩ rw [int256_zero_word] @@ -482,7 +534,7 @@ theorem mulExpRay_run_bracket_scale_point {y : Nat} (hy : Int128Word y) /-- Below the zero cutoff, every supported magnitude's real target is below one. -/ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : + (habs : absTree y ≤ kernelScaleMax) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : mulExpRayMagnitudeTarget (int256 y) (int256 x) < 1 := by unfold mulExpRayMagnitudeTarget have hRAY : (RAY : ℝ) = 10 ^ 27 := by unfold RAY; push_cast; norm_num @@ -501,11 +553,11 @@ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) rw [Real.log_pow]; push_cast; ring] rw [Real.exp_log (by positivity)] ring - have hnat : ((int256 y).natAbs : ℝ) ≤ ((scaleMax : Nat) : ℝ) := by + have hnat : ((int256 y).natAbs : ℝ) ≤ ((kernelScaleMax : Nat) : ℝ) := by have h := absTree_eq_natAbs hy exact_mod_cast (h ▸ habs) - have hQ : ((scaleMax : Nat) : ℝ) < (2 : ℝ) ^ (127 : ℕ) := by - unfold scaleMax + have hQ : ((kernelScaleMax : Nat) : ℝ) ≤ (2 : ℝ) ^ (127 : ℕ) := by + unfold kernelScaleMax norm_num calc ((int256 y).natAbs : ℝ) * Real.exp z ≤ (2 : ℝ) ^ (127 : ℕ) * Real.exp z := by @@ -516,10 +568,10 @@ theorem clamped_target_lt_one {y x : Nat} (hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) /-- **Clamp bracket.** The zero result satisfies the public bracket at or below the cutoff. -/ theorem mulExpRay_run_bracket_clamped {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) + (habs : absTree y ≤ kernelScaleMax) (hshift : 2 ≤ int256 (mulShiftTree y x)) (hclamp : int256 x ≤ int256 mulExpRayZeroMax) : MulExpRayRunBracket y x := by - refine ⟨0, run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp, ?_⟩ + refine ⟨0, run_mul_exp_ray_evm_clamped hy hx hshift hclamp, ?_⟩ rw [int256_zero_word] have hlt := clamped_target_lt_one hy.1 hx habs hclamp have hnn := mulExpRayMagnitudeTarget_nonneg (int256 y) (int256 x) diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean index e2db20200..fa4b35ebc 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -11,8 +11,9 @@ shift `S − k`. This module transports those words to arithmetic facts the accu monotonicity arguments consume: * the headroom shift `S` is at most `127`, and for a nonzero magnitude the scale is *maximal* — - the all-ones 127-bit cap aligns every nonzero supported magnitude into `[2^126, 2^127)`, so every - live scale satisfies `2^125 ≤ scale ≤ scaleMax`; + every supported magnitude is normalized at or immediately below bit 126, except the inclusive + `2^127` endpoint, which stays at that endpoint, so every live scale satisfies + `2^125 ≤ scale ≤ kernelScaleMax`; * the closing-shift word is the signed difference `S − k` on the wide region, and on the live region (`2 ≤ shift` from the guard) it is a plain small `Nat` in `[2, 254]`; * the closing `shr` keeps nonnegative small values small for any shift below the word size. @@ -46,111 +47,107 @@ private theorem evmShl_small {s v : Nat} (hs : s < 256) (hv : v < 2 ^ 256) /-! ## The headroom shift and normalized scale -/ -/-- Every positive supported magnitude aligns its highest set bit with bit 126. -/ -private theorem scaleShiftTree_pos {ay : Nat} (hy : ay < 2 ^ 256) - (hpos : 1 ≤ ay) (habs : ay ≤ scaleMax) : +/-- Every positive supported magnitude aligns its highest set bit with bit 126, except the +inclusive endpoint, whose normalization shift is zero. -/ +theorem scaleShiftTree_pos {ay : Nat} (hy : ay < 2 ^ 256) + (hpos : 1 ≤ ay) (habs : ay ≤ kernelScaleMax) : scaleShiftTree ay = 126 - Nat.log2 ay := by - have hay127 : ay < 2 ^ 127 := lt_of_le_of_lt habs scaleMax_lt_2127 - have hlog : Nat.log2 ay ≤ 126 := by - have h1 : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) - by_contra h - push_neg at h - have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 ay := - Nat.pow_le_pow_right (by norm_num) h - omega - have hclz : evmClz ay = 255 - Nat.log2 ay := by - unfold evmClz - rw [u256_self hy, if_neg (by omega)] - unfold scaleShiftTree - rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by omega)] - unfold scaleMaxClz - omega + by_cases hend : ay = kernelScaleMax + · rw [hend, kernelScaleMax_eq] + have hloglo : 127 ≤ Nat.log2 (2 ^ 127) := + (Nat.le_log2 (by norm_num)).2 (by norm_num) + have hloghi : Nat.log2 (2 ^ 127) < 128 := + (Nat.log2_lt (by norm_num)).2 (by norm_num) + have hlog : Nat.log2 (2 ^ 127) = 127 := by omega + have hclz : evmClz (2 ^ 127) = 128 := by + unfold evmClz + rw [u256_self (by norm_num), if_neg (by norm_num), hlog] + have hsub : evmSub 128 scaleClzBias = 2 ^ 256 - 1 := by + norm_num [evmSub, scaleClzBias, u256, WORD_MOD] + have hshr : evmShr 127 (2 ^ 127) = 1 := by + norm_num [evmShr, u256, WORD_MOD] + unfold scaleShiftTree + rw [hclz, hsub, hshr] + have hadd : evmAdd (2 ^ 256 - 1) 1 = 0 := by + norm_num [evmAdd, u256, WORD_MOD] + rw [hadd] + change 0 = 126 - Nat.log2 (2 ^ 127) + rw [hlog] + · have hay127 : ay < 2 ^ 127 := by rw [← kernelScaleMax_eq]; omega + have hlog : Nat.log2 ay ≤ 126 := by + have h1 : 2 ^ Nat.log2 ay ≤ ay := Nat.log2_self_le (by omega) + by_contra h + push_neg at h + have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 ay := + Nat.pow_le_pow_right (by norm_num) h + omega + have hclz : evmClz ay = 255 - Nat.log2 ay := by + unfold evmClz + rw [u256_self hy, if_neg (by omega)] + have hshr : evmShr 127 ay = 0 := by + unfold evmShr + rw [u256_self (by norm_num), u256_self hy, if_pos (by norm_num)] + exact Nat.div_eq_of_lt hay127 + have hsub : evmSub (255 - Nat.log2 ay) scaleClzBias = 126 - Nat.log2 ay := by + rw [evmSub_small (by unfold scaleClzBias; omega) (by omega)] + unfold scaleClzBias + omega + unfold scaleShiftTree + rw [hclz, hshr, hsub] + unfold evmAdd + have hshiftlt : 126 - Nat.log2 ay < 2 ^ 256 := + lt_of_le_of_lt (Nat.sub_le _ _) (by norm_num) + rw [show u256 (126 - Nat.log2 ay) = 126 - Nat.log2 ay from u256_self hshiftlt, + show u256 0 = 0 from u256_self (by norm_num)] + rw [Nat.add_zero, u256_self hshiftlt] -/-- The zero magnitude takes the maximal headroom shift. -/ theorem scaleShiftTree_zero : scaleShiftTree 0 = 127 := by have hclz : evmClz 0 = 256 := by unfold evmClz rw [u256_self (by norm_num)] simp unfold scaleShiftTree - rw [hclz, evmSub_small (by unfold scaleMaxClz; omega) (by norm_num)] - unfold scaleMaxClz - norm_num + rw [hclz, evmSub_small (by unfold scaleClzBias; omega) (by norm_num)] + norm_num [scaleClzBias, evmShr, evmAdd, u256, WORD_MOD] + +theorem scaleShiftTree_int128Max : scaleShiftTree int128Max = 0 := by + have hmax : int128Max ≠ 0 := by unfold int128Max; norm_num + have hloglo : 126 ≤ Nat.log2 int128Max := + (Nat.le_log2 hmax).2 (by unfold int128Max; norm_num) + have hloghi : Nat.log2 int128Max < 127 := + (Nat.log2_lt hmax).2 (by unfold int128Max; norm_num) + have hlog : Nat.log2 int128Max = 126 := by omega + rw [scaleShiftTree_pos (by unfold int128Max; norm_num) (by unfold int128Max; norm_num) + (by rw [int128Max_eq, kernelScaleMax_eq]; omega), hlog] -/-- The maximal supported magnitude has no normalization headroom. -/ -theorem scaleShiftTree_scaleMax : scaleShiftTree scaleMax = 0 := by - have hscaleMax : scaleMax ≠ 0 := by unfold scaleMax; norm_num - have hloglo : 126 ≤ Nat.log2 scaleMax := - (Nat.le_log2 hscaleMax).2 (by unfold scaleMax; norm_num) - have hloghi : Nat.log2 scaleMax < 127 := - (Nat.log2_lt hscaleMax).2 (by unfold scaleMax; norm_num) - have hlog : Nat.log2 scaleMax = 126 := by omega - rw [scaleShiftTree_pos (by unfold scaleMax; norm_num) (by unfold scaleMax; norm_num) - (le_refl _), hlog] +theorem scaleShiftTree_kernelScaleMax : scaleShiftTree kernelScaleMax = 0 := by + rw [scaleShiftTree_pos (by unfold kernelScaleMax; norm_num) + (by unfold kernelScaleMax; norm_num) (le_refl _), kernelScaleMax_eq] + have hloglo : 127 ≤ Nat.log2 (2 ^ 127) := + (Nat.le_log2 (by norm_num)).2 (by norm_num) + have hloghi : Nat.log2 (2 ^ 127) < 128 := + (Nat.log2_lt (by norm_num)).2 (by norm_num) + omega -/-- The headroom shift never exceeds 127 on supported magnitudes. -/ -theorem scaleShiftTree_le_127 {y : Nat} (habs : absTree y ≤ scaleMax) : +theorem scaleShiftTree_le_127 {y : Nat} (habs : absTree y ≤ kernelScaleMax) : scaleShiftTree (absTree y) ≤ 127 := by rcases Nat.eq_zero_or_pos (absTree y) with h0 | hpos · rw [h0, scaleShiftTree_zero] · rw [scaleShiftTree_pos (absTree_lt y) hpos habs] omega -/-- The derived headroom guard is exactly the 127-bit magnitude cap. -/ -theorem scaleShiftTree_le_127_iff {ay : Nat} (hay : ay < 2 ^ 256) : - scaleShiftTree ay ≤ 127 ↔ ay ≤ scaleMax := by - constructor - · intro hs - by_contra hcap - push_neg at hcap - have haylo : 2 ^ 127 ≤ ay := by - rw [scaleMax_eq] at hcap - omega - have hpos : 1 ≤ ay := by omega - have hloglo : 127 ≤ Nat.log2 ay := by - by_contra h - push_neg at h - have hlt := Nat.lt_log2_self (n := ay) - have hp : (2 : Nat) ^ (Nat.log2 ay + 1) ≤ 2 ^ 127 := - Nat.pow_le_pow_right (by norm_num) (by omega) - omega - have hloghi : Nat.log2 ay ≤ 255 := by - have hp := Nat.log2_self_le (by omega : ay ≠ 0) - by_contra h - push_neg at h - have hpow : (2 : Nat) ^ 256 ≤ 2 ^ Nat.log2 ay := - Nat.pow_le_pow_right (by norm_num) h - omega - have hclz : evmClz ay = 255 - Nat.log2 ay := by - unfold evmClz - rw [u256_self hay, if_neg (by omega)] - have hc : 255 - Nat.log2 ay < 129 := by omega - have hraw : 255 - Nat.log2 ay + 2 ^ 256 - 129 < 2 ^ 256 := by - omega - have hsub : scaleShiftTree ay = 255 - Nat.log2 ay + 2 ^ 256 - 129 := by - unfold scaleShiftTree - rw [hclz, evmSub_eq_mod_pow256 (by omega) (by unfold scaleMaxClz; norm_num)] - unfold scaleMaxClz - rw [Nat.mod_eq_of_lt hraw] - rw [hsub] at hs - omega - · intro hcap - rcases Nat.eq_zero_or_pos ay with h0 | hpos - · rw [h0, scaleShiftTree_zero] - · rw [scaleShiftTree_pos hay hpos hcap] - omega - -/-- Scale maximality: for a nonzero supported magnitude, one more doubling of the normalized -scale exceeds the 127-bit cap. -/ +/-- One more doubling of every nonzero normalized scale reaches the inclusive analytic cap. -/ theorem mulScaleTree_max {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) - (habs : absTree y ≤ scaleMax) : scaleMax < 2 * mulScaleTree y := by + (habs : absTree y ≤ kernelScaleMax) : kernelScaleMax ≤ 2 * mulScaleTree y := by obtain ⟨_, hscale, _⟩ := mulScaleTree_spec hy habs + by_cases hend : absTree y = kernelScaleMax + · rw [hscale, hend, scaleShiftTree_kernelScaleMax, kernelScaleMax_eq] + norm_num have hs := scaleShiftTree_pos (absTree_lt y) hpos habs have hloglo : 2 ^ Nat.log2 (absTree y) ≤ absTree y := Nat.log2_self_le (by omega) have hlog : Nat.log2 (absTree y) ≤ 126 := by - have hay127 : absTree y < 2 ^ 127 := - lt_of_le_of_lt habs scaleMax_lt_2127 + have hay127 : absTree y < 2 ^ 127 := by rw [← kernelScaleMax_eq]; omega by_contra h push_neg at h have h2 : (2 : Nat) ^ 127 ≤ 2 ^ Nat.log2 (absTree y) := @@ -165,15 +162,15 @@ theorem mulScaleTree_max {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) exact Nat.pow_le_pow_right (by norm_num) (by omega) _ ≤ absTree y * 2 ^ (126 - Nat.log2 (absTree y)) := Nat.mul_le_mul_right _ hloglo - rw [hscale, hs, scaleMax_eq] + rw [hscale, hs, kernelScaleMax_eq] omega /-- Every nonzero supported magnitude's normalized scale is at least 2^125. -/ theorem mulScaleTree_lower {y : Nat} (hy : y < 2 ^ 256) (hpos : 1 ≤ absTree y) - (habs : absTree y ≤ scaleMax) : 2 ^ 125 ≤ mulScaleTree y := by + (habs : absTree y ≤ kernelScaleMax) : 2 ^ 125 ≤ mulScaleTree y := by have hmax := mulScaleTree_max hy hpos habs - have hQ : (2 : Nat) ^ 126 ≤ scaleMax := by - unfold scaleMax + have hQ : (2 : Nat) ^ 126 ≤ kernelScaleMax := by + unfold kernelScaleMax norm_num omega /-! ## The closing-shift word -/ @@ -199,7 +196,7 @@ theorem kTree_global_bounds (x : Nat) : /-- The closing shift carries the signed difference globally on supported magnitudes. The octave word's signed 64-bit range leaves ample room for the headroom shift in `[0, 127]`, so the EVM subtraction cannot cross either signed boundary. -/ -theorem mulShiftTree_transport_global {y x : Nat} (habs : absTree y ≤ scaleMax) : +theorem mulShiftTree_transport_global {y x : Nat} (habs : absTree y ≤ kernelScaleMax) : int256 (mulShiftTree y x) = (scaleShiftTree (absTree y) : Int) - int256 (kTree x) := by have hs127 := scaleShiftTree_le_127 habs @@ -223,25 +220,64 @@ theorem mulShiftTree_transport_global {y x : Nat} (habs : absTree y ≤ scaleMax /-- At the magnitude cap, an exponent in octave `-2` has exactly the minimum accepted closing shift and lies in the value domain whenever it is below the unconditional upper fence. -/ -theorem scaleMax_octave_neg_two_valueDomain {x : Nat} (hx : x < 2 ^ 256) +theorem int128Max_octave_neg_two_valueDomain {x : Nat} (hx : x < 2 ^ 256) (hxhi : int256 x < int256 mulExpRayHi) (hk : int256 (kTree x) = -2) : - scaleShiftTree (absTree scaleMax) = 0 ∧ - int256 (mulShiftTree scaleMax x) = 2 ∧ - MulExpRayValueDomain scaleMax x := by - have hy : scaleMax < 2 ^ 256 := by unfold scaleMax; norm_num - have habs : absTree scaleMax = scaleMax := - absTree_nonneg (by unfold scaleMax; norm_num) - have hcap : absTree scaleMax ≤ scaleMax := by rw [habs] - have hs : scaleShiftTree (absTree scaleMax) = 0 := by rw [habs, scaleShiftTree_scaleMax] - have hshift : int256 (mulShiftTree scaleMax x) = 2 := by + scaleShiftTree (absTree int128Max) = 0 ∧ + int256 (mulShiftTree int128Max x) = 2 ∧ + MulExpRayValueDomain int128Max x := by + have hy : int128Max < 2 ^ 256 := by unfold int128Max; norm_num + have habs : absTree int128Max = int128Max := + absTree_nonneg (by unfold int128Max; norm_num) + have hcap : absTree int128Max ≤ kernelScaleMax := by + rw [habs, int128Max_eq, kernelScaleMax_eq] + omega + have hs : scaleShiftTree (absTree int128Max) = 0 := by rw [habs, scaleShiftTree_int128Max] + have hshift : int256 (mulShiftTree int128Max x) = 2 := by rw [mulShiftTree_transport_global hcap, hs, hk] norm_num exact ⟨hs, hshift, - ⟨⟨int128Word_scaleMax, hx⟩, by rw [hs]; norm_num, hxhi, by omega⟩⟩ + ⟨⟨int128Word_max, hx⟩, hxhi, by omega⟩⟩ + +theorem int128Min_octave_neg_two_valueDomain {x : Nat} (hx : x < 2 ^ 256) + (hxhi : int256 x < int256 mulExpRayHi) (hk : int256 (kTree x) = -2) : + scaleShiftTree (absTree (2 ^ 256 - 2 ^ 127)) = 0 ∧ + int256 (mulShiftTree (2 ^ 256 - 2 ^ 127) x) = 2 ∧ + MulExpRayValueDomain (2 ^ 256 - 2 ^ 127) x := by + have hy : 2 ^ 256 - 2 ^ 127 < 2 ^ 256 := by norm_num + have habs : absTree (2 ^ 256 - 2 ^ 127) = kernelScaleMax := by + rw [absTree_neg (by norm_num) hy, kernelScaleMax_eq] + omega + have hcap : absTree (2 ^ 256 - 2 ^ 127) ≤ kernelScaleMax := by rw [habs] + have hs : scaleShiftTree (absTree (2 ^ 256 - 2 ^ 127)) = 0 := by + rw [habs, scaleShiftTree_kernelScaleMax] + have hshift : int256 (mulShiftTree (2 ^ 256 - 2 ^ 127) x) = 2 := by + rw [mulShiftTree_transport_global hcap, hs, hk] + norm_num + exact ⟨hs, hshift, ⟨⟨int128Word_min, hx⟩, hxhi, by omega⟩⟩ + +theorem int128Min_valueDomain_iff {x : Nat} (hx : x < 2 ^ 256) : + MulExpRayValueDomain (2 ^ 256 - 2 ^ 127) x ↔ + int256 x < int256 mulExpRayHi ∧ int256 (kTree x) ≤ -2 := by + have hy : 2 ^ 256 - 2 ^ 127 < 2 ^ 256 := by norm_num + have habs : absTree (2 ^ 256 - 2 ^ 127) = kernelScaleMax := by + rw [absTree_neg (by norm_num) hy, kernelScaleMax_eq] + omega + have hcap : absTree (2 ^ 256 - 2 ^ 127) ≤ kernelScaleMax := by rw [habs] + have hshift : int256 (mulShiftTree (2 ^ 256 - 2 ^ 127) x) = -int256 (kTree x) := by + rw [mulShiftTree_transport_global hcap, habs, scaleShiftTree_kernelScaleMax] + ring + constructor + · rintro ⟨_, hxhi, hlive⟩ + rw [hshift] at hlive + omega + · rintro ⟨hxhi, hk⟩ + refine ⟨⟨int128Word_min, hx⟩, hxhi, ?_⟩ + rw [hshift] + omega /-- The closing-shift word carries the signed difference `S − k` on the wide region. -/ theorem mulShiftTree_transport {y x : Nat} (_hy : y < 2 ^ 256) (_hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (_hW : WideRegion x) : + (habs : absTree y ≤ kernelScaleMax) (_hW : WideRegion x) : int256 (mulShiftTree y x) = (scaleShiftTree (absTree y) : Int) - int256 (kTree x) := mulShiftTree_transport_global habs @@ -249,7 +285,7 @@ theorem mulShiftTree_transport {y x : Nat} (_hy : y < 2 ^ 256) (_hx : x < 2 ^ 25 /-- On the live region the closing-shift word is a plain small `Nat` in `[2, 254]`, equal to `S − k` on the signed side. -/ theorem mulShift_word_facts {y x : Nat} (hy : y < 2 ^ 256) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (hW : WideRegion x) + (habs : absTree y ≤ kernelScaleMax) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : 2 ≤ mulShiftTree y x ∧ mulShiftTree y x < 256 ∧ (mulShiftTree y x : Int) = int256 (mulShiftTree y x) := by diff --git a/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean b/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean index 0940a4a86..c10bbed67 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/WordBridge.lean @@ -204,4 +204,48 @@ theorem signextend_15_eq_self_of_int256_range {w : Nat} (hw : w < 2 ^ 256) exact_mod_cast hwloInt refine ⟨2 ^ 256 - w, by omega, by omega, by omega⟩ +theorem int256_range_of_signextend_15_eq_self {w : Nat} (hw : w < 2 ^ 256) + (hclean : EvmYul.UInt256.signextend (word 15) (word w) = word w) : + -(2 ^ 127 : Int) ≤ int256 w ∧ int256 w < 2 ^ 127 := by + by_cases hsign : word w &&& word (2 ^ 127) ≠ word 0 + · rw [signextend_15_eq_ite, if_pos hsign] at hclean + rw [word_or] at hclean + have hnat := congrArg wordNat hclean + simp only [wordNat_word] at hnat + have hmask : 2 ^ 256 - 2 ^ 127 < 2 ^ 256 := by norm_num + rw [u256_of_lt_pow256 (evmOr_lt_WORD_MOD _ _), u256_of_lt_pow256 hw] at hnat + unfold evmOr at hnat + rw [u256_of_lt_pow256 hw, u256_of_lt_pow256 hmask] at hnat + have hlo : 2 ^ 256 - 2 ^ 127 ≤ w := by + rw [← hnat] + exact Nat.right_le_or + have hneg : ¬w < 2 ^ 255 := by omega + unfold int256 + rw [if_neg hneg] + have hwI : (w : Int) < 2 ^ 256 := by exact_mod_cast hw + have hbaseCast : ((2 ^ 256 - 2 ^ 127 : Nat) : Int) = + (2 ^ 256 : Int) - 2 ^ 127 := by norm_num + have hloI : (2 ^ 256 : Int) - 2 ^ 127 ≤ (w : Int) := by + rw [← hbaseCast] + exact_mod_cast hlo + omega + · rw [signextend_15_eq_ite, if_neg hsign] at hclean + rw [word_and] at hclean + have hnat := congrArg wordNat hclean + simp only [wordNat_word] at hnat + have hmask : 2 ^ 127 - 1 < 2 ^ 256 := by norm_num + rw [u256_of_lt_pow256 (evmAnd_lt_WORD_MOD _ _), u256_of_lt_pow256 hw] at hnat + unfold evmAnd at hnat + rw [u256_of_lt_pow256 hw, u256_of_lt_pow256 hmask] at hnat + have hhi : w < 2 ^ 127 := by + have : w ≤ 2 ^ 127 - 1 := by + rw [← hnat] + exact Nat.and_le_right + omega + have hpos : w < 2 ^ 255 := lt_trans hhi (by norm_num) + rw [int256_of_lt hpos] + constructor + · exact le_trans (by norm_num) (Int.natCast_nonneg w) + · exact_mod_cast hhi + end ExpYul diff --git a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean index 3bd256fdc..846431602 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/XMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/XMono.lean @@ -51,7 +51,7 @@ private theorem mulShift_word_eq {y x1 x2 : Nat} /-- The signed shift is antitone in the exponent (the octave index is monotone). -/ theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) + (habs : absTree y ≤ kernelScaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hle : int256 x1 ≤ int256 x2) : int256 (mulShiftTree y x2) ≤ int256 (mulShiftTree y x1) := by rw [mulShiftTree_transport hy hx1 habs hW1, mulShiftTree_transport hy hx2 habs hW2] @@ -60,7 +60,7 @@ theorem mulShift_antitone {y x1 x2 : Nat} (hy : y < 2 ^ 256) /-- The decremented quotient word: transport and range at the dynamic scale. -/ theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) (hW : WideRegion x) : + (hx : x < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hW : WideRegion x) : int256 (evmSub (r0MulTree y x) marginWord) = int256 (r0MulTree y x) - 1 ∧ 0 ≤ int256 (r0MulTree y x) - 1 ∧ int256 (r0MulTree y x) - 1 < 2 ^ 129 := by have hpos : 1 ≤ absTree y := absTree_pos hy hy0 @@ -91,7 +91,7 @@ theorem mulShiftArg_facts {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- Adjacent same-octave quotient monotonicity at the dynamic scale. -/ theorem r0Mul_mono_adjacent {y x1 x2 : Nat} (hy : y < 2 ^ 256) - (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hk : int256 (kTree x1) = int256 (kTree x2)) (hadj : int256 x2 = int256 x1 + 1) : @@ -122,7 +122,7 @@ theorem r0Mul_mono_adjacent {y x1 x2 : Nat} (hy : y < 2 ^ 256) /-- **The live unit step**: for adjacent live exponents the kernel magnitude is nondecreasing. -/ theorem mulMagnitude_step {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hx10 : int256 x1 ≠ 0) (hx20 : int256 x2 ≠ 0) (hlive1 : 2 ≤ int256 (mulShiftTree y x1)) (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) @@ -201,7 +201,7 @@ theorem mulMagnitude_step {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) (the endpoint's live shift bounds every intermediate through octave monotonicity, and the sign condition keeps the scale point outside the range). -/ theorem mulMagnitude_mono_steps {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleMax) (n : Nat) : + (habs : absTree y ≤ kernelScaleMax) (n : Nat) : ∀ x1 : Nat, x1 < 2 ^ 256 → int256 mulExpRayZeroMax < int256 x1 → int256 x1 + n < int256 mulExpRayHi → @@ -300,7 +300,7 @@ theorem mulMagnitude_mono_steps {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- **Region monotonicity of the live magnitude**: for live exponents `x1 ≤ x2` on a common sign side, the kernel magnitude is nondecreasing. -/ theorem mulMagnitude_region_mono {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleMax) + (habs : absTree y ≤ kernelScaleMax) (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hle : int256 x1 ≤ int256 x2) @@ -355,18 +355,18 @@ private theorem kTree_one : int256 (kTree 1) = 0 := by /-- The magnitude at the scale point is the multiplier's magnitude. -/ theorem int256_mulMagnitude_zero {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleMax) : + (habs : absTree y ≤ kernelScaleMax) : int256 (mulMagnitudeTree y 0) = (absTree y : Int) := by have hpos : 0 < absTree y := absTree_pos hy hy0 rw [mulMagnitudeTree_scale_point hy hpos habs] - exact int256_of_lt (lt_of_le_of_lt habs (lt_trans scaleMax_lt_2127 (by norm_num))) + exact int256_of_lt (lt_of_le_of_lt habs (by unfold kernelScaleMax; norm_num)) /-- **The analytic pin step.** At `x = 1` the live magnitude is at least the multiplier's magnitude: one exponent unit is worth `scale/10²⁷ ≥ 2⁹⁸` quotient units, far above the deficit envelope, so the decremented quotient still clears `scale` and its closing shift clears `abs(y)`. -/ theorem mulMagnitude_pin_step {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (habs : absTree y ≤ scaleMax) + (habs : absTree y ≤ kernelScaleMax) (hlive1 : 2 ≤ int256 (mulShiftTree y 1)) : (absTree y : Int) ≤ int256 (mulMagnitudeTree y 1) := by have hx1 : (1 : Nat) < 2 ^ 256 := by norm_num @@ -465,7 +465,7 @@ theorem mulMagnitude_pin_step {y : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- A negative live exponent's magnitude never exceeds the multiplier's magnitude: its real target is already below it. -/ theorem mulMagnitude_le_abs_of_neg {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hx : x < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hW : WideRegion x) (hxneg : int256 x < 0) (hlive : 2 ≤ int256 (mulShiftTree y x)) : int256 (mulMagnitudeTree y x) ≤ (absTree y : Int) := by @@ -547,7 +547,7 @@ theorem int256_tree_neg {y x : Nat} (hlo : 2 ^ 255 ≤ y) (hy : y < 2 ^ 256) /-- The live magnitude word stays below `2^255`. -/ theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hx : x < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hx0 : int256 x ≠ 0) (hW : WideRegion x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : mulMagnitudeTree y x < 2 ^ 255 := by @@ -563,7 +563,7 @@ theorem mag_word_small {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) /-- A positive live exponent's magnitude is at least the multiplier's magnitude (through the analytic pin step at `x = 1`). -/ theorem mulMagnitude_ge_abs_of_pos {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx : x < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hx : x < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hW : WideRegion x) (hxpos : 0 < int256 x) (hlive : 2 ≤ int256 (mulShiftTree y x)) : (absTree y : Int) ≤ int256 (mulMagnitudeTree y x) := by @@ -589,7 +589,7 @@ theorem mulMagnitude_ge_abs_of_pos {y x : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0 /-- **Magnitude monotonicity over the live region**, both sign sides, through the scale point. -/ theorem mulMagnitude_mono_pair {y x1 x2 : Nat} (hy : y < 2 ^ 256) (hy0 : y ≠ 0) - (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ scaleMax) + (hx1 : x1 < 2 ^ 256) (hx2 : x2 < 2 ^ 256) (habs : absTree y ≤ kernelScaleMax) (hW1 : WideRegion x1) (hW2 : WideRegion x2) (hx10 : int256 x1 ≠ 0) (hx20 : int256 x2 ≠ 0) (hlive1 : 2 ≤ int256 (mulShiftTree y x1)) (hlive2 : 2 ≤ int256 (mulShiftTree y x2)) @@ -619,8 +619,8 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} run_mul_exp_ray_evm_eq_tree h1 have hrun2 : run_mul_exp_ray_evm y x2 = .ok (mulExpTree y x2) := run_mul_exp_ray_evm_eq_tree h2 - obtain ⟨⟨hy, hx1w⟩, hscale1, hxhi1, hshift1⟩ := h1 - obtain ⟨⟨_, hx2w⟩, _, hxhi2, hshift2⟩ := h2 + obtain ⟨⟨hy, hx1w⟩, hxhi1, hshift1⟩ := h1 + obtain ⟨⟨_, hx2w⟩, hxhi2, hshift2⟩ := h2 refine ⟨mulExpTree y x1, mulExpTree y x2, hrun1, hrun2, hle, ?_⟩ rcases Nat.eq_zero_or_pos y with hy0 | hypos · subst hy0 @@ -628,8 +628,7 @@ theorem run_mul_exp_ray_evm_mono_x {y x1 x2 : Nat} split <;> exact le_refl 0 have hy0 : y ≠ 0 := Nat.pos_iff_ne_zero.mp hypos -- the signed magnitude of each accepted result - have habs : absTree y ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y)).mp hscale1 + have habs : absTree y ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy -- classify each exponent: clamp, scale point, or live have hclass : ∀ x : Nat, x < 2 ^ 256 → 2 ≤ int256 (mulShiftTree y x) → int256 x ≤ int256 mulExpRayZeroMax ∨ x = 0 ∨ diff --git a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean index 7acccdd12..1eb098603 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/YMono.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/YMono.lean @@ -28,93 +28,51 @@ set_option maxHeartbeats 1600000 /-! ## Magnitude words normalize through the absolute value -/ /-- A supported magnitude word is its own absolute value. -/ -private theorem absTree_of_small {a : Nat} (ha : a ≤ scaleMax) : absTree a = a := - absTree_nonneg (lt_of_le_of_lt ha (by unfold scaleMax; norm_num)) +private theorem absTree_of_small {a : Nat} (ha : a ≤ kernelScaleMax) : absTree a = a := + absTree_nonneg (lt_of_le_of_lt ha (by unfold kernelScaleMax; norm_num)) /-- The kernel magnitude depends on the multiplier only through its magnitude word. -/ -theorem mulMagnitude_abs_norm {y : Nat} (habs : absTree y ≤ scaleMax) (x : Nat) : +theorem mulMagnitude_abs_norm {y : Nat} (habs : absTree y ≤ kernelScaleMax) (x : Nat) : mulMagnitudeTree y x = mulMagnitudeTree (absTree y) x := by have h : absTree (absTree y) = absTree y := absTree_of_small habs unfold mulMagnitudeTree mulShiftTree r0MulTree mulScaleTree rw [h] /-- The closing shift depends on the multiplier only through its magnitude word. -/ -theorem mulShift_abs_norm {y : Nat} (habs : absTree y ≤ scaleMax) (x : Nat) : +theorem mulShift_abs_norm {y : Nat} (habs : absTree y ≤ kernelScaleMax) (x : Nat) : mulShiftTree y x = mulShiftTree (absTree y) x := by have h : absTree (absTree y) = absTree y := absTree_of_small habs unfold mulShiftTree rw [h] -/-! ## Headroom arithmetic from scale maximality -/ +/-! ## Headroom arithmetic -/ /-- The headroom shift is antitone in the magnitude. -/ -theorem scaleShift_antitone {a b : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleMax) : +theorem scaleShift_antitone {a b : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ kernelScaleMax) : scaleShiftTree b ≤ scaleShiftTree a := by - have haQ : a ≤ scaleMax := le_trans hab hb - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) - have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleMax; norm_num) - have haa : absTree a = a := absTree_of_small haQ - have hba : absTree b = b := absTree_of_small hb - have hmax := mulScaleTree_max (y := a) haw (by rw [haa]; exact ha) (by rw [haa]; exact haQ) - obtain ⟨_, hspec_a, _⟩ := mulScaleTree_spec (y := a) haw (by rw [haa]; exact haQ) - obtain ⟨_, hspec_b, hcap_b⟩ := mulScaleTree_spec (y := b) hbw (by rw [hba]; exact hb) - rw [hspec_a, haa] at hmax - rw [hspec_b, hba] at hcap_b - rw [haa] at hspec_a - rw [hba] at hspec_b - -- b·2^Sb ≤ Q < 2·a·2^Sa ≤ 2·b·2^Sa, so 2^Sb < 2^(Sa+1) - by_contra hcon - push_neg at hcon - have h1 : b * 2 ^ scaleShiftTree b < 2 * (a * 2 ^ scaleShiftTree a) := - lt_of_le_of_lt hcap_b hmax - have h2 : 2 * (a * 2 ^ scaleShiftTree a) ≤ 2 * (b * 2 ^ scaleShiftTree a) := by - have := Nat.mul_le_mul_right (2 ^ scaleShiftTree a) hab - omega - have h3 : b * 2 ^ scaleShiftTree b < b * 2 ^ (scaleShiftTree a + 1) := by - have h4 : 2 * (b * 2 ^ scaleShiftTree a) = b * 2 ^ (scaleShiftTree a + 1) := by - rw [pow_succ] - ring - omega - have h5 : 2 ^ scaleShiftTree b < 2 ^ (scaleShiftTree a + 1) := - lt_of_mul_lt_mul_left h3 (Nat.zero_le b) - have h6 : scaleShiftTree b < scaleShiftTree a + 1 := - (Nat.pow_lt_pow_iff_right (by norm_num)).mp h5 + have haQ : a ≤ kernelScaleMax := le_trans hab hb + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold kernelScaleMax; norm_num) + have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold kernelScaleMax; norm_num) + have hbpos : 1 ≤ b := le_trans ha hab + have hlog : Nat.log2 a ≤ Nat.log2 b := by + rw [Nat.log2_eq_log_two, Nat.log2_eq_log_two] + exact Nat.log_mono_right hab + rw [scaleShiftTree_pos hbw hbpos hb, scaleShiftTree_pos haw ha haQ] omega /-- A unit magnitude step drops the headroom shift by at most one. -/ -theorem scaleShift_step {a : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleMax) : +theorem scaleShift_step {a : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ kernelScaleMax) : scaleShiftTree a ≤ scaleShiftTree (a + 1) + 1 := by - have haQ : a ≤ scaleMax := le_trans (Nat.le_succ a) ha1 - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) - have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleMax; norm_num) - have haa : absTree a = a := absTree_of_small haQ - have ha1a : absTree (a + 1) = a + 1 := absTree_of_small ha1 - obtain ⟨_, hspec_a, hcap_a⟩ := mulScaleTree_spec (y := a) haw (by rw [haa]; exact haQ) - have hmax1 := mulScaleTree_max (y := a + 1) ha1w (by rw [ha1a]; omega) - (by rw [ha1a]; exact ha1) - obtain ⟨_, hspec_a1, _⟩ := mulScaleTree_spec (y := a + 1) ha1w (by rw [ha1a]; exact ha1) - rw [hspec_a, haa] at hcap_a - rw [hspec_a1, ha1a] at hmax1 - -- a·2^Sa ≤ Q < 2·(a+1)·2^S(a+1): if Sa ≥ S(a+1)+2, then 2a < a+1, impossible for a ≥ 1 - by_contra hcon - push_neg at hcon - have h1 : a * 2 ^ scaleShiftTree a < 2 * ((a + 1) * 2 ^ scaleShiftTree (a + 1)) := - lt_of_le_of_lt hcap_a hmax1 - have h2 : (2:Nat) ^ (scaleShiftTree (a + 1) + 2) ≤ 2 ^ scaleShiftTree a := - Nat.pow_le_pow_right (by norm_num) hcon - have h3 : a * 2 ^ (scaleShiftTree (a + 1) + 2) ≤ a * 2 ^ scaleShiftTree a := - Nat.mul_le_mul_left a h2 - have h4 : a * 2 ^ (scaleShiftTree (a + 1) + 2) = - (2 * a) * (2 * 2 ^ scaleShiftTree (a + 1)) := by - rw [pow_succ, pow_succ] - ring - have h5 : 2 * ((a + 1) * 2 ^ scaleShiftTree (a + 1)) = - (a + 1) * (2 * 2 ^ scaleShiftTree (a + 1)) := by ring - have hppos : 0 < 2 * 2 ^ scaleShiftTree (a + 1) := by positivity - have h6 : 2 * a < a + 1 := by - have h7 : (2 * a) * (2 * 2 ^ scaleShiftTree (a + 1)) < - (a + 1) * (2 * 2 ^ scaleShiftTree (a + 1)) := by omega - exact lt_of_mul_lt_mul_right h7 (Nat.zero_le _) + have haQ : a ≤ kernelScaleMax := le_trans (Nat.le_succ a) ha1 + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold kernelScaleMax; norm_num) + have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold kernelScaleMax; norm_num) + have hlog : Nat.log2 (a + 1) ≤ Nat.log2 a + 1 := by + rw [Nat.log2_eq_log_two, Nat.log2_eq_log_two] + calc + Nat.log 2 (a + 1) ≤ Nat.log 2 (a * 2) := Nat.log_mono_right (by omega) + _ = Nat.log 2 a + 1 := Nat.log_mul_base (by norm_num) (by omega) + rw [scaleShiftTree_pos haw ha haQ, + scaleShiftTree_pos ha1w (by omega) ha1] omega /-! ## Quotient comparisons at a fixed exponent -/ @@ -136,7 +94,7 @@ theorem num_den_ratio {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : linarith [hev, htod_lo, htod_hi] /-- The scaled quotient is monotone in the scale at a fixed exponent. -/ -theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 ≤ scaleMax) +theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (r0ScaledTree sc1 x) ≤ int256 (r0ScaledTree sc2 x) := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW @@ -175,17 +133,12 @@ theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 rw [hp126] linarith [hev, htod_hi] exact_mod_cast h - have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt (le_trans h12 hshi2) (by unfold scaleMax; norm_num) - have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleMax; norm_num) - have hfit1 : sc1 * num < 2 ^ 256 := by - have h1 : sc1 * num ≤ scaleMax * 2 ^ 129 := - Nat.mul_le_mul (le_trans h12 hshi2) (le_of_lt hnumnat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega - have hfit2 : sc2 * num < 2 ^ 256 := by - have h1 : sc2 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega + have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt (le_trans h12 hshi2) (by unfold kernelScaleMax; norm_num) + have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold kernelScaleMax; norm_num) + have hfit1 : sc1 * num < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax (le_trans h12 hshi2) hnumnat + have hfit2 : sc2 * num < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi2 hnumnat have hq1 : r0ScaledTree sc1 x = sc1 * num / den := by show evmDiv (evmMul sc1 num) den = _ rw [evmMul_eq_nat hsw1 hnumw hfit1, evmDiv_eq hfit1 hdenw (Nat.pos_iff_ne_zero.mp hdennat)] @@ -212,7 +165,7 @@ theorem r0Scaled_mono_scale {sc1 sc2 x : Nat} (h12 : sc1 ≤ sc2) (hshi2 : sc2 `2·sc2 = sc1 + 2^S` with `S ≥ 1` gives `r0(sc1) ≤ 2·r0(sc2)` (`2·num > den` pays the floor loss). -/ theorem r0Scaled_double_scale {sc1 sc2 S x : Nat} (hS : 1 ≤ S) - (hid : 2 * sc2 = sc1 + 2 ^ S) (hshi1 : sc1 ≤ scaleMax) (hshi2 : sc2 ≤ scaleMax) + (hid : 2 * sc2 = sc1 + 2 ^ S) (hshi1 : sc1 ≤ kernelScaleMax) (hshi2 : sc2 ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (r0ScaledTree sc1 x) ≤ 2 * int256 (r0ScaledTree sc2 x) := by obtain ⟨hadd, hsub, hnum_pos, hden_pos⟩ := numden_pos_wide hx hW @@ -258,16 +211,12 @@ theorem r0Scaled_double_scale {sc1 sc2 S x : Nat} (hS : 1 ≤ S) rw [← hdeneq, ← hnumeq, hadd, hsub] exact hratio exact_mod_cast h1 - have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt hshi1 (by unfold scaleMax; norm_num) - have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold scaleMax; norm_num) - have hfit1 : sc1 * num < 2 ^ 256 := by - have h1 : sc1 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi1 (le_of_lt hnumnat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega - have hfit2 : sc2 * num < 2 ^ 256 := by - have h1 : sc2 * num ≤ scaleMax * 2 ^ 129 := Nat.mul_le_mul hshi2 (le_of_lt hnumnat) - have h2 : scaleMax * 2 ^ 129 < 2 ^ 256 := by unfold scaleMax; norm_num - omega + have hsw1 : sc1 < 2 ^ 256 := lt_of_le_of_lt hshi1 (by unfold kernelScaleMax; norm_num) + have hsw2 : sc2 < 2 ^ 256 := lt_of_le_of_lt hshi2 (by unfold kernelScaleMax; norm_num) + have hfit1 : sc1 * num < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi1 hnumnat + have hfit2 : sc2 * num < 2 ^ 256 := + mul_lt_2256_of_scale_le_kernelScaleMax hshi2 hnumnat have hq1 : r0ScaledTree sc1 x = sc1 * num / den := by show evmDiv (evmMul sc1 num) den = _ rw [evmMul_eq_nat hsw1 hnumw hfit1, evmDiv_eq hfit1 hdenw (Nat.pos_iff_ne_zero.mp hdennat)] @@ -375,12 +324,12 @@ theorem seam_close_odd {arg1 arg2 s1 s2 : Nat} /-! ## The adjacent magnitude step -/ /-- The signed closing shift is antitone in the magnitude word. -/ -theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ scaleMax) +theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) : int256 (mulShiftTree b x) ≤ int256 (mulShiftTree a x) := by - have haQ : a ≤ scaleMax := le_trans hab hb - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) - have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold scaleMax; norm_num) + have haQ : a ≤ kernelScaleMax := le_trans hab hb + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold kernelScaleMax; norm_num) + have hbw : b < 2 ^ 256 := lt_of_le_of_lt hb (by unfold kernelScaleMax; norm_num) have haa : absTree a = a := absTree_of_small haQ have hba : absTree b = b := absTree_of_small hb have hta := mulShiftTree_transport (y := a) haw hx (by rw [haa]; exact haQ) hW @@ -394,13 +343,13 @@ theorem mulShiftY_antitone {a b x : Nat} (ha : 1 ≤ a) (hab : a ≤ b) (hb : b /-- **The adjacent magnitude step**: at a fixed live exponent, one unit of magnitude never decreases the kernel magnitude. -/ -theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleMax) +theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) (hlive2 : 2 ≤ int256 (mulShiftTree (a + 1) x)) : int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + 1) x) := by - have haQ : a ≤ scaleMax := le_trans (Nat.le_succ a) ha1 - have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold scaleMax; norm_num) - have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold scaleMax; norm_num) + have haQ : a ≤ kernelScaleMax := le_trans (Nat.le_succ a) ha1 + have haw : a < 2 ^ 256 := lt_of_le_of_lt haQ (by unfold kernelScaleMax; norm_num) + have ha1w : a + 1 < 2 ^ 256 := lt_of_le_of_lt ha1 (by unfold kernelScaleMax; norm_num) have haa : absTree a = a := absTree_of_small haQ have ha1a : absTree (a + 1) = a + 1 := absTree_of_small ha1 have hlive1 : 2 ≤ int256 (mulShiftTree a x) := @@ -506,7 +455,7 @@ theorem mulMagnitudeY_step {a x : Nat} (ha : 1 ≤ a) (ha1 : a + 1 ≤ scaleMax) intermediate through the headroom antitonicity. -/ theorem mulMagnitudeY_mono_steps {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) (n : Nat) : - ∀ a : Nat, 1 ≤ a → a + n ≤ scaleMax → + ∀ a : Nat, 1 ≤ a → a + n ≤ kernelScaleMax → 2 ≤ int256 (mulShiftTree (a + n) x) → int256 (mulMagnitudeTree a x) ≤ int256 (mulMagnitudeTree (a + n) x) := by induction n with @@ -533,7 +482,7 @@ theorem mulMagnitudeY_mono_steps {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x /-- **Magnitude monotonicity in the multiplier at a fixed live exponent.** -/ theorem mulMagnitudeY_region_mono {a1 a2 x : Nat} (ha1 : 1 ≤ a1) (h12 : a1 ≤ a2) - (ha2 : a2 ≤ scaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) + (ha2 : a2 ≤ kernelScaleMax) (hx : x < 2 ^ 256) (hW : WideRegion x) (hx0 : int256 x ≠ 0) (hlive2 : 2 ≤ int256 (mulShiftTree a2 x)) : int256 (mulMagnitudeTree a1 x) ≤ int256 (mulMagnitudeTree a2 x) := by have h := mulMagnitudeY_mono_steps hx hW hx0 (a2 - a1) a1 ha1 @@ -553,12 +502,10 @@ theorem run_mul_exp_ray_evm_mono_y {y1 y2 x : Nat} run_mul_exp_ray_evm_eq_tree h1 have hrun2 : run_mul_exp_ray_evm y2 x = .ok (mulExpTree y2 x) := run_mul_exp_ray_evm_eq_tree h2 - obtain ⟨⟨hy1, hxw⟩, hscale1, hxhi, hshift1⟩ := h1 - obtain ⟨⟨hy2, _⟩, hscale2, _, hshift2⟩ := h2 - have habs1 : absTree y1 ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y1)).mp hscale1 - have habs2 : absTree y2 ≤ scaleMax := - (scaleShiftTree_le_127_iff (absTree_lt y2)).mp hscale2 + obtain ⟨⟨hy1, hxw⟩, hxhi, hshift1⟩ := h1 + obtain ⟨⟨hy2, _⟩, _, hshift2⟩ := h2 + have habs1 : absTree y1 ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy1 + have habs2 : absTree y2 ≤ kernelScaleMax := absTree_le_kernelScaleMax_of_int128Word hy2 refine ⟨mulExpTree y1 x, mulExpTree y2 x, hrun1, hrun2, hle, ?_⟩ -- the exponent's class decides the result shape by_cases hcl : int256 x ≤ int256 mulExpRayZeroMax diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index f0356768b..849c54c7b 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -797,6 +797,28 @@ theorem call_cleanup_t_uint8_17_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +theorem call_cleanup_t_uint8_127_direct + (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + 20) [FormalYul.word 0x7f] (.some "cleanup_t_uint8") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x7f]) := by + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_cleanup_t_uint8] + simp only [yulFunction_cleanup_t_uint8, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + /-- `convert_t_rational_17_by_1_to_t_uint8(0x11) = 0x11` (= `cleanup_t_uint8(identity(cleanup_…(0x11)))`). -/ theorem call_convert_17_to_uint8_17_direct (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -1138,19 +1160,19 @@ theorem call_convert_1_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_convert_127_to_uint256_direct +theorem call_convert_127_to_uint8_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0x7f] - (.some "convert_t_rational_127_by_1_to_t_uint256") + (.some "convert_t_rational_127_by_1_to_t_uint8") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x7f]) := by rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_convert_t_rational_127_by_1_to_t_uint256] - simp only [yulFunction_convert_t_rational_127_by_1_to_t_uint256, + lookup_convert_t_rational_127_by_1_to_t_uint8] + simp only [yulFunction_convert_t_rational_127_by_1_to_t_uint8, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1165,8 +1187,7 @@ theorem call_convert_127_to_uint256_direct (store := Finmap.insert "value" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h3 := - call_cleanup_t_uint256_direct (v := 0x7f) (fuel := fuel + extra) (extra := 96) - (shared := shared) + call_cleanup_t_uint8_127_direct (fuel := fuel + extra + 96) (shared := shared) (store := Finmap.insert "value" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) simp [FormalYul.word] at h1 h2 h3 @@ -1368,17 +1389,17 @@ theorem call_constant__MUL_EXP_RAY_ZERO_MAX_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, mulExpRayZeroMax, hconv] -theorem call_constant__SCALE_MAX_CLZ_direct +theorem call_constant__SCALE_CLZ_BIAS_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__SCALE_MAX_CLZ) + EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__SCALE_CLZ_BIAS) (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word scaleMaxClz]) := by + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word scaleClzBias]) := by rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_MAX_CLZ] - simp only [yulFunctionBody_constant__SCALE_MAX_CLZ, + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_CLZ_BIAS] + simp only [yulFunctionBody_constant__SCALE_CLZ_BIAS, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1386,17 +1407,17 @@ theorem call_constant__SCALE_MAX_CLZ_direct have hconv := call_convert_129_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) (shared := shared) - (store := Finmap.insert "expr_125" (FormalYul.word scaleMaxClz) + (store := Finmap.insert "expr_125" (FormalYul.word scaleClzBias) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) - simp [FormalYul.word, scaleMaxClz] at hconv + simp [FormalYul.word, scaleClzBias] at hconv simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, scaleMaxClz, hconv] + Finmap.lookup_insert, FormalYul.word, scaleClzBias, hconv] theorem call_wrapping_sub_t_uint256_direct (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -1431,6 +1452,39 @@ theorem call_wrapping_sub_t_uint256_direct Finmap.lookup_insert, FormalYul.word, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, hcleanup] +theorem call_wrapping_add_t_uint256_direct + (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word x, FormalYul.word y] + (.some "wrapping_add_t_uint256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmAdd x y)]) := by + rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_wrapping_add_t_uint256] + simp only [yulFunction_wrapping_add_t_uint256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hcleanup := + call_cleanup_t_uint256_direct (v := evmAdd x y) (fuel := fuel + extra) (extra := 56) + (shared := shared) + (store := Finmap.insert "x" (FormalYul.word x) + (Finmap.insert "y" (FormalYul.word y) (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := hlookup) + simp [FormalYul.word] at hcleanup + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_add_eq_word_evmAdd, hcleanup] + theorem call_fun_clz_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -1483,6 +1537,85 @@ theorem call_shift_left_dynamic_direct Finmap.lookup_insert, FormalYul.word, FormalYul.Preservation.uint256_ofNat_shiftLeft_eq_word_evmShl] +theorem call_shift_right_unsigned_dynamic_direct + (bits value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 40)) [FormalYul.word bits, FormalYul.word value] + (.some "shift_right_unsigned_dynamic") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmShr bits value)]) := by + rw [show fuel + (extra + 40) = (fuel + extra) + 40 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_shift_right_unsigned_dynamic] + simp only [yulFunction_shift_right_unsigned_dynamic, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + FormalYul.Preservation.uint256_ofNat_shiftRight_eq_word_evmShr] + +theorem call_shift_right_t_uint256_t_uint8_127_direct + (value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 180)) [FormalYul.word value, FormalYul.word 0x7f] + (.some "shift_right_t_uint256_t_uint8") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmShr 0x7f value)]) := by + rw [show fuel + (extra + 180) = (fuel + extra) + 180 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_shift_right_t_uint256_t_uint8] + simp only [yulFunction_shift_right_t_uint256_t_uint8, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hbits := + call_cleanup_t_uint8_127_direct (fuel := fuel + extra + 156) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := hlookup) + have hvalue := + call_cleanup_t_uint256_direct (v := value) (fuel := fuel + extra) (extra := 151) + (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word 0x7f) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + have hshift := + call_shift_right_unsigned_dynamic_direct (bits := 0x7f) (value := value) + (fuel := fuel + extra) (extra := 133) (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word 0x7f) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + have hcleanup := + call_cleanup_t_uint256_direct (v := evmShr 0x7f value) (fuel := fuel + extra) (extra := 155) + (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word 0x7f) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0x7f) (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + simp [FormalYul.word] at hbits hvalue hshift hcleanup + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hbits, hvalue, hshift, hcleanup] + theorem call_shift_left_t_uint256_t_uint256_direct (value bits fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index 50298e444..7e0135753 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -45,7 +45,7 @@ theorem call_fun_mulExpRay_revert_direct simp only [FormalYul.word] at hclean let sign := signTree y let ay := absTree y - let s := evmSub (evmClz ay) scaleMaxClz + let s := scaleShiftTree ay let k := kTree x let shift := evmSub s k have hzeroInit := @@ -60,105 +60,104 @@ theorem call_fun_mulExpRay_revert_direct have hclz := call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) (shared := shared) (hlookup := hlookup) - have hscaleMaxClz := - call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 2023) + have hscaleClzBias := + call_constant__SCALE_CLZ_BIAS_direct (fuel := fuel + extra) (extra := 2023) (shared := shared) (hlookup := hlookup) have hwrapS := - call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) + call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) + have hconvert127 := + call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2058) + (shared := shared) (hlookup := hlookup) + have hshrAy := + call_shift_right_t_uint256_t_uint8_127_direct (value := ay) + (fuel := fuel + extra) (extra := 1997) (shared := shared) (hlookup := hlookup) + have hwrapAdd := + call_wrapping_add_t_uint256_direct + (x := evmSub (evmClz ay) scaleClzBias) (y := evmShr 127 ay) + (fuel := fuel + extra) (extra := 2095) (shared := shared) (hlookup := hlookup) have hoctave := - call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2058) + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2051) (shared := shared) (hlookup := hlookup) have hconvertS := - call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2054) + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2047) (shared := shared) (hlookup := hlookup) have hwrapShift := - call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2091) - (shared := shared) (hlookup := hlookup) - have hconvert127 := - call_convert_127_to_uint256_direct (fuel := fuel + extra) (extra := 2044) - (shared := shared) (hlookup := hlookup) - have hcleanupSGuard := - call_cleanup_t_uint256_direct (v := s) (fuel := fuel + extra) (extra := 2142) + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2084) (shared := shared) (hlookup := hlookup) have hHi := - call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2001) + call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2000) (shared := shared) (hlookup := hlookup) have hconvertOne := - call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2037) + call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2036) (shared := shared) (hlookup := hlookup) have hsubHi := call_wrapping_sub_t_int256_direct (x := mulExpRayHi) (y := 1) - (fuel := fuel + extra) (extra := 2079) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2078) (shared := shared) (hlookup := hlookup) have hcleanupHiMinusOne := call_cleanup_t_int256_direct (v := evmSub mulExpRayHi 1) - (fuel := fuel + extra) (extra := 2136) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2135) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2134) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2133) (shared := shared) (hlookup := hlookup) - have hOrOut := - call_fun_or_direct (a := evmGt s 127) (b := evmSgt x (evmSub mulExpRayHi 1)) - (fuel := fuel + extra) (extra := 2077) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2030) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2029) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2128) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2127) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct - (a := evmOr (evmGt s 127) (evmSgt x (evmSub mulExpRayHi 1))) + (a := evmSgt x (evmSub mulExpRayHi 1)) (b := evmSlt shift 2) - (fuel := fuel + extra) (extra := 2071) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2070) (shared := shared) (hlookup := hlookup) have hoverflow := - call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1986) + call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1985) (shared := shared) (hlookup := hlookup) have hconvu := - call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2025) + call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2024) (shared := shared) (hlookup := hlookup) have hpanic := - call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1544) + call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1543) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_CLZ_BIAS] at hscaleClzBias + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS + simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree] at hshrAy + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapAdd simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave - simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] at hconvertS - simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, scaleMaxClz] + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleShiftTree, + scaleClzBias] at hconvertS + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, + scaleShiftTree, scaleClzBias] at hwrapShift - simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 - simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] - at hcleanupSGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, mulExpRayHi] at hHi simp only [Nat.reduceAdd, FormalYul.word] at hconvertOne simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hsubHi hcleanupHiMinusOne simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, s, ay, absTree, signTree, - scaleMaxClz, mulExpRayHi] at hOrOut simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, - scaleMaxClz] at hcleanupShift + scaleShiftTree, scaleClzBias] at hcleanupShift simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, ay, absTree, - signTree, scaleMaxClz, mulExpRayHi] at hOrGuard + signTree, scaleShiftTree, scaleClzBias, mulExpRayHi] at hOrGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant_ARITHMETIC_OVERFLOW] at hoverflow simp only [Nat.reduceAdd, FormalYul.word] at hconvu simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_panic] at hpanic have hguardUnfold : evmOr - (evmOr - (evmGt - (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - 127) - (evmSgt x (evmSub 86989971160273136331862631244 1))) - (evmSlt - (evmSub + (evmSgt x (evmSub 86989971160273136331862631244 1)) + (evmSlt + (evmSub + (evmAdd (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) - 2) = 1 := by + (evmShr 127 (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)))) + (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) + 2) = 1 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, - scaleMaxClz, mulExpRayHi] using hguard + scaleClzBias, mulExpRayHi] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -167,18 +166,17 @@ theorem call_fun_mulExpRay_revert_direct EvmYul.Yul.State.setStore, FormalYul.word, primCall_signextend_yul, hguardUnfold, - hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS, - hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, - hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hOrOut, + hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleClzBias, hwrapS, + hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, + hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hoverflow, hconvu, hpanic, - FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, Common.Word.uint256_ofNat_xor_eq_word_evmXor, Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, uint256_ofNat_sgt_eq_word_evmSgt, - scaleMaxClz, hclean] + scaleClzBias, hclean] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay` forwards the revert. -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 7e1d61e22..7ca6a84fd 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -48,7 +48,7 @@ theorem call_fun_mulExpRay_direct simp only [FormalYul.word] at hclean let sign := signTree y let ay := absTree y - let s := evmSub (evmClz ay) scaleMaxClz + let s := scaleShiftTree ay let k := kTree x let shift := evmSub s k let scale := evmShl s ay @@ -64,126 +64,126 @@ theorem call_fun_mulExpRay_direct have hclz := call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) (shared := shared) (hlookup := hlookup) - have hscaleMaxClz := - call_constant__SCALE_MAX_CLZ_direct (fuel := fuel + extra) (extra := 2023) + have hscaleClzBias := + call_constant__SCALE_CLZ_BIAS_direct (fuel := fuel + extra) (extra := 2023) (shared := shared) (hlookup := hlookup) have hwrapS := - call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleMaxClz) + call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) + have hconvert127 := + call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2058) + (shared := shared) (hlookup := hlookup) + have hshrAy := + call_shift_right_t_uint256_t_uint8_127_direct (value := ay) + (fuel := fuel + extra) (extra := 1997) (shared := shared) (hlookup := hlookup) + have hwrapAdd := + call_wrapping_add_t_uint256_direct + (x := evmSub (evmClz ay) scaleClzBias) (y := evmShr 127 ay) + (fuel := fuel + extra) (extra := 2095) (shared := shared) (hlookup := hlookup) have hoctave := - call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2058) + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2051) (shared := shared) (hlookup := hlookup) have hconvertS := - call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2054) + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2047) (shared := shared) (hlookup := hlookup) have hwrapShift := - call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2091) - (shared := shared) (hlookup := hlookup) - have hconvert127 := - call_convert_127_to_uint256_direct (fuel := fuel + extra) (extra := 2044) - (shared := shared) (hlookup := hlookup) - have hcleanupSGuard := - call_cleanup_t_uint256_direct (v := s) (fuel := fuel + extra) (extra := 2142) + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2084) (shared := shared) (hlookup := hlookup) have hHi := - call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2001) + call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2000) (shared := shared) (hlookup := hlookup) have hconvertOne := - call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2037) + call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2036) (shared := shared) (hlookup := hlookup) have hsubHi := call_wrapping_sub_t_int256_direct (x := mulExpRayHi) (y := 1) - (fuel := fuel + extra) (extra := 2079) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2078) (shared := shared) (hlookup := hlookup) have hcleanupHiMinusOne := call_cleanup_t_int256_direct (v := evmSub mulExpRayHi 1) - (fuel := fuel + extra) (extra := 2136) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2135) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2134) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2133) (shared := shared) (hlookup := hlookup) - have hOrOut := - call_fun_or_direct (a := evmGt s 127) (b := evmSgt x (evmSub mulExpRayHi 1)) - (fuel := fuel + extra) (extra := 2077) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2030) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2029) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2128) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2127) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct - (a := evmOr (evmGt s 127) (evmSgt x (evmSub mulExpRayHi 1))) + (a := evmSgt x (evmSub mulExpRayHi 1)) (b := evmSlt shift 2) - (fuel := fuel + extra) (extra := 2071) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2070) (shared := shared) (hlookup := hlookup) have hscaleShift := call_shift_left_t_uint256_t_uint256_direct (value := ay) (bits := s) - (fuel := fuel + extra) (extra := 1961) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 1960) (shared := shared) (hlookup := hlookup) have hconvertShiftOut := - call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2018) + call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2017) (shared := shared) (hlookup := hlookup) have hZM := - call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1977) + call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1976) (shared := shared) (hlookup := hlookup) have hkernel := call_fun__expRayKernel_direct (x := x) (k := k) (scale := scale) (shift := shift) - (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1436) + (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1435) (shared := shared) (hlookup := hlookup) have hconvertInt256 := call_convert_uint256_to_int256_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 2011) (shared := shared) (hlookup := hlookup) + (extra := 2010) (shared := shared) (hlookup := hlookup) have hconvertNarrow := call_convert_int256_to_int128_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 2010) (shared := shared) (hlookup := hlookup) + (extra := 2009) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_MAX_CLZ] at hscaleMaxClz - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleMaxClz] at hwrapS + simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_CLZ_BIAS] at hscaleClzBias + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS + simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree] at hshrAy + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapAdd simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave - simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] at hconvertS - simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, scaleMaxClz] + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleShiftTree, + scaleClzBias] at hconvertS + simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, + scaleShiftTree, scaleClzBias] at hwrapShift - simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 - simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] - at hcleanupSGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, mulExpRayHi] at hHi simp only [Nat.reduceAdd, FormalYul.word] at hconvertOne simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hsubHi hcleanupHiMinusOne simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi - simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, s, ay, absTree, signTree, - scaleMaxClz, mulExpRayHi] at hOrOut simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, - scaleMaxClz] at hcleanupShift + scaleShiftTree, scaleClzBias] at hcleanupShift simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, ay, absTree, - signTree, scaleMaxClz, mulExpRayHi] at hOrGuard - simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleMaxClz] at hscaleShift + signTree, scaleShiftTree, scaleClzBias, mulExpRayHi] at hOrGuard + simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleShiftTree, + scaleClzBias] at hscaleShift simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, - scaleMaxClz] at hconvertShiftOut + scaleShiftTree, scaleClzBias] at hconvertShiftOut simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, mulExpRayZeroMax] at hZM simp only [Nat.reduceAdd, FormalYul.word, k, kTree, scale, shift, s, ay, absTree, - signTree, scaleMaxClz, mulExpRayZeroMax, evmShl_one_c0] at hkernel + signTree, scaleShiftTree, scaleClzBias, mulExpRayZeroMax, evmShl_one_c0] at hkernel simp only [Nat.reduceAdd, FormalYul.word, mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, tTree, vTree, evTree, odTree, todTree, kTree, scaleShiftTree, absTree, signTree, tArgShift, k27Q235, ln2Q235, squareShift, ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, - todShift, marginWord, scaleMaxClz, mulExpRayZeroMax] at hconvertInt256 hconvertNarrow + todShift, marginWord, scaleClzBias, mulExpRayZeroMax] at hconvertInt256 hconvertNarrow have hguardUnfold : evmOr - (evmOr - (evmGt - (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - 127) - (evmSgt x (evmSub 86989971160273136331862631244 1))) - (evmSlt - (evmSub + (evmSgt x (evmSub 86989971160273136331862631244 1)) + (evmSlt + (evmSub + (evmAdd (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) - 2) = 0 := by + (evmShr 127 (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)))) + (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) + 2) = 0 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, - scaleMaxClz, mulExpRayHi] using hguard + scaleClzBias, mulExpRayHi] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -194,12 +194,11 @@ theorem call_fun_mulExpRay_direct EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, primCall_signextend_yul, hguardUnfold, - hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleMaxClz, hwrapS, - hoctave, hconvertS, hwrapShift, hconvert127, hcleanupSGuard, - hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hOrOut, + hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleClzBias, hwrapS, + hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, + hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hscaleShift, hconvertShiftOut, hZM, hkernel, hconvertInt256, hconvertNarrow, - FormalYul.Preservation.uint256_ofNat_gt_eq_word_evmGt, FormalYul.Preservation.uint256_ofNat_lt_eq_word_evmLt, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, FormalYul.Preservation.uint256_ofNat_mul_eq_word_evmMul, @@ -215,7 +214,7 @@ theorem call_fun_mulExpRay_direct od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, todShift, marginWord, scaleShiftTree, absTree, signTree, kTree, - scaleMaxClz, mulExpRayZeroMax, hclean] + scaleClzBias, mulExpRayZeroMax, hclean] simpa only [FormalYul.word] using hresultClean set_option maxHeartbeats 12000000 in diff --git a/formal/exp/ExpProof/ExpProof/Theorems.lean b/formal/exp/ExpProof/ExpProof/Theorems.lean index e86bb2299..733483ba7 100644 --- a/formal/exp/ExpProof/ExpProof/Theorems.lean +++ b/formal/exp/ExpProof/ExpProof/Theorems.lean @@ -109,9 +109,10 @@ Every documented `mulExpRay` property holds for the compiled runtime, axiom-clea | Monotone in `x`, direction following `sign(y)` | `run_mul_exp_ray_evm_mono_x` | | Nondecreasing in `y` at a fixed `x` | `run_mul_exp_ray_evm_mono_y` | | Joint sign-aware monotonicity (three cases) | `run_mul_exp_ray_evm_mono_joint` | -| Reverts exactly when magnitude, upper-fence, or closing-shift guard fails | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_magnitude_guard`, `run_mul_exp_ray_evm_revert_int128_min` | -| The 127-bit magnitude guard is exact | `scaleShiftTree_le_127_iff` | -| The maximal magnitude is live at closing shift two | `scaleMax_octave_neg_two_run_bracket` | +| Reverts exactly when the upper-fence or closing-shift guard fails | `mulExpRay_value_iff_not_panic`, `run_mul_exp_ray_evm_revert`, `panicDomain_iff_guard_eq_one` | +| The inclusive `2^127` kernel scale has zero headroom shift | `scaleShiftTree_kernelScaleMax` | +| `int128.min` is accepted exactly below the fence with octave at most `-2` | `int128Min_valueDomain_iff` | +| The positive `int128` maximum is live at closing shift two | `int128Max_octave_neg_two_run_bracket` | Supporting rows: the exact value/panic partition of canonical calldata (`mulExpRay_value_or_panic_of_canonical`), the guard word ↔ domain bridge @@ -120,7 +121,7 @@ Supporting rows: the exact value/panic partition of canonical calldata The proof chain: the scale-symbolic per-point certificates (`r0Scaled_real_over_within`/`r0Scaled_real_under_within`) instantiate at the dynamic scale -`abs(y)·2ˢ ∈ [2¹²⁵, 2¹²⁷ − 1]`; the accumulator fold (`Mul.Accum`) closes the live-region +`abs(y)·2ˢ ∈ [2¹²⁵, 2¹²⁷]`; the accumulator fold (`Mul.Accum`) closes the live-region bracket; the unit-step induction with the scaled seam doubling (`Mul.XMono`) closes the sign-directed exponent monotonicity; the headroom-step induction (`Mul.YMono`) closes the multiplier monotonicity; and the corner composition with the antitone headroom (`Mul.Joint`) @@ -133,57 +134,82 @@ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayValueDomain y x ∨ MulExpRayPanicDomain y x := mulExpRay_value_or_panic_of_canonical hcanon -/-- The magnitude cap is the largest signed 127-bit value. -/ -example : scaleMax = 2 ^ 127 - 1 := scaleMax_eq +/-- The analytic kernel scale includes the absolute magnitude of `int128.min`. -/ +example : kernelScaleMax = 2 ^ 127 := kernelScaleMax_eq -/-- The headroom comparison accepts exactly the magnitudes at or below the cap. -/ -example {y : Nat} : - scaleShiftTree (absTree y) ≤ 127 ↔ absTree y ≤ scaleMax := - scaleShiftTree_le_127_iff (absTree_lt y) +/-- The inclusive endpoint is already normalized and therefore needs no headroom shift. -/ +example : scaleShiftTree kernelScaleMax = 0 := + scaleShiftTree_kernelScaleMax /-- The panic predicate is exactly the compiled guard word being one. -/ example {y x : Nat} (hcanon : MulExpRayCanonical y x) : MulExpRayPanicDomain y x ↔ mulExpGuardTree y x = 1 := panicDomain_iff_guard_eq_one hcanon -/-- The never-over certificate holds at the maximal dynamic scale. -/ +/-- The compiled guard rejects exactly at the upper fence or below closing shift two. -/ +example {y x : Nat} (hx : x < 2 ^ 256) : + mulExpGuardTree y x = 1 ↔ + FormalYul.Preservation.int256 mulExpRayHi ≤ FormalYul.Preservation.int256 x ∨ + FormalYul.Preservation.int256 (mulShiftTree y x) < 2 := + mulExpGuardTree_eq_one_iff hx + +/-- The never-over certificate holds at the inclusive maximal dynamic scale. -/ example {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : - (FormalYul.Preservation.int256 (r0ScaledTree scaleMax x) : Real) ≤ - (scaleMax : Real) * Real.exp (reducedArg x) + + (FormalYul.Preservation.int256 (r0ScaledTree kernelScaleMax x) : Real) ≤ + (kernelScaleMax : Real) * Real.exp (reducedArg x) + 2 * 4668745981919039833 / 10000000000000000000 := - r0Scaled_real_over_within (by norm_num [scaleMax]) (le_refl _) hx hW + r0Scaled_real_over_within (by norm_num [kernelScaleMax]) (le_refl _) hx hW -/-- The deficit certificate holds at the maximal dynamic scale. -/ +/-- The deficit certificate holds at the inclusive maximal dynamic scale. -/ example {x : Nat} (hx : x < 2 ^ 256) (hW : WideRegion x) : - (scaleMax : Real) * Real.exp (reducedArg x) ≤ - (FormalYul.Preservation.int256 (r0ScaledTree scaleMax x) : Real) + 2993 / 1000 := - r0Scaled_real_under_within (by norm_num [scaleMax]) (le_refl _) hx hW + (kernelScaleMax : Real) * Real.exp (reducedArg x) ≤ + (FormalYul.Preservation.int256 (r0ScaledTree kernelScaleMax x) : Real) + 2993 / 1000 := + r0Scaled_real_under_within (by norm_num [kernelScaleMax]) (le_refl _) hx hW -/-- At the maximal magnitude, octave `-2` attains the minimum accepted closing shift and the -compiled runtime satisfies its signed bracket. -/ -theorem scaleMax_octave_neg_two_run_bracket {x : Nat} (hx : x < 2 ^ 256) +/-- At the positive `int128` maximum, octave `-2` attains the minimum accepted closing shift and +the compiled runtime satisfies its signed bracket. -/ +theorem int128Max_octave_neg_two_run_bracket {x : Nat} (hx : x < 2 ^ 256) (hxhi : FormalYul.Preservation.int256 x < FormalYul.Preservation.int256 mulExpRayHi) (hk : FormalYul.Preservation.int256 (kTree x) = -2) : - scaleShiftTree (absTree scaleMax) = 0 ∧ - FormalYul.Preservation.int256 (mulShiftTree scaleMax x) = 2 ∧ - MulExpRayRunBracket scaleMax x := by - obtain ⟨hs, hshift, hdom⟩ := scaleMax_octave_neg_two_valueDomain hx hxhi hk + scaleShiftTree (absTree int128Max) = 0 ∧ + FormalYul.Preservation.int256 (mulShiftTree int128Max x) = 2 ∧ + MulExpRayRunBracket int128Max x := by + obtain ⟨hs, hshift, hdom⟩ := int128Max_octave_neg_two_valueDomain hx hxhi hk exact ⟨hs, hshift, mulExpRay_run_bracket hdom⟩ -/-- A concrete exponent word in octave `-2` witnesses the live maximal-magnitude boundary. -/ -theorem scaleMax_concrete_neg_three_halves_run_bracket : - scaleShiftTree (absTree scaleMax) = 0 ∧ +/-- A concrete exponent word in octave `-2` witnesses the live positive-magnitude boundary. -/ +theorem int128Max_concrete_neg_three_halves_run_bracket : + scaleShiftTree (absTree int128Max) = 0 ∧ FormalYul.Preservation.int256 - (mulShiftTree scaleMax + (mulShiftTree int128Max (2 ^ 256 - 1500000000000000000000000000)) = 2 ∧ - MulExpRayRunBracket scaleMax + MulExpRayRunBracket int128Max (2 ^ 256 - 1500000000000000000000000000) := by - apply scaleMax_octave_neg_two_run_bracket + apply int128Max_octave_neg_two_run_bracket · norm_num · norm_num [FormalYul.Preservation.int256, mulExpRayHi] · decide +kernel +/-- At `int128.min`, octave `-2` attains the minimum accepted closing shift and lies in the value +domain below the unconditional upper fence. -/ +example {x : Nat} (hx : x < 2 ^ 256) + (hxhi : FormalYul.Preservation.int256 x < + FormalYul.Preservation.int256 mulExpRayHi) + (hk : FormalYul.Preservation.int256 (kTree x) = -2) : + scaleShiftTree (absTree (2 ^ 256 - 2 ^ 127)) = 0 ∧ + FormalYul.Preservation.int256 (mulShiftTree (2 ^ 256 - 2 ^ 127) x) = 2 ∧ + MulExpRayValueDomain (2 ^ 256 - 2 ^ 127) x := + int128Min_octave_neg_two_valueDomain hx hxhi hk + +/-- `int128.min` is accepted exactly below the unconditional upper fence while the octave is at +most `-2`. -/ +example {x : Nat} (hx : x < 2 ^ 256) : + MulExpRayValueDomain (2 ^ 256 - 2 ^ 127) x ↔ + FormalYul.Preservation.int256 x < FormalYul.Preservation.int256 mulExpRayHi ∧ + FormalYul.Preservation.int256 (kTree x) ≤ -2 := + int128Min_valueDomain_iff hx + /-- **The signed bracket on the whole value domain.** Every accepted input returns a result whose magnitude `m` satisfies `0 ≤ m ≤ A ∧ A < m + 2` for `A = abs(y)·exp(x/10²⁷)`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : MulExpRayRunBracket y x := @@ -214,21 +240,6 @@ example {y1 y2 x1 x2 : Nat} MulExpRayRunJointMonotone y1 y2 x1 x2 := run_mul_exp_ray_evm_mono_joint h1 h2 hcond -/-- **The panic domain in magnitude/guard vocabulary**: too-large magnitude, exponent at or beyond -the unconditional fence, or a closing shift below two. -/ -example {y x : Nat} (hcanon : MulExpRayCanonical y x) : - MulExpRayPanicDomain y x ↔ - scaleMax < absTree y ∨ - FormalYul.Preservation.int256 mulExpRayHi ≤ FormalYul.Preservation.int256 x ∨ - FormalYul.Preservation.int256 (mulShiftTree y x) < 2 := - panicDomain_iff_magnitude_guard hcanon - -/-- **`type(int128).min` always reverts**: its magnitude `2^127` exceeds the maximal -scale. -/ -example {x : Nat} (hx : x < 2 ^ 256) : - run_mul_exp_ray_evm (2 ^ 256 - 2 ^ 127) x = .error "revert" := - run_mul_exp_ray_evm_revert_int128_min hx - /-- **Floor membership.** Every accepted input's result magnitude is `⌊A⌋` or `⌊A⌋ − 1`. -/ example {y x : Nat} (h : MulExpRayValueDomain y x) : ∃ r, run_mul_exp_ray_evm y x = .ok r ∧ @@ -283,28 +294,27 @@ example {y x : Nat} (h : MulExpRayPanicDomain y x) : run_mul_exp_ray_evm_revert h /-- The accepted scale point returns the multiplier exactly. -/ -example {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ scaleMax) +example {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ kernelScaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : run_mul_exp_ray_evm y 0 = .ok y := run_mul_exp_ray_evm_scale_point hy habs hshift /-- The scale-point result satisfies the public bracket. -/ -example {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ scaleMax) +example {y : Nat} (hy : Int128Word y) (habs : absTree y ≤ kernelScaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y 0)) : MulExpRayRunBracket y 0 := mulExpRay_run_bracket_scale_point hy habs hshift /-- At or below the zero cutoff, every accepted magnitude returns zero. -/ example {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : run_mul_exp_ray_evm y x = .ok 0 := - run_mul_exp_ray_evm_clamped hy hx habs hshift hclamp + run_mul_exp_ray_evm_clamped hy hx hshift hclamp /-- The clamped result satisfies the public bracket. -/ example {y x : Nat} (hy : Int128Word y) (hx : x < 2 ^ 256) - (habs : absTree y ≤ scaleMax) + (habs : absTree y ≤ kernelScaleMax) (hshift : 2 ≤ FormalYul.Preservation.int256 (mulShiftTree y x)) (hclamp : FormalYul.Preservation.int256 x ≤ FormalYul.Preservation.int256 mulExpRayZeroMax) : MulExpRayRunBracket y x := @@ -363,18 +373,22 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms mulExpRay_run_bracket -/-- info: 'ExpYul.scaleMax_eq' depends on axioms: [propext] -/ +/-- info: 'ExpYul.kernelScaleMax_eq' depends on axioms: [propext] -/ #guard_msgs in -#print axioms scaleMax_eq +#print axioms kernelScaleMax_eq -/-- info: 'ExpYul.scaleShiftTree_le_127_iff' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.scaleShiftTree_kernelScaleMax' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms scaleShiftTree_le_127_iff +#print axioms scaleShiftTree_kernelScaleMax /-- info: 'ExpYul.panicDomain_iff_guard_eq_one' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms panicDomain_iff_guard_eq_one +/-- info: 'ExpYul.mulExpGuardTree_eq_one_iff' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +#guard_msgs in +#print axioms mulExpGuardTree_eq_one_iff + /-- info: 'ExpYul.r0Scaled_real_over_within' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in #print axioms r0Scaled_real_over_within @@ -383,13 +397,13 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms r0Scaled_real_under_within -/-- info: 'ExpYul.scaleMax_octave_neg_two_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.int128Max_octave_neg_two_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms scaleMax_octave_neg_two_run_bracket +#print axioms int128Max_octave_neg_two_run_bracket -/-- info: 'ExpYul.scaleMax_concrete_neg_three_halves_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.int128Max_concrete_neg_three_halves_run_bracket' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms scaleMax_concrete_neg_three_halves_run_bracket +#print axioms int128Max_concrete_neg_three_halves_run_bracket /-- info: 'ExpYul.run_mul_exp_ray_evm_mono_x' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in @@ -411,13 +425,13 @@ example {y1 y2 x1 x2 : Int} #guard_msgs in #print axioms run_mul_exp_ray_evm_mono_joint -/-- info: 'ExpYul.panicDomain_iff_magnitude_guard' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.int128Min_octave_neg_two_valueDomain' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms panicDomain_iff_magnitude_guard +#print axioms int128Min_octave_neg_two_valueDomain -/-- info: 'ExpYul.run_mul_exp_ray_evm_revert_int128_min' depends on axioms: [propext, Classical.choice, Quot.sound] -/ +/-- info: 'ExpYul.int128Min_valueDomain_iff' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs in -#print axioms run_mul_exp_ray_evm_revert_int128_min +#print axioms int128Min_valueDomain_iff /-- info: 'ExpYul.mulExpRay_value_or_panic_of_canonical' depends on axioms: [propext, Quot.sound] -/ #guard_msgs in diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index eafaebbe8..477b0a471 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -72,7 +72,8 @@ def functionPrefixes : ModelKind → List String "fun_wrap_expRayToWad_", "fun_wrap_mulExpRay_", "fun_expRayToWad_", "fun_mulExpRay_", "fun__octave_", "fun__expRayKernel_", - "constant__EXP_RAY_TO_WAD_HI_", "constant__WAD_SCALE_", "constant__WAD_ZERO_MAX_", + "constant__EXP_RAY_TO_WAD_HI_", "constant__SCALE_CLZ_BIAS_", + "constant__WAD_SCALE_", "constant__WAD_ZERO_MAX_", "constant_ARITHMETIC_OVERFLOW_", "fun_panic_", "fun_or_", "fun_clz_"] @@ -754,7 +755,7 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : aliasByPrefix functions "fun__octave" "fun__octave_", aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", aliasByPrefix functions "constant__EXP_RAY_TO_WAD_HI" "constant__EXP_RAY_TO_WAD_HI_", - aliasByPrefix functions "constant__SCALE_MAX_CLZ" "constant__SCALE_MAX_CLZ_", + aliasByPrefix functions "constant__SCALE_CLZ_BIAS" "constant__SCALE_CLZ_BIAS_", aliasByPrefix functions "constant__WAD_SCALE" "constant__WAD_SCALE_", aliasByPrefix functions "constant__WAD_ZERO_MAX" "constant__WAD_ZERO_MAX_", aliasByPrefix functions "constant__MUL_EXP_RAY_HI" "constant__MUL_EXP_RAY_HI_", diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index bdb1ae083..de5b1240a 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -8,8 +8,7 @@ import {Clz} from "./Clz.sol"; library Exp { using FastLogic for bool; - // With s = clz(abs(y)) - 129, the s ≤ 127 guard admits exactly magnitudes through 2¹²⁷ − 1. - uint256 private constant _SCALE_MAX_CLZ = 129; + uint256 private constant _SCALE_CLZ_BIAS = 129; // 10¹⁸ ⋅ 2⁶⁷ < 2¹²⁷: `expRayToWad`'s scale — the wad output basis carrying 67 bits of // closing headroom. uint256 private constant _WAD_SCALE = 0x6f05b59d3b2000000000000000000000; @@ -32,7 +31,7 @@ library Exp { int256 private constant _MUL_EXP_RAY_HI = 86989971160273136331862631244; // The least x whose octave count reaches -127, i.e. ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ // -127.5⋅ln(2)⋅10²⁷ ≈ -88.38⋅10²⁷. At or below it the kernel clamps `mulExpRay` to zero, - // which is within the bracket at every supported scale ((2¹²⁷ - 1)⋅exp(x/10²⁷) < 1); the + // which is within the bracket at every supported scale (2¹²⁷⋅exp(x/10²⁷) < 1); the // clamp consults only x, so it also zeroes every accepted x inside `_octave`'s negative // wraparound region (x ≲ -2¹⁵²). Above it, k ≥ -127 keeps the closing shift below 256 and // the reduced argument on the certified domain. @@ -72,13 +71,13 @@ library Exp { /// (y₁, x₁) and (y₂, x₂), the first result is no greater than the second when 0 ≤ y₁ ≤ y₂ /// and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. /// - /// Reverts with `Panic(17)` in exactly three cases: - /// y = type(int128).min; x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ (regardless of - /// y); or the octave word — `_octave`'s output, which is round(x / (10²⁷⋅ln(2))) wherever - /// its product does not wrap (|x| ≲ 2¹⁵²) — exceeding s - 2, with 2ˢ the scale headroom - /// above abs(y) (the largest power of two with abs(y)⋅2ˢ < 2¹²⁷; - /// s = 127 at y = 0). Within the wrap-free range the accepted exponents form one - /// interval that narrows as abs(y) grows, and every accepted + /// Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ + /// (regardless of y), or when the octave word — `_octave`'s output, which is + /// round(x / (10²⁷⋅ln(2))) wherever its product does not wrap (|x| ≲ 2¹⁵²) — exceeds + /// s - 2, with 2ˢ the scale headroom above abs(y). The normalized scale is at most + /// 2¹²⁷; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. Within the + /// wrap-free range the accepted exponents form one interval that narrows as abs(y) + /// grows, and every accepted /// x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap /// boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to /// zero, either of which is sound (A < 1 there at every supported magnitude). @@ -94,17 +93,13 @@ library Exp { } unchecked { - // The scale headroom aligns ay's top bit with bit 126 (127 at ay = 0), keeping every - // supported pre-scale below 2¹²⁷ without a value comparison. For a 128-bit or larger - // ay, clz comes up short of _SCALE_MAX_CLZ and the subtraction - // underflows to a word whose int256 value is in [-129, -1]. The magnitude guard below - // rejects every such ay after FastLogic eagerly evaluates the garbage shift comparison. - uint256 s = Clz.clz(ay) - _SCALE_MAX_CLZ; + // The top-bit term admits abs(type(int128).min) at s = 0 while leaving every smaller + // magnitude's normalization unchanged. + uint256 s = Clz.clz(ay) - _SCALE_CLZ_BIAS + (ay >> 127); int256 k = _octave(x); int256 shift = int256(s) - k; // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: - // - abs(y) requiring at least 128 bits; // - x at or above the octave (k = 126) that exhausts the deficit envelope at even // the maximal headroom, phrased as one signed comparison against the constant // less one; its irreducible role is fencing accepted x away from `_octave`'s @@ -115,7 +110,7 @@ library Exp { // result would be exact. When `_octave`'s product wraps (x ≲ -2¹⁵²) its output // stands in for k, so those exponents revert or pass as the wrapped word falls; // the kernel's clamp zeroes every accepted one. - if ((s > 127).or(x > _MUL_EXP_RAY_HI - 1).or(shift < 2)) { + if ((x > _MUL_EXP_RAY_HI - 1).or(shift < 2)) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } @@ -148,7 +143,7 @@ library Exp { /// @dev The rational polynomial approximation kernel, shared by `expRayToWad` /// (scale = 10¹⁸⋅2⁶⁷, shift = 67 - k) and `mulExpRay` (scale = abs(y)⋅2ˢ, shift = s - k). /// The caller must maintain: - /// - `k == _octave(x)` and `scale < 2¹²⁷`: the margin and deficit budgets below + /// - `k == _octave(x)` and `scale ≤ 2¹²⁷`: the margin and deficit budgets below /// hold throughout this range, and smaller scales only shrink them; /// - `scale == base << s` for the caller's magnitude base, with `shift == s - k`; /// - for every accepted x with `zeroCutoff` < x and x ≠ 0: `shift ≥ 2` (the deficit @@ -195,7 +190,8 @@ library Exp { // product stays inside 256 bits // dividend: Q156 the widest basis that fits in 256 bits before the single truncating // `DIV` by Q89 divisor. < 2¹²⁹ - // r: the pre-scale is below 2¹²⁷ to avoid overflowing the dividend. + // r: the pre-scale is at most 2¹²⁷; the strict numerator bound keeps the dividend + // below 2²⁵⁶ at the endpoint. // output: the closing `shr(shift, …)` is the output-rounding floor, with the 2ᵏ octave // scaling folded into the caller's scale/shift pair. // @@ -221,7 +217,7 @@ library Exp { // grid term below 2⁻²²⁸), lifting ê by ≤ 0.0055242717280199026 (≈ √2/256). // // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid unit - // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale < 2¹²⁷ and + // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale ≤ 2¹²⁷ and // Δ < 1/2, its image scale⋅Δ/2¹²⁶ is below one grid unit. The margin dominates the image: // 0x01, worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so // the pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is @@ -288,9 +284,9 @@ library Exp { // both positive. let tod := sar(0x81, mul(t, od)) - // The scaled rational: the caller keeps scale < 2¹²⁷, so one `DIV` scales, widens, - // and floors at once. The numerator stays below 2¹²⁹ and scale < 2¹²⁷, so the - // dividend stays inside 256 bits; the denominator > 0. + // The scaled rational: one `DIV` scales, widens, and floors at once. The numerator + // stays strictly below 2¹²⁹ and scale ≤ 2¹²⁷, so the dividend stays inside 256 bits; + // the denominator > 0. r := div(mul(scale, add(ev, tod)), sub(ev, tod)) // Less the one-sided margin (0x01; see the budget above), then floored by diff --git a/test/0.8.34/Exp.t.sol b/test/0.8.34/Exp.t.sol index 29c966982..e4202b053 100644 --- a/test/0.8.34/Exp.t.sol +++ b/test/0.8.34/Exp.t.sol @@ -7,8 +7,9 @@ import {Clz} from "src/vendor/Clz.sol"; import {Test, stdError} from "@forge-std/Test.sol"; contract ExpTest is Test { - // The largest magnitude admitted by `mulExpRay`'s s <= 127 guard. - uint256 private constant _SCALE_MAX = 0x7fffffffffffffffffffffffffffffff; + // The largest positive `int128` magnitude. + uint256 private constant _INT128_MAX = 0x7fffffffffffffffffffffffffffffff; + uint256 private constant _KERNEL_SCALE_MAX = uint256(1) << 127; int128 private constant _Y_MAX = type(int128).max; // First input whose octave count exceeds the supported range; `expRayToWad` reverts here. int256 private constant _TOO_BIG = 0x92b2f16cc66c5a4ae96e80d4; @@ -221,7 +222,7 @@ contract ExpTest is Test { } /// x = 0 is pinned exactly wherever it is accepted: acceptance needs two bits of closing - /// shift, i.e. 4*abs(y) <= _SCALE_MAX. One unit of magnitude past that boundary reverts. + /// shift, i.e. 4*abs(y) <= _INT128_MAX. One unit of magnitude past that boundary reverts. function testMulExpRayScalePoint() external { assertEq(Exp.mulExpRay(1, 0), 1, "one"); assertEq(Exp.mulExpRay(-1, 0), -1, "minus one"); @@ -234,7 +235,7 @@ contract ExpTest is Test { this.mulExpRayExternal(-(pinMax + 1), 0); } - /// At abs(y) = _SCALE_MAX (s = 0), octave k = -2 is the highest accepted octave and the + /// At abs(y) = _INT128_MAX (s = 0), octave k = -2 is the highest accepted octave and the /// closing shift is exactly 2. The two-unit bracket must hold at both ends of that octave. function testMulExpRayScaleCapLive() external pure { int256 x = _octaveStart(-2); @@ -286,19 +287,22 @@ contract ExpTest is Test { this.mulExpRayExternal(0, type(int256).max); } - /// `_SCALE_MAX_CLZ` inside the library must track the maximal sub-2**127 scale. The positive - /// Q126 over envelope remains below one half, so its image at the cap is below one unit. - function testScaleMaxClzPairing() external pure { - assertEq(_SCALE_MAX, (uint256(1) << 127) - 1, "maximal 127-bit scale"); + /// The positive Q126 over envelope remains below one half, so its image at the inclusive + /// scale cap is below one unit. + function testScaleCapPairing() external pure { + assertEq(_INT128_MAX, (uint256(1) << 127) - 1, "positive int128 maximum"); + assertEq(_KERNEL_SCALE_MAX, uint256(1) << 127, "inclusive kernel scale maximum"); assertLt(uint256(2 * 4668745981919039833), uint256(1e19), "over envelope below one half"); - assertEq(Clz.clz(_SCALE_MAX), 129, "_SCALE_MAX_CLZ"); - assertLe(uint256(1e18) << 67, _SCALE_MAX, "wad scale within the cap"); + assertEq(Clz.clz(_INT128_MAX), 129, "positive maximum clz"); + assertEq(Clz.clz(_KERNEL_SCALE_MAX), 128, "negative minimum magnitude clz"); + assertLe(uint256(1e18) << 67, _INT128_MAX, "wad scale within the cap"); } function testMulExpRayLowerZero() external pure { assertEq(Exp.mulExpRay(1, _X_LO_ZERO), 0, "one at boundary"); assertEq(Exp.mulExpRay(_Y_MAX, _X_LO_ZERO), 0, "scale max at boundary"); assertEq(Exp.mulExpRay(-_Y_MAX, _X_LO_ZERO - 1), 0, "negative below boundary"); + assertEq(Exp.mulExpRay(type(int128).min, _X_LO_ZERO), 0, "minimum at boundary"); } function testMulExpRayNegativeSignSymmetry() external pure { @@ -311,17 +315,28 @@ contract ExpTest is Test { function testMulExpRayClearsDirtyYBits() external pure { uint256 positive = (type(uint256).max << 128) | uint256(uint128(1e18)); uint256 negative = uint256(uint128(-int128(1e18))); + uint256 minimum = _KERNEL_SCALE_MAX; assertEq(mulExpRayDirtyY(positive, 1e27), Exp.mulExpRay(1e18, 1e27), "dirty positive"); assertEq(mulExpRayDirtyY(negative, 1e27), Exp.mulExpRay(-1e18, 1e27), "dirty negative"); + assertEq(mulExpRayDirtyY(minimum, -3e27), Exp.mulExpRay(type(int128).min, -3e27), "dirty minimum"); } - function testMulExpRayMinReverts() external { + function testMulExpRayMinBoundary() external { + int128 y = type(int128).min; + int256 x = _octaveStart(-2); + assertEq(Exp.mulExpRay(y, x), -30076996146000563943129221579116071223, "k = -2 start"); + + x = _octaveStart(-1) - 1; + assertEq(x, -1039720770839917964125848183, "k = -2 end"); + assertEq(Exp.mulExpRay(y, x), -60153992292001127886258443070517000410, "k = -2 end value"); + + assertEq(Exp.mulExpRay(y, _X_LO_ZERO), 0, "zero clamp"); vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(type(int128).min, 0); + this.mulExpRayExternal(y, _octaveStart(-1)); vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(type(int128).min, _X_LO_ZERO); + this.mulExpRayExternal(y, 0); vm.expectRevert(stdError.arithmeticError); - this.mulExpRayExternal(type(int128).min, type(int256).min); + this.mulExpRayExternal(y, type(int256).min); } function testMulExpRayHighGuardReverts() external { @@ -369,7 +384,7 @@ contract ExpTest is Test { /// at its deepest accepted octaves. function testMulExpRayMonotoneYHeadroomBoundaries() external pure { for (uint256 s0 = 1; s0 <= 126; ++s0) { - int128 q = int128(uint128(_SCALE_MAX >> s0)); + int128 q = int128(uint128(_INT128_MAX >> s0)); int256 kmax = int256(s0) - 3; for (int256 k = kmax; k >= kmax - 2 && k >= -60; --k) { int256 xb = _octaveStart(k); @@ -384,7 +399,7 @@ contract ExpTest is Test { /// Fuzz the bit-length headroom boundaries across the full accepted exponent range. function testFuzzMulExpRayMonotoneYHeadroom(uint256 us, int256 x) external pure { uint256 s0 = bound(us, 1, 126); - int128 q = int128(uint128(_SCALE_MAX >> s0)); + int128 q = int128(uint128(_INT128_MAX >> s0)); // The deepest x accepted by both magnitudes: octave count at most s0 - 3. x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s0) - 2) - 1); assertLe(Exp.mulExpRay(q, x), Exp.mulExpRay(q + 1, x), "y-monotonicity across headroom"); @@ -394,9 +409,21 @@ contract ExpTest is Test { /// Adjacent multipliers anywhere in the supported range, with the exponent bounded to the /// octaves both headrooms accept. function testFuzzMulExpRayMonotoneYAdjacent(uint256 uy, int256 x) external pure { - int128 y = int128(uint128(bound(uy, 1, _SCALE_MAX - 1))); + int128 y = int128(uint128(bound(uy, 1, _INT128_MAX - 1))); uint256 s = Clz.clz(uint256(uint128(y)) + 1) - 129; x = bound(x, _X_LO_ZERO + 1, _octaveStart(int256(s) - 1) - 1); assertLe(Exp.mulExpRay(y, x), Exp.mulExpRay(y + 1, x), "adjacent y-monotonicity"); } + + function testFuzzMulExpRayMinYMonotone(int256 x) external pure { + x = bound(x, _X_LO_ZERO + 1, _octaveStart(-1) - 1); + int128 y = type(int128).min; + assertLe(Exp.mulExpRay(y, x), Exp.mulExpRay(y + 1, x), "minimum-y adjacency"); + } + + function testFuzzMulExpRayMinXMonotone(int256 x) external pure { + x = bound(x, _X_LO_ZERO + 1, _octaveStart(-1) - 2); + int128 y = type(int128).min; + assertGe(Exp.mulExpRay(y, x), Exp.mulExpRay(y, x + 1), "minimum-y x-monotonicity"); + } } From 2b2bcae5f4675847a537c06d64d8f533ca9fd2e1 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 21:59:26 +0200 Subject: [PATCH 086/107] Inline single-use Exp constants Embed each one-use threshold and scale at its use site and certify the generated Yul through direct literal conversions. Co-Authored-By: OpenAI Codex --- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 289 ++---------------- .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 49 ++- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 57 ++-- formal/exp/ExpProof/ExpProof/Seam/Revert.lean | 11 +- formal/exp/ExpProof/ExpProof/Seam/Value.lean | 42 ++- formal/yul/YulImporter.lean | 8 - src/vendor/Exp.sol | 65 ++-- 7 files changed, 114 insertions(+), 407 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 849c54c7b..7eb8a4b32 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -343,37 +343,6 @@ theorem call_convert_44_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_constant__EXP_RAY_TO_WAD_HI_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__EXP_RAY_TO_WAD_HI) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0x92b2f16cc66c5a4ae96e80d4]) := by - rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_constant__EXP_RAY_TO_WAD_HI] - simp only [yulFunctionBody_constant__EXP_RAY_TO_WAD_HI, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv := - call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) - (fuel := fuel + extra + 35) (extra := 0) (shared := shared) - (store := Finmap.insert "expr_131" (FormalYul.word 0x92b2f16cc66c5a4ae96e80d4) - (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word] at hconv - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, hconv] - theorem call_convert_67_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -514,70 +483,6 @@ theorem call_convert_WAD_ZERO_MAX_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_constant__WAD_SCALE_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__WAD_SCALE) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, - [FormalYul.word 0x6f05b59d3b2000000000000000000000]) := by - rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__WAD_SCALE] - simp only [yulFunctionBody_constant__WAD_SCALE, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv := - call_convert_WAD_SCALE_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) - (shared := shared) - (store := Finmap.insert "expr_128" - (FormalYul.word 0x6f05b59d3b2000000000000000000000) - (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word] at hconv - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, hconv] - -theorem call_constant__WAD_ZERO_MAX_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__WAD_ZERO_MAX) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, - [FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7]) := by - rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__WAD_ZERO_MAX] - simp only [yulFunctionBody_constant__WAD_ZERO_MAX, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv := - call_convert_WAD_ZERO_MAX_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) - (shared := shared) - (store := Finmap.insert "expr_135" - (FormalYul.word 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) - (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word] at hconv - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, hconv] - theorem call_wrapping_sub_t_int256_direct (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -948,28 +853,6 @@ theorem call_zero_value_for_split_t_bool_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_cleanup_t_rational_1_direct - (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] - (.some "cleanup_t_rational_1_by_1") (.some yulContract) - (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by - rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_cleanup_t_rational_1_by_1] - simp only [yulFunction_cleanup_t_rational_1_by_1, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word] - theorem call_cleanup_t_rational_2_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -1036,19 +919,19 @@ theorem call_cleanup_t_rational_129_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] -theorem call_cleanup_t_rational_MUL_EXP_RAY_HI_direct +theorem call_cleanup_t_rational_MUL_EXP_RAY_HI_MINUS_ONE_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] - (.some "cleanup_t_rational_86989971160273136331862631244_by_1") + (.some "cleanup_t_rational_86989971160273136331862631243_by_1") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_cleanup_t_rational_86989971160273136331862631244_by_1] - simp only [yulFunction_cleanup_t_rational_86989971160273136331862631244_by_1, + lookup_cleanup_t_rational_86989971160273136331862631243_by_1] + simp only [yulFunction_cleanup_t_rational_86989971160273136331862631243_by_1, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, @@ -1120,46 +1003,6 @@ theorem call_convert_2_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_convert_1_to_int256_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 1] - (.some "convert_t_rational_1_by_1_to_t_int256") - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 1]) := by - rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_convert_t_rational_1_by_1_to_t_int256] - simp only [yulFunction_convert_t_rational_1_by_1_to_t_int256, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have h1 := - call_cleanup_t_rational_1_direct (v := 1) (fuel := fuel + extra) (extra := 92) - (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 1) (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - have h2 := - call_identity_direct (v := 1) (fuel := fuel + extra) (extra := 94) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 1) (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - have h3 := - call_cleanup_t_int256_direct (v := 1) (fuel := fuel + extra) (extra := 96) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word 1) (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word] at h1 h2 h3 - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.evalCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, h1, h2, h3] - theorem call_convert_127_to_uint8_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -1240,41 +1083,45 @@ theorem call_convert_129_to_uint256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, h1, h2, h3] -theorem call_convert_MUL_EXP_RAY_HI_to_int256_direct +theorem call_convert_MUL_EXP_RAY_HI_MINUS_ONE_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word mulExpRayHi] - (.some "convert_t_rational_86989971160273136331862631244_by_1_to_t_int256") + EvmYul.Yul.call (fuel + (extra + 120)) + [FormalYul.word 86989971160273136331862631243] + (.some "convert_t_rational_86989971160273136331862631243_by_1_to_t_int256") (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayHi]) := by + .ok (EvmYul.Yul.State.Ok shared store, + [FormalYul.word 86989971160273136331862631243]) := by rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] rw [EvmYul.Yul.call.eq_def] simp only [hlookup, Option.getD_some, yulContract_functions, - lookup_convert_t_rational_86989971160273136331862631244_by_1_to_t_int256] - simp only [yulFunction_convert_t_rational_86989971160273136331862631244_by_1_to_t_int256, + lookup_convert_t_rational_86989971160273136331862631243_by_1_to_t_int256] + simp only [yulFunction_convert_t_rational_86989971160273136331862631243_by_1_to_t_int256, FormalYul.Preservation.functionDefinition_params_def, FormalYul.Preservation.functionDefinition_rets_def, FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have h1 := - call_cleanup_t_rational_MUL_EXP_RAY_HI_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 92) + call_cleanup_t_rational_MUL_EXP_RAY_HI_MINUS_ONE_direct + (v := 86989971160273136331862631243) (fuel := fuel + extra) (extra := 92) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word mulExpRayHi) + (store := Finmap.insert "value" (FormalYul.word 86989971160273136331862631243) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h2 := - call_identity_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 94) (shared := shared) - (store := Finmap.insert "value" (FormalYul.word mulExpRayHi) + call_identity_direct (v := 86989971160273136331862631243) + (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 86989971160273136331862631243) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) have h3 := - call_cleanup_t_int256_direct (v := mulExpRayHi) (fuel := fuel + extra) (extra := 96) - (shared := shared) - (store := Finmap.insert "value" (FormalYul.word mulExpRayHi) + call_cleanup_t_int256_direct (v := 86989971160273136331862631243) + (fuel := fuel + extra) (extra := 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 86989971160273136331862631243) (Inhabited.default : EvmYul.Yul.VarStore)) (hlookup := hlookup) - simp [FormalYul.word, mulExpRayHi] at h1 h2 h3 + simp [FormalYul.word] at h1 h2 h3 simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -1282,7 +1129,7 @@ theorem call_convert_MUL_EXP_RAY_HI_to_int256_direct EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, mulExpRayHi, h1, h2, h3] + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] theorem call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -1329,96 +1176,6 @@ theorem call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word, mulExpRayZeroMax, h1, h2, h3] -theorem call_constant__MUL_EXP_RAY_HI_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__MUL_EXP_RAY_HI) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayHi]) := by - rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__MUL_EXP_RAY_HI] - simp only [yulFunctionBody_constant__MUL_EXP_RAY_HI, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv := - call_convert_MUL_EXP_RAY_HI_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) - (shared := shared) - (store := Finmap.insert "expr_138" (FormalYul.word mulExpRayHi) - (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word, mulExpRayHi] at hconv - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, mulExpRayHi, hconv] - -theorem call_constant__MUL_EXP_RAY_ZERO_MAX_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__MUL_EXP_RAY_ZERO_MAX) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word mulExpRayZeroMax]) := by - rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__MUL_EXP_RAY_ZERO_MAX] - simp only [yulFunctionBody_constant__MUL_EXP_RAY_ZERO_MAX, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv := - call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct (fuel := fuel + extra + 35) (extra := 0) - (shared := shared) - (store := Finmap.insert "expr_142" (FormalYul.word mulExpRayZeroMax) - (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word, mulExpRayZeroMax] at hconv - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, mulExpRayZeroMax, hconv] - -theorem call_constant__SCALE_CLZ_BIAS_direct - (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 160)) [] (.some yulName_constant__SCALE_CLZ_BIAS) - (.some yulContract) (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word scaleClzBias]) := by - rw [show fuel + (extra + 160) = (fuel + extra) + 160 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_constant__SCALE_CLZ_BIAS] - simp only [yulFunctionBody_constant__SCALE_CLZ_BIAS, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hconv := - call_convert_129_to_uint256_direct (fuel := fuel + extra + 35) (extra := 0) - (shared := shared) - (store := Finmap.insert "expr_125" (FormalYul.word scaleClzBias) - (Inhabited.default : EvmYul.Yul.VarStore)) - (hlookup := hlookup) - simp [FormalYul.word, scaleClzBias] at hconv - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, scaleClzBias, hconv] - theorem call_wrapping_sub_t_uint256_direct (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index 7e0135753..2fd0140c2 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -61,7 +61,7 @@ theorem call_fun_mulExpRay_revert_direct call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) (shared := shared) (hlookup := hlookup) have hscaleClzBias := - call_constant__SCALE_CLZ_BIAS_direct (fuel := fuel + extra) (extra := 2023) + call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2060) (shared := shared) (hlookup := hlookup) have hwrapS := call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) @@ -86,43 +86,35 @@ theorem call_fun_mulExpRay_revert_direct call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2084) (shared := shared) (hlookup := hlookup) have hHi := - call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2000) + call_convert_MUL_EXP_RAY_HI_MINUS_ONE_to_int256_direct + (fuel := fuel + extra) (extra := 2037) (shared := shared) (hlookup := hlookup) - have hconvertOne := - call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2036) - (shared := shared) (hlookup := hlookup) - have hsubHi := - call_wrapping_sub_t_int256_direct (x := mulExpRayHi) (y := 1) - (fuel := fuel + extra) (extra := 2078) (shared := shared) (hlookup := hlookup) - have hcleanupHiMinusOne := - call_cleanup_t_int256_direct (v := evmSub mulExpRayHi 1) - (fuel := fuel + extra) (extra := 2135) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2133) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2135) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2029) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2031) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2127) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2129) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct - (a := evmSgt x (evmSub mulExpRayHi 1)) + (a := evmSgt x 86989971160273136331862631243) (b := evmSlt shift 2) - (fuel := fuel + extra) (extra := 2070) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2072) (shared := shared) (hlookup := hlookup) have hoverflow := - call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1985) + call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1987) (shared := shared) (hlookup := hlookup) have hconvu := - call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2024) + call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2026) (shared := shared) (hlookup := hlookup) have hpanic := - call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1543) + call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1545) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_CLZ_BIAS] at hscaleClzBias + simp only [Nat.reduceAdd, FormalYul.word] at hscaleClzBias simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree] at hshrAy @@ -133,22 +125,21 @@ theorem call_fun_mulExpRay_revert_direct simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hwrapShift - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, - mulExpRayHi] at hHi - simp only [Nat.reduceAdd, FormalYul.word] at hconvertOne - simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hsubHi hcleanupHiMinusOne + simp only [Nat.reduceAdd, FormalYul.word] at hHi simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hcleanupShift simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, ay, absTree, - signTree, scaleShiftTree, scaleClzBias, mulExpRayHi] at hOrGuard + signTree, scaleShiftTree, scaleClzBias] at hOrGuard simp only [Nat.reduceAdd, FormalYul.word, yulName_constant_ARITHMETIC_OVERFLOW] at hoverflow simp only [Nat.reduceAdd, FormalYul.word] at hconvu simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_panic] at hpanic + have hhiMinusOne : evmSub mulExpRayHi 1 = 86989971160273136331862631243 := by + norm_num [evmSub, mulExpRayHi, u256, WORD_MOD] have hguardUnfold : evmOr - (evmSgt x (evmSub 86989971160273136331862631244 1)) + (evmSgt x 86989971160273136331862631243) (evmSlt (evmSub (evmAdd @@ -157,7 +148,7 @@ theorem call_fun_mulExpRay_revert_direct (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) 2) = 1 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, - scaleClzBias, mulExpRayHi] using hguard + scaleClzBias, hhiMinusOne] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -168,7 +159,7 @@ theorem call_fun_mulExpRay_revert_direct hguardUnfold, hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleClzBias, hwrapS, hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, - hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, + hHi, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hoverflow, hconvu, hpanic, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, @@ -176,7 +167,7 @@ theorem call_fun_mulExpRay_revert_direct Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, uint256_ofNat_sgt_eq_word_evmSgt, - scaleClzBias, hclean] + hclean] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay` forwards the revert. -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 7ca6a84fd..0890f82d8 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -65,7 +65,7 @@ theorem call_fun_mulExpRay_direct call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) (shared := shared) (hlookup := hlookup) have hscaleClzBias := - call_constant__SCALE_CLZ_BIAS_direct (fuel := fuel + extra) (extra := 2023) + call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2060) (shared := shared) (hlookup := hlookup) have hwrapS := call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) @@ -90,53 +90,46 @@ theorem call_fun_mulExpRay_direct call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2084) (shared := shared) (hlookup := hlookup) have hHi := - call_constant__MUL_EXP_RAY_HI_direct (fuel := fuel + extra) (extra := 2000) + call_convert_MUL_EXP_RAY_HI_MINUS_ONE_to_int256_direct + (fuel := fuel + extra) (extra := 2037) (shared := shared) (hlookup := hlookup) - have hconvertOne := - call_convert_1_to_int256_direct (fuel := fuel + extra) (extra := 2036) - (shared := shared) (hlookup := hlookup) - have hsubHi := - call_wrapping_sub_t_int256_direct (x := mulExpRayHi) (y := 1) - (fuel := fuel + extra) (extra := 2078) (shared := shared) (hlookup := hlookup) - have hcleanupHiMinusOne := - call_cleanup_t_int256_direct (v := evmSub mulExpRayHi 1) - (fuel := fuel + extra) (extra := 2135) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2133) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2135) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2029) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2031) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2127) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2129) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct - (a := evmSgt x (evmSub mulExpRayHi 1)) + (a := evmSgt x 86989971160273136331862631243) (b := evmSlt shift 2) - (fuel := fuel + extra) (extra := 2070) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2072) (shared := shared) (hlookup := hlookup) have hscaleShift := call_shift_left_t_uint256_t_uint256_direct (value := ay) (bits := s) - (fuel := fuel + extra) (extra := 1960) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 1962) (shared := shared) (hlookup := hlookup) have hconvertShiftOut := - call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2017) + call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2019) (shared := shared) (hlookup := hlookup) have hZM := - call_constant__MUL_EXP_RAY_ZERO_MAX_direct (fuel := fuel + extra) (extra := 1976) + call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct + (fuel := fuel + extra) (extra := 2017) (shared := shared) (hlookup := hlookup) have hkernel := call_fun__expRayKernel_direct (x := x) (k := k) (scale := scale) (shift := shift) - (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1435) + (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1436) (shared := shared) (hlookup := hlookup) have hconvertInt256 := call_convert_uint256_to_int256_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 2010) (shared := shared) (hlookup := hlookup) + (extra := 2011) (shared := shared) (hlookup := hlookup) have hconvertNarrow := call_convert_int256_to_int128_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 2009) (shared := shared) (hlookup := hlookup) + (extra := 2010) (shared := shared) (hlookup := hlookup) simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__SCALE_CLZ_BIAS] at hscaleClzBias + simp only [Nat.reduceAdd, FormalYul.word] at hscaleClzBias simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree] at hshrAy @@ -147,22 +140,18 @@ theorem call_fun_mulExpRay_direct simp only [Nat.reduceAdd, FormalYul.word, k, kTree, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hwrapShift - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_HI, - mulExpRayHi] at hHi - simp only [Nat.reduceAdd, FormalYul.word] at hconvertOne - simp only [Nat.reduceAdd, FormalYul.word, mulExpRayHi] at hsubHi hcleanupHiMinusOne + simp only [Nat.reduceAdd, FormalYul.word] at hHi simp only [Nat.reduceAdd, FormalYul.word] at hcleanupXForHi simp only [Nat.reduceAdd, FormalYul.word] at hconvertTwo simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hcleanupShift simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_or, k, kTree, shift, s, ay, absTree, - signTree, scaleShiftTree, scaleClzBias, mulExpRayHi] at hOrGuard + signTree, scaleShiftTree, scaleClzBias] at hOrGuard simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hscaleShift simp only [Nat.reduceAdd, FormalYul.word, shift, k, kTree, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hconvertShiftOut - simp only [Nat.reduceAdd, FormalYul.word, yulName_constant__MUL_EXP_RAY_ZERO_MAX, - mulExpRayZeroMax] at hZM + simp only [Nat.reduceAdd, FormalYul.word, mulExpRayZeroMax] at hZM simp only [Nat.reduceAdd, FormalYul.word, k, kTree, scale, shift, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias, mulExpRayZeroMax, evmShl_one_c0] at hkernel simp only [Nat.reduceAdd, FormalYul.word, @@ -172,9 +161,11 @@ theorem call_fun_mulExpRay_direct ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, todShift, marginWord, scaleClzBias, mulExpRayZeroMax] at hconvertInt256 hconvertNarrow + have hhiMinusOne : evmSub mulExpRayHi 1 = 86989971160273136331862631243 := by + norm_num [evmSub, mulExpRayHi, u256, WORD_MOD] have hguardUnfold : evmOr - (evmSgt x (evmSub 86989971160273136331862631244 1)) + (evmSgt x 86989971160273136331862631243) (evmSlt (evmSub (evmAdd @@ -183,7 +174,7 @@ theorem call_fun_mulExpRay_direct (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) 2) = 0 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, - scaleClzBias, mulExpRayHi] using hguard + scaleClzBias, hhiMinusOne] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -196,7 +187,7 @@ theorem call_fun_mulExpRay_direct hguardUnfold, hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleClzBias, hwrapS, hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, - hHi, hconvertOne, hsubHi, hcleanupHiMinusOne, hcleanupXForHi, + hHi, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hscaleShift, hconvertShiftOut, hZM, hkernel, hconvertInt256, hconvertNarrow, FormalYul.Preservation.uint256_ofNat_lt_eq_word_evmLt, diff --git a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean index 22169ddb3..e7f2e358c 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Revert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Revert.lean @@ -78,11 +78,8 @@ theorem call_fun_expRayToWad_revert_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hconstHi := - call_constant__EXP_RAY_TO_WAD_HI_direct (fuel := fuel + extra) (extra := 832) - (shared := shared) (hlookup := hlookup) - have hcleanupHi := - call_cleanup_t_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) - (extra := 967) (shared := shared) (hlookup := hlookup) + call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) + (fuel := fuel + extra) (extra := 867) (shared := shared) (hlookup := hlookup) have hcleanup := call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 965) (shared := shared) (hlookup := hlookup) @@ -92,7 +89,7 @@ theorem call_fun_expRayToWad_revert_direct have hpanic := call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 384) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hconvu hpanic + simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanup hconvu hpanic simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -105,7 +102,7 @@ theorem call_fun_expRayToWad_revert_direct (shared := shared) (hlookup := hlookup), call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 826) (shared := shared) (hlookup := hlookup), - hcleanupHi, hcleanup, hconstHi, hconvu, hpanic] + hcleanup, hconstHi, hconvu, hpanic] set_option maxHeartbeats 8000000 in /-- The thin wrapper `fun_wrap_expRayToWad` just forwards to `fun_expRayToWad`, so it reverts diff --git a/formal/exp/ExpProof/ExpProof/Seam/Value.lean b/formal/exp/ExpProof/ExpProof/Seam/Value.lean index 7a67293f3..75a5c9376 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Value.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Value.lean @@ -82,11 +82,8 @@ theorem call_fun_expRayToWad_zero_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] have hconstHi := - call_constant__EXP_RAY_TO_WAD_HI_direct (fuel := fuel + extra) (extra := 732) - (shared := shared) (hlookup := hlookup) - have hcleanupHi := - call_cleanup_t_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) - (extra := 867) (shared := shared) (hlookup := hlookup) + call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) + (fuel := fuel + extra) (extra := 767) (shared := shared) (hlookup := hlookup) have hcleanup := call_cleanup_t_int256_direct (v := 0) (fuel := fuel + extra) (extra := 865) (shared := shared) (hlookup := hlookup) @@ -95,7 +92,7 @@ theorem call_fun_expRayToWad_zero_direct call_fun__octave_direct (x := 0) (fuel := fuel + extra) (extra := 767) (shared := shared) (hlookup := hlookup) have hscale := - call_constant__WAD_SCALE_direct (fuel := fuel + extra) (extra := 721) + call_convert_WAD_SCALE_to_uint256_direct (fuel := fuel + extra) (extra := 753) (shared := shared) (hlookup := hlookup) have hconv67 := call_convert_67_to_int256_direct (fuel := fuel + extra) (extra := 759) @@ -107,18 +104,18 @@ theorem call_fun_expRayToWad_zero_direct call_convert_int256_to_uint256_direct (v := evmSub 0x43 k) (fuel := fuel + extra) (extra := 755) (shared := shared) (hlookup := hlookup) have hzeroCutoff := - call_constant__WAD_ZERO_MAX_direct (fuel := fuel + extra) (extra := 714) + call_convert_WAD_ZERO_MAX_to_int256_direct (fuel := fuel + extra) (extra := 752) (shared := shared) (hlookup := hlookup) have hkernel := - call_fun__expRayKernel_zero_direct (fuel := fuel + extra) (extra := 173) + call_fun__expRayKernel_zero_direct (fuel := fuel + extra) (extra := 171) (shared := shared) (hlookup := hlookup) have hconvertInt256 := call_convert_uint256_to_int256_direct (v := 1000000000000000000) (fuel := fuel + extra) - (extra := 752) (shared := shared) (hlookup := hlookup) + (extra := 750) (shared := shared) (hlookup := hlookup) have hconvertNarrow := call_convert_int256_to_int128_direct (v := 1000000000000000000) (fuel := fuel + extra) - (extra := 751) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hoctave hscale hconv67 + (extra := 749) (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanup hoctave hscale hconv67 simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertInt256 hconvertNarrow simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, @@ -131,7 +128,7 @@ theorem call_fun_expRayToWad_zero_direct Finmap.lookup_insert, FormalYul.word, call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 876) (shared := shared) (hlookup := hlookup), - hconstHi, hcleanupHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, + hconstHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, hzeroCutoff, hkernel, hconvertInt256, hconvertNarrow, k] set_option maxHeartbeats 8000000 in @@ -578,11 +575,8 @@ theorem call_fun_expRayToWad_direct EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] let k := evmSar 0xc0 (evmAdd (evmShl 0xbf 1) (evmMul 0x724d54edbacbebbb95c52a0f60 x)) have hconstHi := - call_constant__EXP_RAY_TO_WAD_HI_direct (fuel := fuel + extra) (extra := 732) - (shared := shared) (hlookup := hlookup) - have hcleanupHi := - call_cleanup_t_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) (fuel := fuel + extra) - (extra := 867) (shared := shared) (hlookup := hlookup) + call_convert_44_to_int256_direct (v := 0x92b2f16cc66c5a4ae96e80d4) + (fuel := fuel + extra) (extra := 767) (shared := shared) (hlookup := hlookup) have hcleanup := call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 865) (shared := shared) (hlookup := hlookup) @@ -590,7 +584,7 @@ theorem call_fun_expRayToWad_direct call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 767) (shared := shared) (hlookup := hlookup) have hscale := - call_constant__WAD_SCALE_direct (fuel := fuel + extra) (extra := 721) + call_convert_WAD_SCALE_to_uint256_direct (fuel := fuel + extra) (extra := 753) (shared := shared) (hlookup := hlookup) have hconv67 := call_convert_67_to_int256_direct (fuel := fuel + extra) (extra := 759) @@ -602,13 +596,13 @@ theorem call_fun_expRayToWad_direct call_convert_int256_to_uint256_direct (v := evmSub 0x43 k) (fuel := fuel + extra) (extra := 755) (shared := shared) (hlookup := hlookup) have hzeroCutoff := - call_constant__WAD_ZERO_MAX_direct (fuel := fuel + extra) (extra := 714) + call_convert_WAD_ZERO_MAX_to_int256_direct (fuel := fuel + extra) (extra := 752) (shared := shared) (hlookup := hlookup) have hkernel := call_fun__expRayKernel_direct (x := x) (k := k) (scale := 0x6f05b59d3b2000000000000000000000) (shift := evmSub 0x43 k) (zeroCutoff := 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7) - (fuel := fuel + extra) (extra := 173) + (fuel := fuel + extra) (extra := 171) (shared := shared) (hlookup := hlookup) have hconvertInt256 := call_convert_uint256_to_int256_direct @@ -632,7 +626,7 @@ theorem call_fun_expRayToWad_direct let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) - (fuel := fuel + extra) (extra := 752) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 750) (shared := shared) (hlookup := hlookup) have hconvertNarrow := call_convert_int256_to_int128_direct (v := @@ -655,8 +649,8 @@ theorem call_fun_expRayToWad_direct let r1 := evmShr (evmSub 0x43 k) (evmSub r0 0x1) evmAdd (evmIszero x) (evmMul (evmSlt 0xffffffffffffffffffffffffffffffffffffffff7a143b87dbdabf5ee0a0efd7 x) r1)) - (fuel := fuel + extra) (extra := 751) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanupHi hcleanup hoctave hscale hconv67 + (fuel := fuel + extra) (extra := 749) (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hconstHi hcleanup hoctave hscale hconv67 simp only [Nat.reduceAdd, FormalYul.word] at hwrapSub hshift hzeroCutoff hkernel hconvertInt256 hconvertNarrow simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, @@ -670,7 +664,7 @@ theorem call_fun_expRayToWad_direct slt_thresh_lt hval, call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 876) (shared := shared) (hlookup := hlookup), - hconstHi, hcleanupHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, + hconstHi, hcleanup, hoctave, hscale, hconv67, hwrapSub, hshift, hzeroCutoff, hkernel, hconvertInt256, hconvertNarrow, k] simpa only [FormalYul.word] using hresultClean diff --git a/formal/yul/YulImporter.lean b/formal/yul/YulImporter.lean index 477b0a471..3bb59f83a 100644 --- a/formal/yul/YulImporter.lean +++ b/formal/yul/YulImporter.lean @@ -72,8 +72,6 @@ def functionPrefixes : ModelKind → List String "fun_wrap_expRayToWad_", "fun_wrap_mulExpRay_", "fun_expRayToWad_", "fun_mulExpRay_", "fun__octave_", "fun__expRayKernel_", - "constant__EXP_RAY_TO_WAD_HI_", "constant__SCALE_CLZ_BIAS_", - "constant__WAD_SCALE_", "constant__WAD_ZERO_MAX_", "constant_ARITHMETIC_OVERFLOW_", "fun_panic_", "fun_or_", "fun_clz_"] @@ -754,12 +752,6 @@ def generatedAliases (kind : ModelKind) (functions : List FunctionSource) : aliasByPrefix functions "fun_mulExpRay" "fun_mulExpRay_", aliasByPrefix functions "fun__octave" "fun__octave_", aliasByPrefix functions "fun__expRayKernel" "fun__expRayKernel_", - aliasByPrefix functions "constant__EXP_RAY_TO_WAD_HI" "constant__EXP_RAY_TO_WAD_HI_", - aliasByPrefix functions "constant__SCALE_CLZ_BIAS" "constant__SCALE_CLZ_BIAS_", - aliasByPrefix functions "constant__WAD_SCALE" "constant__WAD_SCALE_", - aliasByPrefix functions "constant__WAD_ZERO_MAX" "constant__WAD_ZERO_MAX_", - aliasByPrefix functions "constant__MUL_EXP_RAY_HI" "constant__MUL_EXP_RAY_HI_", - aliasByPrefix functions "constant__MUL_EXP_RAY_ZERO_MAX" "constant__MUL_EXP_RAY_ZERO_MAX_", aliasByPrefix functions "constant_ARITHMETIC_OVERFLOW" "constant_ARITHMETIC_OVERFLOW_", aliasByPrefix functions "fun_panic" "fun_panic_", aliasByPrefix functions "fun_or" "fun_or_", diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index de5b1240a..7d31e3e8c 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -8,35 +8,6 @@ import {Clz} from "./Clz.sol"; library Exp { using FastLogic for bool; - uint256 private constant _SCALE_CLZ_BIAS = 129; - // 10¹⁸ ⋅ 2⁶⁷ < 2¹²⁷: `expRayToWad`'s scale — the wad output basis carrying 67 bits of - // closing headroom. - uint256 private constant _WAD_SCALE = 0x6f05b59d3b2000000000000000000000; - // The least x whose octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, i.e. - // ⌈(66⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ 65.5⋅ln(2)⋅10²⁷ ≈ 45.40⋅10²⁷ (CINV is `_octave`'s - // reciprocal): at `expRayToWad`'s fixed headroom s = 67 the deficit envelope reaches one - // output unit at k = 66. - int256 private constant _EXP_RAY_TO_WAD_HI = 0x92b2f16cc66c5a4ae96e80d4; - // ⌊10²⁷ ⋅ ln(10⁻¹⁸)⌋: the greatest x with 10¹⁸⋅exp(x / 10²⁷) < 1. At or below it - // `expRayToWad` clamps to zero; the clamp consults only x, so it also discards the - // reduction garbage for x ≲ -2¹⁵¹ where `_octave`'s product wraps. - int256 private constant _WAD_ZERO_MAX = -41446531673892822312323846185; - // The least x whose octave count reaches 126, i.e. ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ - // 125.5⋅ln(2)⋅10²⁷ ≈ 87.00⋅10²⁷: the first octave past the deficit envelope at even the - // maximal scale headroom (s = 127, at y = 0). Within the wrap-free octave range the - // closing-shift guard already rejects these inputs; this comparison's irreducible role is - // the fence that keeps accepted x clear of the region (x ≳ 2¹⁵¹) where `_octave`'s product - // wraps and the octave word is garbage; without it, a wrapped word could pass the accuracy - // guard and the kernel would return an unflagged wrong value. - int256 private constant _MUL_EXP_RAY_HI = 86989971160273136331862631244; - // The least x whose octave count reaches -127, i.e. ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉ ≈ - // -127.5⋅ln(2)⋅10²⁷ ≈ -88.38⋅10²⁷. At or below it the kernel clamps `mulExpRay` to zero, - // which is within the bracket at every supported scale (2¹²⁷⋅exp(x/10²⁷) < 1); the - // clamp consults only x, so it also zeroes every accepted x inside `_octave`'s negative - // wraparound region (x ≲ -2¹⁵²). Above it, k ≥ -127 keeps the closing shift below 256 and - // the reduced argument on the certified domain. - int256 private constant _MUL_EXP_RAY_ZERO_MAX = -88376265521393026950697095485; - /// @notice Compute the natural exponential of a fixnum with 10**27 (ray) basis, returning the /// result as a fixnum with 10**18 (wad) basis. /// @dev Let E = 10¹⁸ ⋅ exp(x / 10²⁷) be the exact, infinite-precision result. This function @@ -47,15 +18,27 @@ library Exp { /// returns w. Reverts with `Panic(17)` when x is large enough to leave the supported range /// (x ≥ 0x92b2f16cc66c5a4ae96e80d4 ≈ 45.40 ⋅ 10²⁷, i.e. E ≳ 5.22 ⋅ 10³⁷). function expRayToWad(int256 x) internal pure returns (int128) { - // At this input the octave count k = round(x / (10²⁷⋅ln(2))) reaches 66, where the deficit - // envelope below exceeds 1ulp. - if (x >= _EXP_RAY_TO_WAD_HI) { + // This is ⌈(66⋅2¹⁹² - 2¹⁹¹) / CINV⌉, with CINV the Q192 reciprocal in `_octave`; here the + // octave count reaches 66 and the deficit envelope exceeds one output unit. + if (x >= 0x92b2f16cc66c5a4ae96e80d4) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } int256 k = _octave(x); unchecked { - return int128(int256(_expRayKernel(x, k, _WAD_SCALE, uint256(int256(67) - k), _WAD_ZERO_MAX))); + // 10¹⁸⋅2⁶⁷ carries 67 closing-headroom bits. The cutoff is + // ⌊10²⁷⋅ln(10⁻¹⁸)⌋, the greatest x with 10¹⁸⋅exp(x/10²⁷) < 1. + return int128( + int256( + _expRayKernel( + x, + k, + 0x6f05b59d3b2000000000000000000000, + uint256(int256(67) - k), + -41446531673892822312323846185 + ) + ) + ); } } @@ -95,22 +78,22 @@ library Exp { unchecked { // The top-bit term admits abs(type(int128).min) at s = 0 while leaving every smaller // magnitude's normalization unchanged. - uint256 s = Clz.clz(ay) - _SCALE_CLZ_BIAS + (ay >> 127); + uint256 s = Clz.clz(ay) - 129 + (ay >> 127); int256 k = _octave(x); int256 shift = int256(s) - k; // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: - // - x at or above the octave (k = 126) that exhausts the deficit envelope at even - // the maximal headroom, phrased as one signed comparison against the constant - // less one; its irreducible role is fencing accepted x away from `_octave`'s - // positive wraparound (see `_MUL_EXP_RAY_HI`); + // - x at or above ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉, where k = 126 exhausts the deficit + // envelope at even the maximal headroom, phrased as one signed comparison against + // the threshold less one; its irreducible role is fencing accepted x away from + // `_octave`'s positive wraparound; // - fewer than two bits of closing shift: the deficit envelope // (2993/1000 + margin)⋅2ᵏ⁻ˢ reaches one output unit at k > s - 2 (see the // kernel). This also rejects x = 0 when abs(y) leaves s ≤ 1, although the pinned // result would be exact. When `_octave`'s product wraps (x ≲ -2¹⁵²) its output // stands in for k, so those exponents revert or pass as the wrapped word falls; // the kernel's clamp zeroes every accepted one. - if ((x > _MUL_EXP_RAY_HI - 1).or(shift < 2)) { + if ((x > 86989971160273136331862631243).or(shift < 2)) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } @@ -119,7 +102,9 @@ library Exp { // (ay reaching 2ᴸ), the scale ay << s does not decrease while the closing shift shrinks // by one, so both effects raise the result. The x = 0 pin and zero clamp preserve order, // and sign reapplication mirrors the argument to y < 0. - uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), _MUL_EXP_RAY_ZERO_MAX); + // The cutoff is ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉. At or below it, + // 2¹²⁷⋅exp(x/10²⁷) < 1, so every supported magnitude clamps soundly to zero. + uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), -88376265521393026950697095485); // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale // is zero) in one branchless step: // m *= sgn(y) From 7a3b33c30ef135adccb533e4d35927d02e122db9 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 23:02:22 +0200 Subject: [PATCH 087/107] WIP: clean up AI comments --- src/vendor/Exp.sol | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 7d31e3e8c..b8b281592 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -42,28 +42,23 @@ library Exp { } } - /// @notice Compute y * exp(x / 10**27), with y's sign reapplied after magnitude evaluation. + /// @notice Compute trunc(y * exp(x / 10**27)) /// @dev Let A = abs(y) ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m - /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, except that when - /// A < 1 the lower bound pins m = 0. `mulExpRay(0, x) == 0` for every accepted x, and - /// `mulExpRay(y, 0) == y` exactly whenever 4⋅abs(y) ≤ 2¹²⁷ - 1 = - /// 170141183460469231731687303715884105727 (larger magnitudes leave fewer than two bits - /// of closing shift, so x = 0 reverts there). Among accepted inputs, the result is - /// monotone in x: nondecreasing if y ≥ 0 and nonincreasing if y < 0. For a fixed x, - /// among accepted inputs, the result is nondecreasing in y. Jointly, for accepted pairs - /// (y₁, x₁) and (y₂, x₂), the first result is no greater than the second when 0 ≤ y₁ ≤ y₂ - /// and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. - /// - /// Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ - /// (regardless of y), or when the octave word — `_octave`'s output, which is - /// round(x / (10²⁷⋅ln(2))) wherever its product does not wrap (|x| ≲ 2¹⁵²) — exceeds - /// s - 2, with 2ˢ the scale headroom above abs(y). The normalized scale is at most - /// 2¹²⁷; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. Within the - /// wrap-free range the accepted exponents form one interval that narrows as abs(y) - /// grows, and every accepted - /// x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap - /// boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to - /// zero, either of which is sound (A < 1 there at every supported magnitude). + /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, without + /// underflow. `mulExpRay(0, x) == 0` for every accepted x, and `mulExpRay(y, 0) == y` + /// exactly whenever 4⋅|y| ≤ 2¹²⁷ - 1 = 170141183460469231731687303715884105727. Among + /// accepted inputs, the result is monotone in x: nondecreasing if y ≥ 0 and nonincreasing + /// if y < 0. For a fixed x, among accepted inputs, the result is nondecreasing in + /// y. Jointly, for accepted pairs (y₁, x₁) and (y₂, x₂), the first result is no greater + /// than the second when 0 ≤ y₁ ≤ y₂ and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ + /// ≤ 0 ≤ y₂ for any exponents. + /// @dev Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ + /// (regardless of y), or when round(x / (10²⁷⋅ln(2))) exceeds s - 2, with 2ˢ the scale + /// headroom above abs(y); s = 0 at both maximal signed magnitudes and s = 127 at y = + /// 0. The accepted exponents form one interval that narrows as abs(y) grows, and every + /// accepted x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the + /// wrap boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp + /// to zero, either of which is sound (A < 1 there at every supported magnitude). function mulExpRay(int128 y, int256 x) internal pure returns (int128) { uint256 ay; uint256 sign; From be882e86c9f050dedb6a3b08670bdd8ade5f3aab Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 23:11:24 +0200 Subject: [PATCH 088/107] WIP: clean up AI comments --- src/vendor/Exp.sol | 54 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index b8b281592..13cf8b833 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -43,7 +43,7 @@ library Exp { } /// @notice Compute trunc(y * exp(x / 10**27)) - /// @dev Let A = abs(y) ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m + /// @dev Let A = |y| ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, without /// underflow. `mulExpRay(0, x) == 0` for every accepted x, and `mulExpRay(y, 0) == y` /// exactly whenever 4⋅|y| ≤ 2¹²⁷ - 1 = 170141183460469231731687303715884105727. Among @@ -54,16 +54,17 @@ library Exp { /// ≤ 0 ≤ y₂ for any exponents. /// @dev Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ /// (regardless of y), or when round(x / (10²⁷⋅ln(2))) exceeds s - 2, with 2ˢ the scale - /// headroom above abs(y); s = 0 at both maximal signed magnitudes and s = 127 at y = - /// 0. The accepted exponents form one interval that narrows as abs(y) grows, and every - /// accepted x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the - /// wrap boundary (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp - /// to zero, either of which is sound (A < 1 there at every supported magnitude). + /// headroom above |y|; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. The + /// accepted exponents form one interval that narrows as |y| grows, and every accepted x ≤ + /// -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap boundary + /// (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to zero, either + /// of which is sound (A < 1 there at every supported magnitude). function mulExpRay(int128 y, int256 x) internal pure returns (int128) { - uint256 ay; + // Split y into a sign mask and a magnitude: + // sign = y >> 255 + // ay = (y ^ sign) - sign uint256 sign; - // Split y into a sign mask and a magnitude without negating `type(int128).min`: - // sign = y >> 255; ay = (y ^ sign) - sign + uint256 ay; assembly ("memory-safe") { y := signextend(0x0f, y) sign := sar(0xff, y) @@ -78,30 +79,29 @@ library Exp { int256 k = _octave(x); int256 shift = int256(s) - k; // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: - // - x at or above ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉, where k = 126 exhausts the deficit + // * x at or above ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉, where k = 126 exhausts the deficit // envelope at even the maximal headroom, phrased as one signed comparison against - // the threshold less one; its irreducible role is fencing accepted x away from - // `_octave`'s positive wraparound; - // - fewer than two bits of closing shift: the deficit envelope - // (2993/1000 + margin)⋅2ᵏ⁻ˢ reaches one output unit at k > s - 2 (see the - // kernel). This also rejects x = 0 when abs(y) leaves s ≤ 1, although the pinned - // result would be exact. When `_octave`'s product wraps (x ≲ -2¹⁵²) its output - // stands in for k, so those exponents revert or pass as the wrapped word falls; - // the kernel's clamp zeroes every accepted one. + // the threshold less one. This fences accepted x away from `_octave`'s positive + // wraparound + // * fewer than 2 bits of closing shift: the deficit envelope (2993/1000 + margin)⋅2ᵏ⁻ˢ + // reaches one output unit at k > s - 2 (see the kernel). This also rejects x = 0 + // when |y| leaves s ≤ 1, although the pinned result would be exact. When `_octave`'s + // product wraps (x ≲ -2¹⁵²) its output stands in for k, so those exponents revert or + // pass as the wrapped word falls if ((x > 86989971160273136331862631243).or(shift < 2)) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } - // Monotonicity in y at a fixed accepted x: within one headroom class (fixed s) the - // magnitude is a composition of nondecreasing maps of ay. At a bit-length boundary - // (ay reaching 2ᴸ), the scale ay << s does not decrease while the closing shift shrinks - // by one, so both effects raise the result. The x = 0 pin and zero clamp preserve order, - // and sign reapplication mirrors the argument to y < 0. - // The cutoff is ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉. At or below it, - // 2¹²⁷⋅exp(x/10²⁷) < 1, so every supported magnitude clamps soundly to zero. + // Monotonicity in `y` at a fixed accepted `x`: within one headroom class (fixed s) the + // magnitude is a composition of nondecreasing maps of `ay`. At a bit-length boundary + // (ay reaching 2ᴸ), the scale `ay << s` does not decrease while the closing shift + // shrinks by one, so both effects raise the result. The x = 0 pin and zero-clamp + // preserve order, and sign reapplication mirrors the argument to y < 0. The cutoff is + // ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉. At or below it, 2¹²⁷⋅exp(x/10²⁷) < 1, so every supported + // magnitude clamps soundly to zero. uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), -88376265521393026950697095485); - // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale - // is zero) in one branchless step: + // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale is + // 0) in one branchless step: // m *= sgn(y) assembly ("memory-safe") { m := mul(m, or(sign, lt(0, ay))) From 0c65c4ad90bccc5ca9e59330160e252e09a92e79 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 23:15:20 +0200 Subject: [PATCH 089/107] WIP: clean up AI comments --- src/vendor/Exp.sol | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 13cf8b833..5443b5d24 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -60,20 +60,13 @@ library Exp { /// (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to zero, either /// of which is sound (A < 1 there at every supported magnitude). function mulExpRay(int128 y, int256 x) internal pure returns (int128) { - // Split y into a sign mask and a magnitude: - // sign = y >> 255 - // ay = (y ^ sign) - sign - uint256 sign; - uint256 ay; - assembly ("memory-safe") { - y := signextend(0x0f, y) - sign := sar(0xff, y) - ay := sub(xor(y, sign), sign) - } - unchecked { - // The top-bit term admits abs(type(int128).min) at s = 0 while leaving every smaller - // magnitude's normalization unchanged. + // Split y into a sign mask and a magnitude: + uint256 sign = uint256(int256(y) >> 255); + uint256 ay = (uint256(int256(y)) ^ sign) - sign; + + // The top-bit term admits ay = abs(type(int128).min) at s = 0 while leaving every + // smaller magnitude's normalization unchanged. uint256 s = Clz.clz(ay) - 129 + (ay >> 127); int256 k = _octave(x); @@ -102,7 +95,7 @@ library Exp { uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), -88376265521393026950697095485); // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale is // 0) in one branchless step: - // m *= sgn(y) + // m *= sign(y) assembly ("memory-safe") { m := mul(m, or(sign, lt(0, ay))) } From ab977356b66cb55d1ef9dd1d0d251e755871ffda Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Mon, 13 Jul 2026 23:51:22 +0200 Subject: [PATCH 090/107] WIP: clean up AI comments --- src/vendor/Exp.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 5443b5d24..f9ec04042 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -19,15 +19,15 @@ library Exp { /// (x ≥ 0x92b2f16cc66c5a4ae96e80d4 ≈ 45.40 ⋅ 10²⁷, i.e. E ≳ 5.22 ⋅ 10³⁷). function expRayToWad(int256 x) internal pure returns (int128) { // This is ⌈(66⋅2¹⁹² - 2¹⁹¹) / CINV⌉, with CINV the Q192 reciprocal in `_octave`; here the - // octave count reaches 66 and the deficit envelope exceeds one output unit. + // octave count reaches 66 and the deficit envelope exceeds 1ulp. if (x >= 0x92b2f16cc66c5a4ae96e80d4) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } int256 k = _octave(x); unchecked { - // 10¹⁸⋅2⁶⁷ carries 67 closing-headroom bits. The cutoff is - // ⌊10²⁷⋅ln(10⁻¹⁸)⌋, the greatest x with 10¹⁸⋅exp(x/10²⁷) < 1. + // 10¹⁸⋅2⁶⁷ carries 67 closing-headroom bits. The cutoff is ⌊10²⁷⋅ln(10⁻¹⁸)⌋, the + // greatest x with 10¹⁸⋅exp(x/10²⁷) < 1. return int128( int256( _expRayKernel( @@ -97,7 +97,7 @@ library Exp { // 0) in one branchless step: // m *= sign(y) assembly ("memory-safe") { - m := mul(m, or(sign, lt(0, ay))) + m := mul(or(lt(0x00, ay), sign), m) } return int128(int256(m)); } @@ -145,7 +145,7 @@ library Exp { // `exp(t) = (1 + tanh(t/2)) / (1 - tanh(t/2))`, so with the even/odd split N(t) = Ev(t²) + // t⋅Od(t²) the quotient N(t)/N(-t) is the reciprocal-symmetric rational that matches // `Od/Ev` to `tanh(√v/2)/√v` on v = t² ∈ [0, (ln(2)/2)²]. Ev(v) is degree 5 and Od(v) - // degree 4; in exact arithmetic this (4,5) form approximates exp to ≈135 bits, and the + // degree 4; in exact arithmetic this (5,4) form approximates exp to ≈135 bits, and the // integer coefficients realize ≈133 of them: each coefficient's low bits are chosen // jointly, after rounding at the staircase bases, to re-center the ten quantization // residuals, holding the realized envelope at ≤ 0.0075 ulp. Ev(v) is monic, so its leading From e9bd7aaa7f07db6b053ea7981661d301a8ab12b7 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 00:31:53 +0200 Subject: [PATCH 091/107] Tighten Ln downward margin Use the largest Q72 bias accepted by the 0.3383-ulp cap and keep the compiled runtime, floor bracket, error bound, and monotonicity proofs synchronized. Co-Authored-By: OpenAI Codex --- .../LnProof/LnProof/Error/Core/Assembly.lean | 14 +- .../LnProof/LnProof/Error/Core/BranchBn.lean | 12 +- .../LnProof/LnProof/Error/Core/BranchNeg.lean | 20 +- .../LnProof/LnProof/Error/Core/BranchPos.lean | 8 +- .../ln/LnProof/LnProof/Error/Core/C160.lean | 6 +- .../LnProof/LnProof/Error/Core/CutDefs.lean | 2 +- formal/ln/LnProof/LnProof/Floor/Assembly.lean | 244 +++++++++--------- formal/ln/LnProof/LnProof/Floor/CertDefs.lean | 7 +- formal/ln/LnProof/LnProof/Floor/Consts.lean | 3 +- formal/ln/LnProof/LnProof/Floor/Model.lean | 8 +- formal/ln/LnProof/LnProof/Floor/Spec.lean | 4 +- formal/ln/LnProof/LnProof/Model/Body.lean | 2 +- formal/ln/LnProof/LnProof/Mono/Octave.lean | 4 +- src/vendor/Ln.sol | 2 +- 14 files changed, 166 insertions(+), 170 deletions(-) diff --git a/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean b/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean index bb40efa72..2fd8b476d 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean @@ -32,9 +32,9 @@ attribute [local irreducible] lnWadToRayBody theorem r_nonneg_of_c160_v_nonneg {m : Nat} {R : Int} (hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516284764321243411868 < (R + 1) * 2 ^ 72) : + 116873961749927929127912020551516294209054209107914 < (R + 1) * 2 ^ 72) : 0 ≤ R := by rcases Int.lt_or_le R 0 with hneg | hnon · exfalso @@ -76,7 +76,7 @@ theorem lnWadToRayBody_error_bound_upper_c160 {x : Nat} (h1 : 1 ≤ x) (h2 : x < obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 have hbr2' : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516284764321243411868 < + ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by @@ -98,7 +98,7 @@ theorem lnWadToRayBody_error_bound_upper_c160 {x : Nat} (h1 : 1 ≤ x) (h2 : x < rw [hc160] at hw2 simpa only [Nat.sub_self, Nat.pow_zero, Nat.mul_one] using hw2 have hbr2c : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt 160 + 116873961749927929127912020551516284764321243411868 < + ln2kInt 160 + 116873961749927929127912020551516294209054209107914 < (R + 1) * 2 ^ 72 := by simpa [hc160] using hbr2' apply CutLogWadRayLtRational_of_strict (by omega) @@ -113,7 +113,7 @@ theorem lnWadToRayBody_error_bound_upper_c160 {x : Nat} (h1 : 1 ≤ x) (h2 : x < · have hmhi : mant x < MHI := hmant_hi have hV0I := v_c160_nonneg hmant_lo hmhi have hV0 : 0 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt 160 + 116873961749927929127912020551516284764321243411868 := by + ln2kInt 160 + 116873961749927929127912020551516294209054209107914 := by simpa [lnBiasI] using hV0I have hr0 := r_nonneg_of_c160_v_nonneg hV0 hbr2c unfold lnErrorBoundDen lnErrorBoundNum @@ -130,7 +130,7 @@ theorem lnWadToRayBody_error_bound_upper_neg_shift_nonneg {x : Nat} obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 have hbr2' : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516284764321243411868 < + ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by @@ -163,7 +163,7 @@ theorem lnWadToRayBody_error_bound_upper_neg_shift_rec_ge {x : Nat} obtain ⟨_hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr2 have hbrHi : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516284764321243411868 < + ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean index 426be3626..24fae95e5 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean @@ -24,7 +24,7 @@ attribute [local irreducible] lnWadToRayBody theorem bn_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r ≤ -2) (hmx : m = x * 2 ^ (c - 160)) : capUB (lnErrNegArg r) lnErrQ wadRayStrictDen (wadRayNum x) := by @@ -38,11 +38,11 @@ theorem bn_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := Int.mul_le_mul_of_nonneg_right (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (by decide : (0 : Int) ≤ 2 ^ 27) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -275,7 +275,7 @@ theorem bn_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem bn_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r ≤ -2) (hmx : m = x * 2 ^ (c - 160)) : capUB (lnErrNegArg r) lnErrQ wadRayStrictDen (wadRayNum x) := by @@ -289,11 +289,11 @@ theorem bn_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := Int.mul_le_mul_of_nonneg_right (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (by decide : (0 : Int) ≤ 2 ^ 27) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean index 0a8d05fe9..491f6fc75 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean @@ -25,9 +25,9 @@ attribute [local irreducible] lnWadToRayBody theorem lo_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by @@ -41,12 +41,12 @@ theorem lo_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h0 : 0 ≤ r * 2 ^ 72 := Int.mul_nonneg hr0 (by decide) have hg : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hrlo ⊢ + 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ generalize hgR : r * 2 ^ 72 = R at hrlo h0 omega exact Int.mul_nonneg hg (by decide) @@ -280,9 +280,9 @@ theorem lo_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem lo_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by @@ -296,12 +296,12 @@ theorem lo_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h0 : 0 ≤ r * 2 ^ 72 := Int.mul_nonneg hr0 (by decide) have hg : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hrlo ⊢ + 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ generalize hgR : r * 2 ^ 72 = R at hrlo h0 omega exact Int.mul_nonneg hg (by decide) diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean index 61a3ba905..3205f6407 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean @@ -382,7 +382,7 @@ theorem lo_ge_pos_exact_ge_residue {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : theorem lo_lt_pos_exact {m c x : Nat} {r : Int} (h1 : Sc - 45 ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c < 160) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516284764321243411868) + ln2kInt c + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hres : PosShiftResidueOk m c r) (hxm : x < (m + 1) * 2 ^ (160 - c)) : @@ -398,12 +398,12 @@ theorem lo_lt_pos_exact {m c x : Nat} {r : Int} (h1 : Sc - 45 ≤ m) (h2 : m < S have hX1 := x1_nonpos_ltF hmlo h2 have hVs := v_scale_pos (int256 (x1W (zWord m))) c (by omega : c ≤ 160) have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h0 : 0 ≤ r * 2 ^ 72 := Int.mul_nonneg hr0 (by decide) have hg : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hrlo ⊢ + 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ generalize hgR : r * 2 ^ 72 = R at hrlo h0 omega exact Int.mul_nonneg hg (by decide) diff --git a/formal/ln/LnProof/LnProof/Error/Core/C160.lean b/formal/ln/LnProof/LnProof/Error/Core/C160.lean index de6da4d65..2716df6e6 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/C160.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/C160.lean @@ -88,7 +88,7 @@ def c160R : Nat := Sc * (c160R0 * c160R1 * c160R2 * c160R3 * c160R4) theorem lo_ge_c160_exact {m x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hr0 : -1 ≤ r) (hmx : m ≤ x) (hxm : x < m + 1) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by have hx : x = m := by omega @@ -169,7 +169,7 @@ theorem lo_ge_c160_exact {m x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem lo_lt_c160_exact {m x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hmx : m ≤ x) (hxm : x < m + 1) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by have hx : x = m := by omega @@ -179,7 +179,7 @@ theorem lo_lt_c160_exact {m x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) omega have hV0I := v_c160_nonneg h1 hmhi have hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by simpa [lnBiasI] using hV0I have hr0 : -1 ≤ r := by rcases Int.lt_or_le r (-1) with hlt | hle diff --git a/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean b/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean index 18153506f..a39d14c0c 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean @@ -71,7 +71,7 @@ def twoPow72I : Int := 2 ^ 72 def twoPow99I : Int := 2 ^ 99 def lnPhaseScaleN : Nat := 1000000000000000000000000000 def lnPhaseScaleI : Int := 1000000000000000000000000000 -def lnBiasI : Int := 116873961749927929127912020551516284764321243411868 +def lnBiasI : Int := 116873961749927929127912020551516294209054209107914 def lnErrorHardMantissa : Nat := 39770979022059719714796403827 /-- First-order exact-wad budget with the common `10^18` and `2^99` factors diff --git a/formal/ln/LnProof/LnProof/Floor/Assembly.lean b/formal/ln/LnProof/LnProof/Floor/Assembly.lean index 38fb91881..263ff9b91 100644 --- a/formal/ln/LnProof/LnProof/Floor/Assembly.lean +++ b/formal/ln/LnProof/LnProof/Floor/Assembly.lean @@ -22,10 +22,10 @@ open LnYul Common.Poly Common.Exp LnFloor /-- `V·2^27` splits into the three cap exponents (positive binade shift). -/ theorem v_scale_pos (X1v : Int) (c : Nat) (hc : c ≤ 160) : (X1v * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = X1v * 1000000000000000000000000000 + ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) + - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by have hl : ln2kInt c = (LN2c : Int) * ((160 - c : Nat) : Int) := by unfold ln2kInt rw [if_pos hc] @@ -40,10 +40,10 @@ theorem v_scale_pos (X1v : Int) (c : Nat) (hc : c ≤ 160) : /-- `V·2^27` splits with the `ln 2` term on the other side (negative shift). -/ theorem v_scale_neg (X1v : Int) (c : Nat) (hc : 160 < c) : (X1v * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 + + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 + ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = X1v * 1000000000000000000000000000 + - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by have hl : ln2kInt c = -((LN2c : Int) * ((c - 160 : Nat) : Int)) := by unfold ln2kInt rw [if_neg (by omega)] @@ -70,7 +70,7 @@ theorem v_scale_neg (X1v : Int) (c : Nat) (hc : 160 < c) : theorem up_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hmx : m * 2 ^ (160 - c) ≤ x) : capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by @@ -85,13 +85,13 @@ theorem up_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 := by have hsc : r * 2 ^ 72 * 2 ^ 27 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := + ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := mul_le_mul_right_nonneg hr (by omega) rw [hVs] at hsc have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -200,7 +200,7 @@ strictness slack. -/ theorem lo_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hr0 : -1 ≤ r) (hxm : x < (m + 1) * 2 ^ (160 - c)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -216,14 +216,14 @@ theorem lo_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 + 2 ^ 99 ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) rw [hVs] at hsc have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -326,7 +326,7 @@ theorem lo_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem up_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by @@ -344,24 +344,24 @@ theorem up_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have hm := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) have h0 : 0 ≤ r * 2 ^ 72 * 2 ^ 27 := Int.mul_nonneg (Int.mul_nonneg hr0 (by omega)) (by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hm ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R27 at hm h0 clear cap1 cap1B hX1 hVs hX1n hBc hLc h1 h2 hmx hc hc2 hr hr0 omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hV0 hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -380,17 +380,17 @@ theorem up_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) BIASc * 2 ^ 27 - (c - 160) * (LN2c * 2 ^ 27) := by have hsc : r * 2 ^ 72 * 2 ^ 27 + ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) ≤ int256 (x1W (zWord m)) * 1000000000000000000000000000 + - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by have h := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgL : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = L at hVs ⊢ generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs ⊢ generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hVs h + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVs h omega have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -466,9 +466,9 @@ theorem up_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : -1 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -478,20 +478,20 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hVnn : -(2 ^ 99) ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h0 : -(2 ^ 72) ≤ r * 2 ^ 72 := by have := mul_le_mul_right_nonneg (show (-1 : Int) ≤ r from hr0) (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : r * 2 ^ 72 = T at this ⊢ omega have hg : -(2 ^ 72) ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hrlo ⊢ + 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ omega have := mul_le_mul_right_nonneg hg (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ have e : (-(2 ^ 72) : Int) * 2 ^ 27 = -(2 ^ 99) := by decide omega have hsplit : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + @@ -502,14 +502,14 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hVnn hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVnn hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -526,7 +526,7 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) BIASc * 2 ^ 27 + 2 ^ 99 - (c - 160) * (LN2c * 2 ^ 27) ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by @@ -537,14 +537,14 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs hVnn + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs hVnn generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -604,7 +604,7 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem up_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hmx : m * 2 ^ (160 - c) ≤ x) : capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by @@ -620,24 +620,24 @@ theorem up_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have hm := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) have h0 : 0 ≤ r * 2 ^ 72 * 2 ^ 27 := Int.mul_nonneg (Int.mul_nonneg hr0 (by omega)) (by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hm ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R27 at hm h0 clear cap1 hsum hX1 hVs hX1n hBc hLc h1 h2 hmx hc hc1 hr hr0 omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hV0 hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -657,7 +657,7 @@ theorem up_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 - (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 := by have hsc : r * 2 ^ 72 * 2 ^ 27 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := + ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := mul_le_mul_right_nonneg hr (by omega) have e99 : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] @@ -665,14 +665,14 @@ theorem up_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -741,9 +741,9 @@ theorem up_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : -1 ≤ r) (hxm : x < (m + 1) * 2 ^ (160 - c)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -752,20 +752,20 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc have hVnn : -(2 ^ 99) ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h0 : -(2 ^ 72) ≤ r * 2 ^ 72 := by have := mul_le_mul_right_nonneg (show (-1 : Int) ≤ r from hr0) (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : r * 2 ^ 72 = T at this ⊢ omega have hg : -(2 ^ 72) ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hrlo ⊢ + 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ omega have := mul_le_mul_right_nonneg hg (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ have e : (-(2 ^ 72) : Int) * 2 ^ 27 = -(2 ^ 99) := by decide omega have hsplit : (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 + 2 ^ 99 = @@ -775,14 +775,14 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hVnn hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVnn hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -802,7 +802,7 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by @@ -813,14 +813,14 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs hVnn + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs hVnn generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -911,7 +911,7 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem up_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : 0 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by @@ -928,24 +928,24 @@ theorem up_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have hm := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) have h0 : 0 ≤ r * 2 ^ 72 * 2 ^ 27 := Int.mul_nonneg (Int.mul_nonneg hr0 (by omega)) (by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hm ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R27 at hm h0 clear cap1 hb hX1 hVs hX1n hBc hLc h1 h2 hmx hc hc2 hr hr0 omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hV0 hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -967,7 +967,7 @@ theorem up_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) BIASc * 2 ^ 27 - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + (c - 160) * (LN2c * 2 ^ 27)) := by have hsc : r * 2 ^ 72 * 2 ^ 27 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := + ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := mul_le_mul_right_nonneg hr (by omega) have e99 : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] @@ -975,14 +975,14 @@ theorem up_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1043,9 +1043,9 @@ theorem up_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr0 : -1 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -1055,20 +1055,20 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hVnn : -(2 ^ 99) ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h0 : -(2 ^ 72) ≤ r * 2 ^ 72 := by have := mul_le_mul_right_nonneg (show (-1 : Int) ≤ r from hr0) (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : r * 2 ^ 72 = T at this ⊢ omega have hg : -(2 ^ 72) ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hrlo ⊢ + 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ omega have := mul_le_mul_right_nonneg hg (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ have e : (-(2 ^ 72) : Int) * 2 ^ 27 = -(2 ^ 99) := by decide omega have hsplit : BIASc * 2 ^ 27 + 2 ^ 99 = @@ -1080,14 +1080,14 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hVnn hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVnn hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1108,7 +1108,7 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (c - 160) * (LN2c * 2 ^ 27)) ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by @@ -1119,14 +1119,14 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs hVnn + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs hVnn generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1199,9 +1199,9 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r < 0) (hmx : m * 2 ^ (160 - c) ≤ x) : capLB ((-r).toNat * 2 ^ 99) QS (10 ^ 18) x := by @@ -1217,19 +1217,19 @@ theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hV0 : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ 0 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ 0 := by have hm := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ 0 from by + 116873961749927929127912020551516294209054209107914 ≤ 0 from by generalize hgV' : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hr ⊢ + 116873961749927929127912020551516294209054209107914 = V at hr ⊢ generalize hgR : (r + 1) * 2 ^ 72 = R at hr have : R ≤ 0 := by rw [← hgR] @@ -1239,11 +1239,11 @@ theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) omega omega) (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hm ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ clear cap1 hb hX1 hVs hrlo hr h1 h2 hmx hX1n hBc hLc omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hV0 hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1262,10 +1262,10 @@ theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hple : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27) ≤ (-r).toNat * 2 ^ 99 := by have hsc : (-r) * 2 ^ 72 * 2 ^ 27 ≥ -(int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516284764321243411868) * 2 ^ 27 := by + ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by have h := mul_le_mul_right_nonneg hrlo (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) = V at h ⊢ + 116873961749927929127912020551516294209054209107914) = V at h ⊢ generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R at h have e1 : (-r) * 2 ^ 72 * 2 ^ 27 = -(r * 2 ^ 72 * 2 ^ 27) := by rw [Int.neg_mul, Int.neg_mul] @@ -1278,20 +1278,20 @@ theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hnegV : -(int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = -((int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27) := + 116873961749927929127912020551516294209054209107914) * 2 ^ 27) := Int.neg_mul _ _ rw [hnegV] at hsc generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1362,9 +1362,9 @@ theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem an_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r < 0) (hmx : m = x * 2 ^ (c - 160)) : capLB ((-r).toNat * 2 ^ 99) QS (10 ^ 18) x := by @@ -1383,32 +1383,32 @@ theorem an_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hV0 : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ 0 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ 0 := by have hVle : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ 0 := by + 116873961749927929127912020551516294209054209107914 ≤ 0 := by have hR : (r + 1) * 2 ^ 72 ≤ 0 := by have hle : r + 1 ≤ 0 := by omega have := mul_le_mul_right_nonneg hle (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : (r + 1) * 2 ^ 72 = T at this ⊢ omega generalize hgV' : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hr ⊢ + 116873961749927929127912020551516294209054209107914 = V at hr ⊢ clear cap1 hb hsum hX1 hVs hrlo h1 h2 hmx hX1n hBc hLc omega have := mul_le_mul_right_nonneg hVle (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ clear cap1 hb hsum hX1 hVs hrlo hr h1 h2 hmx hX1n hBc hLc omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hV0 hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1428,7 +1428,7 @@ theorem an_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1438,7 +1438,7 @@ theorem an_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] rw [er] at hsc generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1495,9 +1495,9 @@ theorem an_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem an_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) + 116873961749927929127912020551516294209054209107914) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r < 0) (hmx : m = x * 2 ^ (c - 160)) : capLB ((-r).toNat * 2 ^ 99) QS (10 ^ 18) x := by @@ -1512,32 +1512,32 @@ theorem an_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl have hV0 : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ 0 := by + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ 0 := by have hVle : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ 0 := by + 116873961749927929127912020551516294209054209107914 ≤ 0 := by have hR : (r + 1) * 2 ^ 72 ≤ 0 := by have hle : r + 1 ≤ 0 := by omega have := mul_le_mul_right_nonneg hle (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : (r + 1) * 2 ^ 72 = T at this ⊢ omega generalize hgV' : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 = V at hr ⊢ + 116873961749927929127912020551516294209054209107914 = V at hr ⊢ clear cap1 hsum hX1 hVs hrlo h1 h2 hmx hX1n hBc hLc omega have := mul_le_mul_right_nonneg hVle (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ clear cap1 hsum hX1 hVs hrlo hr h1 h2 hmx hX1n hBc hLc omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hV0 hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1559,7 +1559,7 @@ theorem an_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1569,7 +1569,7 @@ theorem an_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] rw [er] at hsc generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hsc hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1658,7 +1658,7 @@ theorem budgetB_fold {m k : Nat} (hm : 2 ^ 95 ≤ m) (hk : k ≤ 159) : theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r + 2 ≤ 0) (hxm : x < (m + 1) * 2 ^ (160 - c)) : capUB ((-(r + 2)).toNat * 2 ^ 99) QS (10 ^ 18 * (10 ^ 31 - 10)) (x * 10 ^ 31) := by @@ -1668,11 +1668,11 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc -- the exponent gap: -V·2^27 ≥ (|r+2|+1)·2^99 + 2^27 have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (show (0 : Int) ≤ 2 ^ 27 by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -1687,7 +1687,7 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1699,7 +1699,7 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) generalize hgT : (r + 1) * 2 ^ 99 = T at this ⊢ omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1722,14 +1722,14 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1818,7 +1818,7 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r + 2 ≤ 0) (hmx : m = x * 2 ^ (c - 160)) : capUB ((-(r + 2)).toNat * 2 ^ 99) QS (10 ^ 18 * (10 ^ 31 - 10)) (x * 10 ^ 31) := by @@ -1828,11 +1828,11 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (show (0 : Int) ≤ 2 ^ 27 by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -1849,7 +1849,7 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1861,7 +1861,7 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) generalize hgT : (r + 1) * 2 ^ 99 = T at this ⊢ omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1882,14 +1882,14 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1950,7 +1950,7 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) (hrneg : r + 2 ≤ 0) (hmx : m = x * 2 ^ (c - 160)) : capUB ((-(r + 2)).toNat * 2 ^ 99) QS (10 ^ 18 * (10 ^ 31 - 10)) (x * 10 ^ 31) := by @@ -1960,11 +1960,11 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 ≤ + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (show (0 : Int) ≤ 2 ^ 27 by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -1980,7 +1980,7 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1992,7 +1992,7 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) generalize hgT : (r + 1) * 2 ^ 99 = T at this ⊢ omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -2015,14 +2015,14 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516284764321243411868 * 2 ^ 27 := by + 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ diff --git a/formal/ln/LnProof/LnProof/Floor/CertDefs.lean b/formal/ln/LnProof/LnProof/Floor/CertDefs.lean index 2a3023eea..b392235e2 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertDefs.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertDefs.lean @@ -62,12 +62,9 @@ def ltTD2b : List Int := polyScale (2 ^ 99) ltTD2 def KF : Int := 1124000727777607680000 def KF1 : Int := 25852016738884976640000 -/-- Never-overshoot margin floor (the +form certs `certGeUp`, `certLtUp`): the -bias keeps at least this much of its `1e-31`-unit margin. Lowered to `3382` -when the bias is raised. -/ +/-- Never-overshoot margin floor for the +form certificates. -/ def EUN : Int := 3382 -/-- Not-too-low margin ceiling (the −form certs `certGeLo`, `certLtLo`): an upper -bound on the bias margin. Unchanged by raising the bias. -/ +/-- Not-too-low margin ceiling for the −form certificates. -/ def EUNl : Int := 3385 def EUD : Int := 10 ^ 31 diff --git a/formal/ln/LnProof/LnProof/Floor/Consts.lean b/formal/ln/LnProof/LnProof/Floor/Consts.lean index 515e8bb3a..ef3aabe01 100644 --- a/formal/ln/LnProof/LnProof/Floor/Consts.lean +++ b/formal/ln/LnProof/LnProof/Floor/Consts.lean @@ -31,8 +31,7 @@ theorem cap2U : capUB (LN2c * 2 ^ 27) QS (2 * (10 ^ 40 + 1)) (10 ^ 40) := by theorem cap2L : capLB (LN2c * 2 ^ 27) QS (2 * (10 ^ 40 - 1)) (10 ^ 40) := ⟨40, by decide⟩ -/-- `e^(BIASc 2^27 / QS) ≤ (S/10^18)(1 - 3.386e-28)`: the bias keeps almost -all of its 0.33866-ulp margin through the cap. -/ +/-- `e^(BIASc 2^27 / QS) ≤ (S/10^18)(1 - 3.383e-28)`. -/ theorem capBU : capUB (BIASc * 2 ^ 27) QS (Sc * (10 ^ 31 - 3383)) (10 ^ 18 * 10 ^ 31) := by refine capUB_of_partial (K := 130) QS_pos (by decide) ?_ diff --git a/formal/ln/LnProof/LnProof/Floor/Model.lean b/formal/ln/LnProof/LnProof/Floor/Model.lean index d4cf00dfb..94a8c01fc 100644 --- a/formal/ln/LnProof/LnProof/Floor/Model.lean +++ b/formal/ln/LnProof/LnProof/Floor/Model.lean @@ -44,7 +44,7 @@ theorem r4_value {m : Nat} (h1 : MLO ≤ m) (h2 : m < MHI) {c : Nat} (hc : c < 2 int256 (evmAdd (evmAdd (evmMul (x1W (zWord m)) Kc) (evmMul LN2c (evmSub 160 c))) BIASc) = int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by have hB := r1_bound h1 h2 have hr1w : x1W (zWord m) < 2 ^ 256 := by unfold x1W; exact evmSdiv_lt _ _ have hW := ln2k_bound hc @@ -66,7 +66,7 @@ theorem r4_value {m : Nat} (h1 : MLO ≤ m) (h2 : m < MHI) {c : Nat} (hc : c < 2 (by rw [e2]; clear e2 hKc hKlt; simp only [ipow255]; omega) (by rw [e2]; clear e2 hKc hKlt; simp only [ipow255]; omega) have hBIlt : BIASc < 2 ^ 256 := by simp only [BIASc]; omega - have hBI : int256 BIASc = (116873961749927929127912020551516284764321243411868 : Int) := by + have hBI : int256 BIASc = (116873961749927929127912020551516294209054209107914 : Int) := by rw [toInt_of_lt (by simp only [BIASc]; omega)] simp only [BIASc] omega @@ -108,9 +108,9 @@ theorem lnWadToRayBody_floor_bracket {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 1000000000000000000) : int256 (lnWadToRayBody x) * 4722366482869645213696 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + ln2kInt (evmClz x) + - 116873961749927929127912020551516284764321243411868 ∧ + 116873961749927929127912020551516294209054209107914 ∧ int256 (x1W (zWord (mant x))) * 7450580596923828125 + ln2kInt (evmClz x) + - 116873961749927929127912020551516284764321243411868 < + 116873961749927929127912020551516294209054209107914 < int256 (lnWadToRayBody x) * 4722366482869645213696 + 4722366482869645213696 := by have hx256 : x < 2 ^ 256 := by omega diff --git a/formal/ln/LnProof/LnProof/Floor/Spec.lean b/formal/ln/LnProof/LnProof/Floor/Spec.lean index 78e8fa2a3..963a0ec13 100644 --- a/formal/ln/LnProof/LnProof/Floor/Spec.lean +++ b/formal/ln/LnProof/LnProof/Floor/Spec.lean @@ -158,7 +158,7 @@ theorem clz_bounds {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : positive, so the output cannot be negative. -/ theorem v_pos_ge_pos {m c : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : c ≤ 160) : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516284764321243411868 := by + 116873961749927929127912020551516294209054209107914 := by have hX1 := x1_nonneg_geF h1 h2 have hx0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 := Int.mul_nonneg hX1 (by omega) @@ -195,7 +195,7 @@ theorem lnWadToRayBody_floor {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : · obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 have hbr2' : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516284764321243411868 < + ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by diff --git a/formal/ln/LnProof/LnProof/Model/Body.lean b/formal/ln/LnProof/LnProof/Model/Body.lean index 64c07a48a..91bceac8f 100644 --- a/formal/ln/LnProof/LnProof/Model/Body.lean +++ b/formal/ln/LnProof/LnProof/Model/Body.lean @@ -32,7 +32,7 @@ def Q2c : Nat := 53722296096946541673620529149 def Q1c : Nat := 16613772931382142257332678212554 def Kc : Nat := 7450580596923828125 def LN2c : Nat := 3273295013171879848905889459134067659407864468560 -def BIASc : Nat := 116873961749927929127912020551516284764321243411868 +def BIASc : Nat := 116873961749927929127912020551516294209054209107914 /-- Largest |z| over the mantissa domain. -/ def Zc : Nat := 217494458298375249691265569565 diff --git a/formal/ln/LnProof/LnProof/Mono/Octave.lean b/formal/ln/LnProof/LnProof/Mono/Octave.lean index 9509543ad..a140d98ed 100644 --- a/formal/ln/LnProof/LnProof/Mono/Octave.lean +++ b/formal/ln/LnProof/LnProof/Mono/Octave.lean @@ -45,7 +45,7 @@ theorem lnWadToRayBody_eq_tail {x : Nat} (_h : x < 2 ^ 256) : rw [evmMul_comm 7450580596923828125, evmAdd_comm (evmMul 3273295013171879848905889459134067659407864468560 (evmSub 160 (evmClz x))), - evmAdd_comm 116873961749927929127912020551516284764321243411868] + evmAdd_comm 116873961749927929127912020551516294209054209107914] /-- Per-`clz` bracket on the signed value of `ln2 * k`; `[-LN2c*95, LN2c*160]`. -/ def ln2kOK (c : Nat) : Bool := @@ -140,7 +140,7 @@ theorem affine_tail_mono {a a' W : Nat} (by rw [e2']; clear e2 e2' e3 hKc hKlt; simp only [ipow255]; omega) (by rw [e2']; clear e2 e2' e3 hKc hKlt; simp only [ipow255]; omega) have hBIlt : BIASc < 2 ^ 256 := by simp only [BIASc]; omega - have hBI : int256 BIASc = (116873961749927929127912020551516284764321243411868 : Int) := by + have hBI : int256 BIASc = (116873961749927929127912020551516294209054209107914 : Int) := by rw [toInt_of_lt (by simp only [BIASc]; omega)] simp only [BIASc] omega diff --git a/src/vendor/Ln.sol b/src/vendor/Ln.sol index f0066d14f..581f55a0a 100644 --- a/src/vendor/Ln.sol +++ b/src/vendor/Ln.sol @@ -117,7 +117,7 @@ library Ln { // Add ⌊(ln(s/2⁹⁵) + 95⋅ln(2) - 18⋅ln(10)) ⋅ 10²⁷ ⋅ 2⁷²⌋ minus the one-sided error // margin described above. - r := add(0x4ff7e9b32826a6aec97ea1e6974062cc1e985b359c, r) + r := add(0x4ff7e9b32826a6aec97ea1e69740845a0dd9c667ca, r) // Q72 → integer ray result (`SAR` floors). r := sar(0x48, r) From 42858c2273ad8e92a477f89ce4229f5e4647616d Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 07:05:25 +0000 Subject: [PATCH 092/107] Add Up UniV3 fork to RobinHood (fork ID 40) --- CHANGELOG.md | 1 + UNISWAPV3_FORKS.md | 2 ++ src/chains/RobinHood/Common.sol | 5 +++++ src/core/univ3forks/Up.sol | 6 ++++++ 4 files changed, 14 insertions(+) create mode 100644 src/core/univ3forks/Up.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 9331553d3..110b19463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Add SquadSwapV3 UniV3 fork to Bnb with fork ID 38 * Add PrjxV3 (Project X) UniV3 fork to HyperEVM with fork ID 39 +* Add Up UniV3 fork to RobinHood with fork ID 40 * Add `BRIDGE_ERC20_TO_ACROSS` and `BRIDGE_NATIVE_TO_ACROSS` to Base * Fix several bugs reported by Nethermind * SettlerMetaTxn now reverts on short actions diff --git a/UNISWAPV3_FORKS.md b/UNISWAPV3_FORKS.md index 40b3ba28b..24b8464b5 100644 --- a/UNISWAPV3_FORKS.md +++ b/UNISWAPV3_FORKS.md @@ -49,3 +49,5 @@ 38. SquadSwapV3 39. PrjxV3 (Project X) + + 40. Up diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index 75489a07c..c3c963e00 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -25,6 +25,7 @@ import { pancakeSwapV3ForkId, IPancakeSwapV3Callback } from "../../core/univ3forks/PancakeSwapV3.sol"; +import {upFactory, upInitHash, upForkId} from "../../core/univ3forks/Up.sol"; import {ROBINHOOD_POOL_MANAGER} from "../../core/UniswapV4Addresses.sol"; import {FastLogic} from "../../utils/FastLogic.sol"; @@ -87,6 +88,10 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3 factory = pancakeSwapV3Factory; initHash = pancakeSwapV3InitHash; callbackSelector = uint32(IPancakeSwapV3Callback.pancakeV3SwapCallback.selector); + } else if (forkId == upForkId) { + factory = upFactory; + initHash = upInitHash; + callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); } else { revertUnknownForkId(forkId); } diff --git a/src/core/univ3forks/Up.sol b/src/core/univ3forks/Up.sol new file mode 100644 index 000000000..780434a61 --- /dev/null +++ b/src/core/univ3forks/Up.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +address constant upFactory = 0x1ac9dB4a2608ba45D6127B1737949b51Bb54B7F3; +bytes32 constant upInitHash = 0x2a16e4a055eca1bf027a534adf1626e905f61a8fd28055bbcc8787c573c76e33; // ERC1167 proxy +uint8 constant upForkId = 40; From b9d8986bef952315dfb311565282422ba9bd71ae Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 09:38:52 +0200 Subject: [PATCH 093/107] WIP: clean up AI comments --- src/vendor/Exp.sol | 66 ++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index f9ec04042..bc0cedf24 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -42,23 +42,23 @@ library Exp { } } - /// @notice Compute trunc(y * exp(x / 10**27)) + /// @notice Compute `trunc(y * exp(x / 10**27))` with up to 1ulp of error, towards zero /// @dev Let A = |y| ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m - /// with 0 ≤ m ≤ A and A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, without + /// with 0 ≤ m ≤ A ∧ A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, without /// underflow. `mulExpRay(0, x) == 0` for every accepted x, and `mulExpRay(y, 0) == y` /// exactly whenever 4⋅|y| ≤ 2¹²⁷ - 1 = 170141183460469231731687303715884105727. Among - /// accepted inputs, the result is monotone in x: nondecreasing if y ≥ 0 and nonincreasing - /// if y < 0. For a fixed x, among accepted inputs, the result is nondecreasing in - /// y. Jointly, for accepted pairs (y₁, x₁) and (y₂, x₂), the first result is no greater - /// than the second when 0 ≤ y₁ ≤ y₂ and x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 and x₂ ≤ x₁, and when y₁ - /// ≤ 0 ≤ y₂ for any exponents. + /// accepted inputs, the result is monotone in `x`: nondecreasing if y ≥ 0 and + /// nonincreasing if y < 0. For a fixed `x`, among accepted inputs, the result is + /// nondecreasing in `y`. Jointly, for accepted (y₁, x₁, r₁ = mulExpRay(y₁, x₁)) and (y₂, + /// x₂, r₂ = mulExpRay(y₂, x₂)), r₁ ≤ r₂ when 0 ≤ y₁ ≤ y₂ ∧ x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 ∧ x₂ + /// ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. /// @dev Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ /// (regardless of y), or when round(x / (10²⁷⋅ln(2))) exceeds s - 2, with 2ˢ the scale /// headroom above |y|; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. The /// accepted exponents form one interval that narrows as |y| grows, and every accepted x ≤ /// -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap boundary - /// (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such x revert or clamp to zero, either - /// of which is sound (A < 1 there at every supported magnitude). + /// (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such `x` revert or clamp to zero, (A < + /// 1 there at every supported magnitude). function mulExpRay(int128 y, int256 x) internal pure returns (int128) { unchecked { // Split y into a sign mask and a magnitude: @@ -73,14 +73,12 @@ library Exp { int256 shift = int256(s) - k; // Reject inputs whose two-unit magnitude bracket the kernel cannot deliver: // * x at or above ⌈(126⋅2¹⁹² - 2¹⁹¹) / CINV⌉, where k = 126 exhausts the deficit - // envelope at even the maximal headroom, phrased as one signed comparison against - // the threshold less one. This fences accepted x away from `_octave`'s positive - // wraparound + // envelope at even the maximal headroom. This fences accepted x away from + // `_octave`'s positive wraparound // * fewer than 2 bits of closing shift: the deficit envelope (2993/1000 + margin)⋅2ᵏ⁻ˢ - // reaches one output unit at k > s - 2 (see the kernel). This also rejects x = 0 - // when |y| leaves s ≤ 1, although the pinned result would be exact. When `_octave`'s - // product wraps (x ≲ -2¹⁵²) its output stands in for k, so those exponents revert or - // pass as the wrapped word falls + // reaches 1ulp at k > s - 2 (see the kernel). When `_octave`'s product wraps (x ≲ + // -2¹⁵²) its output stands in for k, so those exponents revert or pass as the + // wrapped word falls if ((x > 86989971160273136331862631243).or(shift < 2)) { Panic.panic(Panic.ARITHMETIC_OVERFLOW); } @@ -93,8 +91,7 @@ library Exp { // ⌈(-127⋅2¹⁹² - 2¹⁹¹) / CINV⌉. At or below it, 2¹²⁷⋅exp(x/10²⁷) < 1, so every supported // magnitude clamps soundly to zero. uint256 m = _expRayKernel(x, k, ay << s, uint256(shift), -88376265521393026950697095485); - // Reapply y's sign and collapse y = 0 (whose kernel output is unspecified; the scale is - // 0) in one branchless step: + // Reapply `y`'s sign and collapse y = 0 (kernel output is unspecified; scale is 0): // m *= sign(y) assembly ("memory-safe") { m := mul(or(lt(0x00, ay), sign), m) @@ -104,8 +101,6 @@ library Exp { } function _octave(int256 x) private pure returns (int256 k) { - // Round to the nearest octave: - // k = round(x / (10**27 * ln(2))) assembly ("memory-safe") { // k = round(x / (10²⁷⋅ln(2))), half-open. CINV = round(2¹⁹² / (10²⁷⋅ln(2))); the +2¹⁹¹ // and `sar(192, …)` round to nearest with ties resolved toward +∞. @@ -113,19 +108,19 @@ library Exp { } } - /// @dev The rational polynomial approximation kernel, shared by `expRayToWad` - /// (scale = 10¹⁸⋅2⁶⁷, shift = 67 - k) and `mulExpRay` (scale = abs(y)⋅2ˢ, shift = s - k). - /// The caller must maintain: - /// - `k == _octave(x)` and `scale ≤ 2¹²⁷`: the margin and deficit budgets below - /// hold throughout this range, and smaller scales only shrink them; - /// - `scale == base << s` for the caller's magnitude base, with `shift == s - k`; - /// - for every accepted x with `zeroCutoff` < x and x ≠ 0: `shift ≥ 2` (the deficit - /// envelope reaches one output unit below that), `_octave`'s product must not wrap - /// (x ≲ 2¹⁵¹), and `shift < 256`. At x = 0 the result is exact for any shift; - /// - for every x ≤ `zeroCutoff`: base⋅exp(x / 10²⁷) < 1, so the clamped-to-zero result - /// satisfies the bracket. The clamp consults only x, so `_octave` wraparound garbage - /// (x ≲ -2¹⁵¹) in k, t, and shift is discarded. - /// When `scale == 0` the returned value is unspecified and the caller must discard it. + /// @dev The rational polynomial approximation kernel, shared by `expRayToWad` (scale = + /// 10¹⁸⋅2⁶⁷, shift = 67 - k) and `mulExpRay` (scale = |y|⋅2ˢ, shift = s - k). + /// @dev The caller must maintain: + /// * `k == _octave(x)` and `scale <= 2**127`: the margin and deficit budgets below hold + /// throughout this range, and smaller scales only shrink them + /// * `scale == base << s` for the caller's magnitude `base`, with `shift == s - k` + /// * for every accepted `x` with `zeroCutoff < x` and `x != 0`: `shift >= 2` (the deficit + /// envelope reaches 1ulp below that), `_octave`'s product must not wrap (x ≲ 2¹⁵¹), and + /// `shift < 256`. At x = 0 the result is exact for any shift + /// * for every x ≤ zeroCutoff: base⋅exp(x / 10²⁷) < 1, so the clamped-to-zero result + /// satisfies the bracket. The clamp consults only `x`, so `_octave` wraparound garbage + /// (x ≲ -2¹⁵¹) in `k`, `t`, and `shift` is discarded + /// @dev When `scale == 0` the returned value is unspecified and the caller must discard it. function _expRayKernel(int256 x, int256 k, uint256 scale, uint256 shift, int256 zeroCutoff) private pure @@ -152,8 +147,9 @@ library Exp { // stage is just an add. // // Mixed fixed-point bases (a staircase): each coefficient takes the widest basis fitting - // its chosen byte width. A coefficient followed by more multiplies by v tolerates a shorter - // basis. Each renormalizing shift lands a value directly at the basis its consumer needs. + // its chosen byte width. A coefficient followed by more multiplies by `v` tolerates a + // shorter basis. Each renormalizing shift lands a value directly at the basis its consumer + // needs. // v = t²: Q123 the widest basis whose monic-stage product stays inside 256 bits, so // Ev(v)'s leading stage consumes v with no renormalizing shift. t's Q129 basis (|t| // ≤ ln(2)/2) means that pre-reduction t² fits 256 bits. From 9807c96ef2c2d2bf7f4762553838d65d39fc0913 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 09:59:36 +0200 Subject: [PATCH 094/107] WIP: clean up AI comments --- src/vendor/Exp.sol | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index bc0cedf24..b25bf8644 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -51,7 +51,7 @@ library Exp { /// nonincreasing if y < 0. For a fixed `x`, among accepted inputs, the result is /// nondecreasing in `y`. Jointly, for accepted (y₁, x₁, r₁ = mulExpRay(y₁, x₁)) and (y₂, /// x₂, r₂ = mulExpRay(y₂, x₂)), r₁ ≤ r₂ when 0 ≤ y₁ ≤ y₂ ∧ x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 ∧ x₂ - /// ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any exponents. + /// ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any (x₁, x₂). /// @dev Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ /// (regardless of y), or when round(x / (10²⁷⋅ln(2))) exceeds s - 2, with 2ˢ the scale /// headroom above |y|; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. The @@ -61,7 +61,7 @@ library Exp { /// 1 there at every supported magnitude). function mulExpRay(int128 y, int256 x) internal pure returns (int128) { unchecked { - // Split y into a sign mask and a magnitude: + // Split `y` into a sign mask and a magnitude uint256 sign = uint256(int256(y) >> 255); uint256 ay = (uint256(int256(y)) ^ sign) - sign; @@ -185,16 +185,15 @@ library Exp { // (the K27 coefficient-grid term is below 2⁻¹³³ over |x| < 2⁹⁷ and the k⋅ln(2) // grid term below 2⁻²²⁸), lifting ê by ≤ 0.0055242717280199026 (≈ √2/256). // - // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid unit - // is worth 2ᵏ⁻ˢ ulp (1 ulp = 1 in the caller's magnitude). Because scale ≤ 2¹²⁷ and - // Δ < 1/2, its image scale⋅Δ/2¹²⁶ is below one grid unit. The margin dominates the image: - // 0x01, worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so - // the pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is - // certified directly on the output grid, piecewise over the 32 domain pieces: q ≥ - // scale⋅exp(t) - 2993/1000. The `DIV` floor costs one unit at any scale. On the positive - // half, the integer-rational carry is certified over the same 32 pieces used for the - // denominator floors, while the scale-dependent 2⁻¹³² and reduced-argument terms remain - // exact. On the negative half, the one-grain direction and reduced-argument bound shrink. + // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid + // unit is worth 2ᵏ⁻ˢ ulp (1ulp = 1 in the caller's magnitude). Because scale ≤ 2¹²⁷ and Δ < + // 1/2, its image scale⋅Δ/2¹²⁶ is below one grid unit. The margin dominates the image: 0x01, + // worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so the + // pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is certified + // directly on the output grid. The `DIV` floor costs one unit at any scale. On the positive + // half, the integer-rational carry is certified similarly, while the scale-dependent 2⁻¹³² + // and reduced-argument terms remain exact. On the negative half, the one-grain direction + // and reduced-argument bound shrink. // // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2993/1000 + margin)⋅2ᵏ⁻ˢ. The caller // keeps k ≤ s - 2, where this is < 1, so the floor returns ⌊E⌋ or ⌊E⌋ - 1. For the wad @@ -204,16 +203,15 @@ library Exp { // ⌊10²⁷⋅ln(2)/2⌋, matching `lnWadToRay`'s image over [1/√2, √2). // // Monotonicity: one unit step in x multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves the - // pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live - // scale is at least 2¹²⁶ > 10¹⁸⋅2⁶⁶). The error - // terms above confine the accumulator to a band of width scale⋅Δ/2¹²⁶ + 2993/1000 < 4.0 grid - // units just below E's grid image at every octave (in grid units the band is k-independent; - // an octave seam rescales E and the band together), so the per-step gain exceeds any - // adverse swing within the band by more than 9 orders of magnitude, and the pre-floor - // accumulator strictly increases at every step; its floor is non-decreasing. The zeroing - // clamp and the +1 pin at x = 0 preserve order: below C the result is 0 while just above it - // ⌊E⌋ ≥ 0, and the adjacent runtime values around x = 0 bracket the pinned scale-point - // value. + // pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live scale + // is at least 2¹²⁶ > 10¹⁸⋅2⁶⁶). The error terms above confine the accumulator to a band of + // width scale⋅Δ/2¹²⁶ + 2993/1000 < 4.0 grid units just below E's grid image at every octave + // (in grid units the band is k-independent; an octave seam rescales E and the band + // together), so the per-step gain exceeds any adverse swing within the band by more than 9 + // orders of magnitude, and the pre-floor accumulator strictly increases at every step; its + // floor is non-decreasing. The zeroing clamp and the +1 pin at x = 0 preserve order: below + // C the result is 0 while just above it ⌊E⌋ ≥ 0, and the adjacent runtime values around x = + // 0 bracket the pinned scale-point value. assembly ("memory-safe") { // t in Q129. K27 = round(2²³⁵ / 10²⁷) and LN2 = round(ln(2) ⋅ 2²³⁵). Subtracting k⋅LN2 // from K27⋅x at the Q235 product basis (so the k⋅ln(2) rounding error stays below From c3eca0209abf21a7f1b07534b0ff0274920bb0c3 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 10:05:54 +0200 Subject: [PATCH 095/107] Finished: clean up AI comments --- src/vendor/Exp.sol | 48 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index b25bf8644..50ceaabd9 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -166,31 +166,29 @@ library Exp { // // Error budget. Let ê = N/D be the exact value of the integer rational (N = Ev + t⋅Od, D = // Ev - t⋅Od; the closing `DIV` floor is counted on the output grid below) and write its - // excess over exp(t) as Δ = (ê - exp(t))⋅2¹²⁶ (in Q126 units, one unit = 2⁻¹²⁶). The - // budget bounds Δ ≤ 0.4668745981919039833, the sum - // of four one-sided contributions: + // excess over exp(t) as Δ = (ê - exp(t))⋅2¹²⁶ (in Q126 units, one unit = 2⁻¹²⁶). The budget + // bounds Δ ≤ 0.4668745981919039833, the sum of four one-sided contributions: // integer Horner truncation: the shared Ev cancels to first order in the quotient, so - // its truncation barely perturbs ê; this jitter stays ≤ 0.1102011232081646123. + // its truncation barely perturbs ê; this jitter stays ≤ 0.1103. // argument granularity: v carries t² on the Q123 grid, and its floor only lowers the - // polynomials' shared argument, which lifts ê on the t > 0 half by - // ≤ 0.3290521163436398582: one v-grain moves the quotient by - // 2t⋅(Od⋅ΔEv - Ev⋅ΔOd)/(D⋅D′), whose one-signed numerator is maximal at each - // piece's upper edge and whose denominator, analyzed over 32 domain pieces, has + // polynomials' shared argument, which lifts ê on the t > 0 half by ≤ 0.3291: one + // v-grain moves the quotient by 2t⋅(Od⋅ΔEv - Ev⋅ΔOd)/(D⋅D′), whose one-signed + // numerator is maximal at each piece's upper edge and whose denominator has // pointwise supremum ≈ 0.3287 at t = ln(2)/2. The t < 0 direction is budgeted on // the under side. // rational `Mp`-factor (the dyadic gap between the reciprocal-symmetric form and exp): - // ≤ 0.0220970869120796102 (its supremum is √2⋅2¹²⁶/(2¹³²-1)). - // reduced-argument gap: the Q129 floor of t only pushes ê downward (that direction is + // ≤ 0.0221 (its supremum is √2⋅2¹²⁶/(2¹³²-1)). + // reduced-argument gap: the Q129 floor of `t` only pushes ê downward (that direction is // budgeted on the under side); the over side is the K27/LN2 constant-grid residue - // (the K27 coefficient-grid term is below 2⁻¹³³ over |x| < 2⁹⁷ and the k⋅ln(2) - // grid term below 2⁻²²⁸), lifting ê by ≤ 0.0055242717280199026 (≈ √2/256). + // (the K27 coefficient-grid term is below 2⁻¹³³ over |x| < 2⁹⁷ and the k⋅ln(2) grid + // term below 2⁻²²⁸), lifting ê by ≤ 0.0055 (≈ √2/256). // // The quotient `r` carries the scaled rational on a dynamic output grid, where one grid // unit is worth 2ᵏ⁻ˢ ulp (1ulp = 1 in the caller's magnitude). Because scale ≤ 2¹²⁷ and Δ < // 1/2, its image scale⋅Δ/2¹²⁶ is below one grid unit. The margin dominates the image: 0x01, // worth 0.25 ulp at the supported edge. The `DIV` floor only lowers the quotient, so the // pre-floor accumulator A = q - margin satisfies A⋅2ᵏ⁻ˢ ≤ E. The under side is certified - // directly on the output grid. The `DIV` floor costs one unit at any scale. On the positive + // directly on the output grid. The `DIV` floor costs 1ulp at any scale. On the positive // half, the integer-rational carry is certified similarly, while the scale-dependent 2⁻¹³² // and reduced-argument terms remain exact. On the negative half, the one-grain direction // and reduced-argument bound shrink. @@ -202,16 +200,16 @@ library Exp { // leaves, so the round trip floors to ⌊E⌋. The k = 0 band is exactly [-H, H] with H = // ⌊10²⁷⋅ln(2)/2⌋, matching `lnWadToRay`'s image over [1/√2, √2). // - // Monotonicity: one unit step in x multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves the - // pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live scale - // is at least 2¹²⁶ > 10¹⁸⋅2⁶⁶). The error terms above confine the accumulator to a band of - // width scale⋅Δ/2¹²⁶ + 2993/1000 < 4.0 grid units just below E's grid image at every octave - // (in grid units the band is k-independent; an octave seam rescales E and the band - // together), so the per-step gain exceeds any adverse swing within the band by more than 9 - // orders of magnitude, and the pre-floor accumulator strictly increases at every step; its - // floor is non-decreasing. The zeroing clamp and the +1 pin at x = 0 preserve order: below - // C the result is 0 while just above it ⌊E⌋ ≥ 0, and the adjacent runtime values around x = - // 0 bracket the pinned scale-point value. + // Monotonicity: one unit step in `x` multiplies E by exp(10⁻²⁷) ≈ 1 + 10⁻²⁷, which moves + // the pre-floor accumulator by at least scale⋅10⁻²⁷/√2 > 5.2⋅10¹⁰ grid units (every live + // scale is at least 2¹²⁶ > 10¹⁸⋅2⁶⁶). The error terms above confine the accumulator to a + // band of width scale⋅Δ/2¹²⁶ + 2993/1000 < 4.0 grid units just below E's grid image at + // every octave (in grid units the band is k-independent; an octave seam rescales E and the + // band together), so the per-step gain exceeds any adverse swing within the band by more + // than 9 orders of magnitude, and the pre-floor accumulator strictly increases at every + // step; its floor is non-decreasing. The zeroing clamp and the +1 pin at x = 0 preserve + // order: below C the result is 0 while just above it ⌊E⌋ ≥ 0, and the adjacent runtime + // values around x = 0 bracket the pinned scale-point value. assembly ("memory-safe") { // t in Q129. K27 = round(2²³⁵ / 10²⁷) and LN2 = round(ln(2) ⋅ 2²³⁵). Subtracting k⋅LN2 // from K27⋅x at the Q235 product basis (so the k⋅ln(2) rounding error stays below @@ -256,8 +254,8 @@ library Exp { // the denominator > 0. r := div(mul(scale, add(ev, tod)), sub(ev, tod)) - // Less the one-sided margin (0x01; see the budget above), then floored by - // `shr(shift, …)` which folds in the 2ᵏ octave scaling. + // Less the one-sided margin (0x01; see the budget above), then floored by `shr(shift, + // …)` which folds in the 2ᵏ octave scaling. r := shr(shift, sub(r, 0x01)) // Zero results whose exact magnitude is below one output unit. For very negative x, From df10d57f4687aaace29ea5a23222735c719fb284 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 15:23:51 +0200 Subject: [PATCH 096/107] Fix Exp proof and formal dependency caching Model the generated mulExpRay conversion sequence in the Lean seam proof. Cache complete Lake package trees and reuse them across formal proof builds. Co-Authored-By: OpenAI Codex --- .github/actions/build-cbrt-proof/action.yml | 5 - .../actions/build-cbrt512-proof/action.yml | 5 - .github/actions/build-exp-proof/action.yml | 5 - .github/actions/build-ln-proof/action.yml | 5 - .github/actions/build-sqrt-proof/action.yml | 5 - .../actions/build-sqrt512-proof/action.yml | 5 - .github/actions/setup-formal/action.yml | 16 +- formal/README.md | 11 +- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 218 ++++++++++++++++++ .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 75 +++--- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 101 +++++--- 11 files changed, 342 insertions(+), 109 deletions(-) diff --git a/.github/actions/build-cbrt-proof/action.yml b/.github/actions/build-cbrt-proof/action.yml index a5da365a0..6e9f35d50 100644 --- a/.github/actions/build-cbrt-proof/action.yml +++ b/.github/actions/build-cbrt-proof/action.yml @@ -20,11 +20,6 @@ runs: python3 formal/python/cbrt/generate_cbrt_cert.py \ --output formal/cbrt/CbrtProof/CbrtProof/FiniteCert.lean - - name: Fetch Cbrt proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/cbrt/CbrtProof - - name: Build Cbrt proof package shell: bash working-directory: formal/cbrt/CbrtProof diff --git a/.github/actions/build-cbrt512-proof/action.yml b/.github/actions/build-cbrt512-proof/action.yml index 386bc39ad..599216ebb 100644 --- a/.github/actions/build-cbrt512-proof/action.yml +++ b/.github/actions/build-cbrt512-proof/action.yml @@ -17,11 +17,6 @@ runs: formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Yul.lean \ 0.8.34 - - name: Fetch Cbrt512 proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/cbrt/Cbrt512Proof - - name: Build Cbrt512 proof package shell: bash working-directory: formal/cbrt/Cbrt512Proof diff --git a/.github/actions/build-exp-proof/action.yml b/.github/actions/build-exp-proof/action.yml index 03167f068..e5a1edab4 100644 --- a/.github/actions/build-exp-proof/action.yml +++ b/.github/actions/build-exp-proof/action.yml @@ -17,11 +17,6 @@ runs: formal/exp/ExpProof/ExpProof/ExpYul.lean \ 0.8.34 - - name: Fetch Exp proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/exp/ExpProof - - name: Generate Exp certificates uses: ./.github/actions/check-generated-sources with: diff --git a/.github/actions/build-ln-proof/action.yml b/.github/actions/build-ln-proof/action.yml index 2e0dde4a0..24a18faec 100644 --- a/.github/actions/build-ln-proof/action.yml +++ b/.github/actions/build-ln-proof/action.yml @@ -20,11 +20,6 @@ runs: formal/ln/LnProof/LnProof/LnYul.lean \ 0.8.34 - - name: Fetch Ln proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/ln/LnProof - - name: Generate Ln certificates uses: ./.github/actions/check-generated-sources with: diff --git a/.github/actions/build-sqrt-proof/action.yml b/.github/actions/build-sqrt-proof/action.yml index 80455c6b4..8844736b5 100644 --- a/.github/actions/build-sqrt-proof/action.yml +++ b/.github/actions/build-sqrt-proof/action.yml @@ -20,11 +20,6 @@ runs: python3 formal/python/sqrt/generate_sqrt_cert.py \ --output formal/sqrt/SqrtProof/SqrtProof/FiniteCert.lean - - name: Fetch Sqrt proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/sqrt/SqrtProof - - name: Build Sqrt proof package shell: bash working-directory: formal/sqrt/SqrtProof diff --git a/.github/actions/build-sqrt512-proof/action.yml b/.github/actions/build-sqrt512-proof/action.yml index 89e1dc72f..1f0eeb0d5 100644 --- a/.github/actions/build-sqrt512-proof/action.yml +++ b/.github/actions/build-sqrt512-proof/action.yml @@ -17,11 +17,6 @@ runs: formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512Yul.lean \ 0.8.34 - - name: Fetch Sqrt512 proof dependency cache - uses: ./.github/actions/fetch-lean-cache - with: - working-directory: formal/sqrt/Sqrt512Proof - - name: Build Sqrt512 proof package shell: bash working-directory: formal/sqrt/Sqrt512Proof diff --git a/.github/actions/setup-formal/action.yml b/.github/actions/setup-formal/action.yml index 594c33b9c..51bb37e7c 100644 --- a/.github/actions/setup-formal/action.yml +++ b/.github/actions/setup-formal/action.yml @@ -1,8 +1,9 @@ name: Set up the formal toolchain description: >- Install Foundry and the pinned Lean toolchain, restore separate dependency - and formal-tool caches, install solc 0.8.34, fetch the Yul importer's - Mathlib cache, and build the Yul importer. Proof packages cache separately. + and formal-tool caches, install solc 0.8.34, materialize the Yul importer's + Mathlib dependencies after a cache miss, and build the Yul importer. Proof + packages cache separately. inputs: lean-toolchain-files: @@ -57,18 +58,18 @@ runs: if: inputs.publish == 'true' uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: - path: formal/yul/.lake/packages/*/.lake/build - key: ${{ runner.os }}-formal-dependencies-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} + path: formal/yul/.lake/packages + key: ${{ runner.os }}-formal-packages-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} restore-keys: | - ${{ runner.os }}-formal-dependencies- + ${{ runner.os }}-formal-packages- - name: Restore formal dependency cache without publishing id: dependency-restore if: inputs.publish != 'true' uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: - path: formal/yul/.lake/packages/*/.lake/build - key: ${{ runner.os }}-formal-dependencies-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} + path: formal/yul/.lake/packages + key: ${{ runner.os }}-formal-packages-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} - name: Require exact formal dependency cache from its publisher if: inputs.publish != 'true' && steps.dependency-restore.outputs.cache-hit != 'true' @@ -114,6 +115,7 @@ runs: FOUNDRY_SOLC_VERSION: 0.8.34 - name: Fetch Mathlib cache + if: steps.dependency-cache.outputs.cache-hit != 'true' && steps.dependency-restore.outputs.cache-hit != 'true' uses: ./.github/actions/fetch-lean-cache with: working-directory: formal/yul diff --git a/formal/README.md b/formal/README.md index 9f607accd..ddac2e302 100644 --- a/formal/README.md +++ b/formal/README.md @@ -92,11 +92,12 @@ branches, and subsequent jobs trust the formal-tool artifact it publishes. ## CI and cache boundaries -The unified formal workflow keeps the large Mathlib and Lake dependency outputs -in a cache keyed only by the pinned toolchain and dependency manifests. A -separate formal-tool cache contains `FormalYul` and EVMYulLean outputs and is -keyed by their sources as well as that dependency configuration. Every proof -package has a separate cache. A package's exact key includes: +The unified formal workflow keeps the complete Mathlib and Lake package trees, +including their repository metadata and build outputs, in a cache keyed only +by the pinned toolchain and dependency manifests. A separate formal-tool cache +contains `FormalYul` and EVMYulLean outputs and is keyed by their sources as +well as that dependency configuration. Every proof package has a separate +cache. A package's exact key includes: - the source hash of each direct dependency; - its Lake configuration and Lean sources; diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 7eb8a4b32..9bc1833a5 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -172,6 +172,75 @@ theorem call_identity_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +theorem call_convert_int128_to_int256_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) + (hclean : EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word v) = + FormalYul.word v) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word v] + (.some "convert_t_int128_to_t_int256") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_int128_to_t_int256] + simp only [yulFunction_convert_t_int128_to_t_int256, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp only [FormalYul.word] at hclean + have h1 := + call_cleanup_t_int128_direct (v := v) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := v) (fuel := fuel + extra) (extra := 94) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_int256_direct (v := v) (fuel := fuel + extra) (extra := 96) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word v) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word, hclean] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + +theorem call_cleanup_t_rational_255_direct + (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 20)) [FormalYul.word v] + (.some "cleanup_t_rational_255_by_1") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word v]) := by + rw [show fuel + (extra + 20) = (fuel + extra) + 20 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_cleanup_t_rational_255_by_1] + simp only [yulFunction_cleanup_t_rational_255_by_1, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + theorem call_cleanup_t_rational_44_direct (v fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = @@ -724,6 +793,72 @@ theorem call_cleanup_t_uint8_127_direct EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, Finmap.lookup_insert, FormalYul.word] +theorem call_cleanup_t_uint8_255_direct + (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + 20) [FormalYul.word 0xff] (.some "cleanup_t_uint8") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0xff]) := by + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, lookup_cleanup_t_uint8] + simp only [yulFunction_cleanup_t_uint8, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word] + +theorem call_convert_255_to_uint8_direct + (fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 120)) [FormalYul.word 0xff] + (.some "convert_t_rational_255_by_1_to_t_uint8") + (.some yulContract) (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word 0xff]) := by + rw [show fuel + (extra + 120) = (fuel + extra) + 120 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_convert_t_rational_255_by_1_to_t_uint8] + simp only [yulFunction_convert_t_rational_255_by_1_to_t_uint8, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have h1 := + call_cleanup_t_rational_255_direct (v := 0xff) (fuel := fuel + extra) (extra := 92) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h2 := + call_identity_direct (v := 0xff) (fuel := fuel + extra) (extra := 94) + (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + have h3 := + call_cleanup_t_uint8_255_direct (fuel := fuel + extra + 96) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore)) + (hlookup := hlookup) + simp [FormalYul.word] at h1 h2 h3 + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, h1, h2, h3] + /-- `convert_t_rational_17_by_1_to_t_uint8(0x11) = 0x11` (= `cleanup_t_uint8(identity(cleanup_…(0x11)))`). -/ theorem call_convert_17_to_uint8_17_direct (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -1320,6 +1455,89 @@ theorem call_shift_right_unsigned_dynamic_direct Finmap.lookup_insert, FormalYul.word, FormalYul.Preservation.uint256_ofNat_shiftRight_eq_word_evmShr] +theorem call_shift_right_signed_dynamic_direct + (bits value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 40)) [FormalYul.word bits, FormalYul.word value] + (.some "shift_right_signed_dynamic") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmSar bits value)]) := by + rw [show fuel + (extra + 40) = (fuel + extra) + 40 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_shift_right_signed_dynamic] + simp only [yulFunction_shift_right_signed_dynamic, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + simp +decide [EvmYul.Yul.execPrimCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, + Common.Word.uint256_ofNat_sar_eq_word_evmSar] + +theorem call_shift_right_t_int256_t_uint8_255_direct + (value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) + (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = + some (FormalYul.accountFor yulContract)) : + EvmYul.Yul.call (fuel + (extra + 180)) [FormalYul.word value, FormalYul.word 0xff] + (.some "shift_right_t_int256_t_uint8") (.some yulContract) + (EvmYul.Yul.State.Ok shared store) = + .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmSar 0xff value)]) := by + rw [show fuel + (extra + 180) = (fuel + extra) + 180 by omega] + rw [EvmYul.Yul.call.eq_def] + simp only [hlookup, Option.getD_some, yulContract_functions, + lookup_shift_right_t_int256_t_uint8] + simp only [yulFunction_shift_right_t_int256_t_uint8, + FormalYul.Preservation.functionDefinition_params_def, + FormalYul.Preservation.functionDefinition_rets_def, + FormalYul.Preservation.functionDefinition_body_def, + EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] + have hbits := + call_cleanup_t_uint8_255_direct (fuel := fuel + extra + 156) (shared := shared) + (store := Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore))) + (hlookup := hlookup) + have hvalue := + call_cleanup_t_int256_direct (v := value) (fuel := fuel + extra) (extra := 151) + (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word 0xff) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + have hshift := + call_shift_right_signed_dynamic_direct (bits := 0xff) (value := value) + (fuel := fuel + extra) (extra := 133) (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word 0xff) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + have hcleanup := + call_cleanup_t_int256_direct (v := evmSar 0xff value) (fuel := fuel + extra) + (extra := 155) (shared := shared) + (store := Finmap.insert "bits" (FormalYul.word 0xff) + (Finmap.insert "value" (FormalYul.word value) + (Finmap.insert "bits" (FormalYul.word 0xff) + (Inhabited.default : EvmYul.Yul.VarStore)))) + (hlookup := hlookup) + simp [FormalYul.word] at hbits hvalue hshift hcleanup + simp +decide [EvmYul.Yul.execCall.eq_def, + EvmYul.Yul.evalCall.eq_def, + EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', + EvmYul.Yul.evalTail.eq_def, + EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, + EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, + EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, + Finmap.lookup_insert, FormalYul.word, hbits, hvalue, hshift, hcleanup] + theorem call_shift_right_t_uint256_t_uint8_127_direct (value fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index 2fd0140c2..17ccc0718 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -48,71 +48,86 @@ theorem call_fun_mulExpRay_revert_direct let s := scaleShiftTree ay let k := kTree x let shift := evmSub s k - have hzeroInit := - call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2176) + have hconvertY1 := + call_convert_int128_to_int256_direct (v := y) (fuel := fuel + extra) (extra := 2072) + (shared := shared) (hlookup := hlookup) (hclean := hclean) + have hconvert255 := + call_convert_255_to_uint8_direct (fuel := fuel + extra) (extra := 2070) (shared := shared) (hlookup := hlookup) - have hzeroUint1 := - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2173) + have hshiftSign := + call_shift_right_t_int256_t_uint8_255_direct (value := y) + (fuel := fuel + extra) (extra := 2009) (shared := shared) (hlookup := hlookup) + have hsignAsUint := + call_convert_int256_to_uint256_direct (v := evmSar 255 y) + (fuel := fuel + extra) (extra := 2068) (shared := shared) (hlookup := hlookup) + have hconvertY2 := + call_convert_int128_to_int256_direct (v := y) (fuel := fuel + extra) (extra := 2064) + (shared := shared) (hlookup := hlookup) (hclean := hclean) + have hayAsUint := + call_convert_int256_to_uint256_direct (v := y) (fuel := fuel + extra) (extra := 2063) (shared := shared) (hlookup := hlookup) - have hzeroUint2 := - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2170) + have hwrapAy := + call_wrapping_sub_t_uint256_direct (x := evmXor y (evmSar 255 y)) (y := evmSar 255 y) + (fuel := fuel + extra) (extra := 2096) (shared := shared) (hlookup := hlookup) + have hzeroInit := + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2176) (shared := shared) (hlookup := hlookup) have hclz := - call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) + call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2091) (shared := shared) (hlookup := hlookup) have hscaleClzBias := - call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2060) + call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2047) (shared := shared) (hlookup := hlookup) have hwrapS := call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) - (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2089) (shared := shared) (hlookup := hlookup) have hconvert127 := - call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2058) + call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2045) (shared := shared) (hlookup := hlookup) have hshrAy := call_shift_right_t_uint256_t_uint8_127_direct (value := ay) - (fuel := fuel + extra) (extra := 1997) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 1984) (shared := shared) (hlookup := hlookup) have hwrapAdd := call_wrapping_add_t_uint256_direct (x := evmSub (evmClz ay) scaleClzBias) (y := evmShr 127 ay) - (fuel := fuel + extra) (extra := 2095) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2082) (shared := shared) (hlookup := hlookup) have hoctave := - call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2051) + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2038) (shared := shared) (hlookup := hlookup) have hconvertS := - call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2047) + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2034) (shared := shared) (hlookup := hlookup) have hwrapShift := - call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2084) + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2071) (shared := shared) (hlookup := hlookup) have hHi := call_convert_MUL_EXP_RAY_HI_MINUS_ONE_to_int256_direct - (fuel := fuel + extra) (extra := 2037) + (fuel := fuel + extra) (extra := 2024) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2135) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2122) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2031) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2018) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2129) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2116) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct (a := evmSgt x 86989971160273136331862631243) (b := evmSlt shift 2) - (fuel := fuel + extra) (extra := 2072) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2059) (shared := shared) (hlookup := hlookup) have hoverflow := - call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1987) + call_constant_ARITHMETIC_OVERFLOW_direct (fuel := fuel + extra) (extra := 1974) (shared := shared) (hlookup := hlookup) have hconvu := - call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2026) + call_convert_uint8_to_uint256_17_direct (fuel := fuel + extra) (extra := 2013) (shared := shared) (hlookup := hlookup) have hpanic := - call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1545) + call_fun_panic_revert_direct (code := 0x11) (fuel := fuel + extra) (extra := 1532) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 + simp only [Nat.reduceAdd, FormalYul.word] at hconvertY1 hconvert255 hshiftSign hsignAsUint hconvertY2 hayAsUint hwrapAy hzeroInit simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word] at hscaleClzBias simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS @@ -150,24 +165,22 @@ theorem call_fun_mulExpRay_revert_direct simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, scaleClzBias, hhiMinusOne] using hguard simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, EvmYul.Yul.State.setStore, - FormalYul.word, primCall_signextend_yul, + FormalYul.word, + hconvertY1, hconvert255, hshiftSign, hsignAsUint, hconvertY2, hayAsUint, hwrapAy, hguardUnfold, - hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleClzBias, hwrapS, + hzeroInit, hclz, hscaleClzBias, hwrapS, hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, hHi, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hoverflow, hconvu, hpanic, - FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, Common.Word.uint256_ofNat_xor_eq_word_evmXor, - Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, - uint256_ofNat_sgt_eq_word_evmSgt, - hclean] + uint256_ofNat_sgt_eq_word_evmSgt] set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay` forwards the revert. -/ diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 0890f82d8..5af31bc3f 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -4,6 +4,7 @@ import ExpProof.Seam.Helpers import ExpProof.Seam.Dispatcher import ExpProof.Seam.Value import FormalYul.Preservation +import Mathlib.Data.Nat.Bitwise /-! # Value-path reductions for `mulExpRay` @@ -52,82 +53,99 @@ theorem call_fun_mulExpRay_direct let k := kTree x let shift := evmSub s k let scale := evmShl s ay - have hzeroInit := - call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2176) + let result := + evmMul (evmOr (evmLt 0 (absTree y)) (signTree y)) (mulMagnitudeTree y x) + have hconvertY1 := + call_convert_int128_to_int256_direct (v := y) (fuel := fuel + extra) (extra := 2072) + (shared := shared) (hlookup := hlookup) (hclean := hclean) + have hconvert255 := + call_convert_255_to_uint8_direct (fuel := fuel + extra) (extra := 2070) (shared := shared) (hlookup := hlookup) - have hzeroUint1 := - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2173) + have hshiftSign := + call_shift_right_t_int256_t_uint8_255_direct (value := y) + (fuel := fuel + extra) (extra := 2009) (shared := shared) (hlookup := hlookup) + have hsignAsUint := + call_convert_int256_to_uint256_direct (v := evmSar 255 y) + (fuel := fuel + extra) (extra := 2068) (shared := shared) (hlookup := hlookup) + have hconvertY2 := + call_convert_int128_to_int256_direct (v := y) (fuel := fuel + extra) (extra := 2064) + (shared := shared) (hlookup := hlookup) (hclean := hclean) + have hayAsUint := + call_convert_int256_to_uint256_direct (v := y) (fuel := fuel + extra) (extra := 2063) (shared := shared) (hlookup := hlookup) - have hzeroUint2 := - call_zero_value_for_split_t_uint256_direct (fuel := fuel + extra) (extra := 2170) + have hwrapAy := + call_wrapping_sub_t_uint256_direct (x := evmXor y (evmSar 255 y)) (y := evmSar 255 y) + (fuel := fuel + extra) (extra := 2096) (shared := shared) (hlookup := hlookup) + have hzeroInit := + call_zero_value_for_split_t_int128_direct (fuel := fuel + extra) (extra := 2176) (shared := shared) (hlookup := hlookup) have hclz := - call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2104) + call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2091) (shared := shared) (hlookup := hlookup) have hscaleClzBias := - call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2060) + call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2047) (shared := shared) (hlookup := hlookup) have hwrapS := call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) - (fuel := fuel + extra) (extra := 2102) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2089) (shared := shared) (hlookup := hlookup) have hconvert127 := - call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2058) + call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2045) (shared := shared) (hlookup := hlookup) have hshrAy := call_shift_right_t_uint256_t_uint8_127_direct (value := ay) - (fuel := fuel + extra) (extra := 1997) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 1984) (shared := shared) (hlookup := hlookup) have hwrapAdd := call_wrapping_add_t_uint256_direct (x := evmSub (evmClz ay) scaleClzBias) (y := evmShr 127 ay) - (fuel := fuel + extra) (extra := 2095) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2082) (shared := shared) (hlookup := hlookup) have hoctave := - call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2051) + call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2038) (shared := shared) (hlookup := hlookup) have hconvertS := - call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2047) + call_convert_uint256_to_int256_direct (v := s) (fuel := fuel + extra) (extra := 2034) (shared := shared) (hlookup := hlookup) have hwrapShift := - call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2084) + call_wrapping_sub_t_int256_direct (x := s) (y := k) (fuel := fuel + extra) (extra := 2071) (shared := shared) (hlookup := hlookup) have hHi := call_convert_MUL_EXP_RAY_HI_MINUS_ONE_to_int256_direct - (fuel := fuel + extra) (extra := 2037) + (fuel := fuel + extra) (extra := 2024) (shared := shared) (hlookup := hlookup) have hcleanupXForHi := - call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2135) + call_cleanup_t_int256_direct (v := x) (fuel := fuel + extra) (extra := 2122) (shared := shared) (hlookup := hlookup) have hconvertTwo := - call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2031) + call_convert_2_to_int256_direct (fuel := fuel + extra) (extra := 2018) (shared := shared) (hlookup := hlookup) have hcleanupShift := - call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2129) + call_cleanup_t_int256_direct (v := shift) (fuel := fuel + extra) (extra := 2116) (shared := shared) (hlookup := hlookup) have hOrGuard := call_fun_or_direct (a := evmSgt x 86989971160273136331862631243) (b := evmSlt shift 2) - (fuel := fuel + extra) (extra := 2072) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 2059) (shared := shared) (hlookup := hlookup) have hscaleShift := call_shift_left_t_uint256_t_uint256_direct (value := ay) (bits := s) - (fuel := fuel + extra) (extra := 1962) (shared := shared) (hlookup := hlookup) + (fuel := fuel + extra) (extra := 1949) (shared := shared) (hlookup := hlookup) have hconvertShiftOut := - call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2019) + call_convert_int256_to_uint256_direct (v := shift) (fuel := fuel + extra) (extra := 2006) (shared := shared) (hlookup := hlookup) have hZM := call_convert_MUL_EXP_RAY_ZERO_MAX_to_int256_direct - (fuel := fuel + extra) (extra := 2017) + (fuel := fuel + extra) (extra := 2004) (shared := shared) (hlookup := hlookup) have hkernel := call_fun__expRayKernel_direct (x := x) (k := k) (scale := scale) (shift := shift) - (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1436) + (zeroCutoff := mulExpRayZeroMax) (fuel := fuel + extra) (extra := 1423) (shared := shared) (hlookup := hlookup) have hconvertInt256 := - call_convert_uint256_to_int256_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 2011) (shared := shared) (hlookup := hlookup) + call_convert_uint256_to_int256_direct (v := result) (fuel := fuel + extra) + (extra := 1998) (shared := shared) (hlookup := hlookup) have hconvertNarrow := - call_convert_int256_to_int128_direct (v := mulExpTree y x) (fuel := fuel + extra) - (extra := 2010) (shared := shared) (hlookup := hlookup) - simp only [Nat.reduceAdd, FormalYul.word] at hzeroInit hzeroUint1 hzeroUint2 + call_convert_int256_to_int128_direct (v := result) (fuel := fuel + extra) + (extra := 1997) (shared := shared) (hlookup := hlookup) + simp only [Nat.reduceAdd, FormalYul.word] at hconvertY1 hconvert255 hshiftSign hsignAsUint hconvertY2 hayAsUint hwrapAy hzeroInit simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word] at hscaleClzBias simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS @@ -155,7 +173,7 @@ theorem call_fun_mulExpRay_direct simp only [Nat.reduceAdd, FormalYul.word, k, kTree, scale, shift, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias, mulExpRayZeroMax, evmShl_one_c0] at hkernel simp only [Nat.reduceAdd, FormalYul.word, - mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, + result, mulMagnitudeTree, r0MulTree, mulScaleTree, mulShiftTree, tTree, vTree, evTree, odTree, todTree, kTree, scaleShiftTree, absTree, signTree, tArgShift, k27Q235, ln2Q235, squareShift, ev0, ev1, ev2, ev3, ev4, evShift1, evShift2, evShift3, evShift4, @@ -175,6 +193,15 @@ theorem call_fun_mulExpRay_direct 2) = 0 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, scaleClzBias, hhiMinusOne] using hguard + have hresultOrder : result = mulExpTree y x := by + have hor : evmOr (evmLt 0 (absTree y)) (signTree y) = + evmOr (signTree y) (evmLt 0 (absTree y)) := by + unfold evmOr + rw [Nat.lor_comm] + dsimp only [result] + rw [hor] + unfold mulExpTree sgnTree evmMul + rw [Nat.mul_comm] simp +decide [EvmYul.Yul.execCall.eq_def, EvmYul.Yul.evalCall.eq_def, EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', @@ -183,19 +210,18 @@ theorem call_fun_mulExpRay_direct EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.revive, EvmYul.Yul.State.setLeave, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, primCall_signextend_yul, + FormalYul.word, + hconvertY1, hconvert255, hshiftSign, hsignAsUint, hconvertY2, hayAsUint, hwrapAy, hguardUnfold, - hzeroInit, hzeroUint1, hzeroUint2, hclz, hscaleClzBias, hwrapS, + hzeroInit, hclz, hscaleClzBias, hwrapS, hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, hHi, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hscaleShift, hconvertShiftOut, hZM, hkernel, hconvertInt256, hconvertNarrow, FormalYul.Preservation.uint256_ofNat_lt_eq_word_evmLt, - FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, FormalYul.Preservation.uint256_ofNat_mul_eq_word_evmMul, FormalYul.Preservation.uint256_ofNat_or_eq_word_evmOr, Common.Word.uint256_ofNat_xor_eq_word_evmXor, - Common.Word.uint256_ofNat_sar_eq_word_evmSar, uint256_ofNat_slt_eq_word_evmSlt, uint256_ofNat_sgt_eq_word_evmSgt, mulExpTree, mulMagnitudeTree, sgnTree, r0MulTree, mulScaleTree, mulShiftTree, @@ -205,8 +231,11 @@ theorem call_fun_mulExpRay_direct od0, od1, od2, od3, od4, odShift1, odShift2, odShift3, odShift4, todShift, marginWord, scaleShiftTree, absTree, signTree, kTree, - scaleClzBias, mulExpRayZeroMax, hclean] - simpa only [FormalYul.word] using hresultClean + scaleClzBias, mulExpRayZeroMax] + change EvmYul.UInt256.signextend (FormalYul.word 15) (FormalYul.word result) = + FormalYul.word (mulExpTree y x) + rw [hresultOrder] + exact hresultClean set_option maxHeartbeats 12000000 in /-- `fun_wrap_mulExpRay(y, x)` forwards to the value path. -/ From f698f59207a01f1c79cc853d3e3fe83306a6d5bd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 15:22:02 +0000 Subject: [PATCH 097/107] Add Sheriff (Algebra-like) UniV3 fork to RobinHood with fork ID 41 Sheriff is an Algebra Integral (v1.2.2) DEX on RobinHood chain (app.sheriff.exchange). Wire it as UniV3 fork ID 41: - New src/core/univ3forks/Sheriff.sol with the Algebra pool deployer (0x9ac30D72168a4498aE5C80226F4d3C86278e8f80), the Algebra Integral pool init code hash, and the fork ID constant. - Wire the fork into RobinHood's _uniV3ForkInfo using the Algebra swap callback (algebraSwapCallback). The Algebra salt (keccak256(abi.encode( token0, token1)), no fee/tickSpacing) is produced by the existing poolId==0 path in _toPool. - Add UNISWAPV3_FORKS.md and CHANGELOG.md entries. The init code hash was verified by recomputing the USDG/WETH pool address (0x536a7B19abB933bf6319e0b8817e733Bba166674) via CREATE2. --- CHANGELOG.md | 1 + UNISWAPV3_FORKS.md | 2 ++ src/chains/RobinHood/Common.sol | 6 ++++++ src/core/univ3forks/Sheriff.sol | 8 ++++++++ 4 files changed, 17 insertions(+) create mode 100644 src/core/univ3forks/Sheriff.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index 110b19463..857e57337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Add SquadSwapV3 UniV3 fork to Bnb with fork ID 38 * Add PrjxV3 (Project X) UniV3 fork to HyperEVM with fork ID 39 * Add Up UniV3 fork to RobinHood with fork ID 40 +* Add Sheriff (Algebra-like) UniV3 fork to RobinHood with fork ID 41 * Add `BRIDGE_ERC20_TO_ACROSS` and `BRIDGE_NATIVE_TO_ACROSS` to Base * Fix several bugs reported by Nethermind * SettlerMetaTxn now reverts on short actions diff --git a/UNISWAPV3_FORKS.md b/UNISWAPV3_FORKS.md index 24b8464b5..33bf84593 100644 --- a/UNISWAPV3_FORKS.md +++ b/UNISWAPV3_FORKS.md @@ -51,3 +51,5 @@ 39. PrjxV3 (Project X) 40. Up + + 41. Sheriff (Algebra-like) diff --git a/src/chains/RobinHood/Common.sol b/src/chains/RobinHood/Common.sol index c3c963e00..079b0a703 100644 --- a/src/chains/RobinHood/Common.sol +++ b/src/chains/RobinHood/Common.sol @@ -26,6 +26,8 @@ import { IPancakeSwapV3Callback } from "../../core/univ3forks/PancakeSwapV3.sol"; import {upFactory, upInitHash, upForkId} from "../../core/univ3forks/Up.sol"; +import {sheriffFactory, sheriffInitHash, sheriffForkId} from "../../core/univ3forks/Sheriff.sol"; +import {IAlgebraCallback} from "../../core/univ3forks/Algebra.sol"; import {ROBINHOOD_POOL_MANAGER} from "../../core/UniswapV4Addresses.sol"; import {FastLogic} from "../../utils/FastLogic.sol"; @@ -92,6 +94,10 @@ abstract contract RobinHoodMixin is FreeMemory, SettlerBase, UniswapV4, EkuboV3 factory = upFactory; initHash = upInitHash; callbackSelector = uint32(IUniswapV3Callback.uniswapV3SwapCallback.selector); + } else if (forkId == sheriffForkId) { + factory = sheriffFactory; + initHash = sheriffInitHash; + callbackSelector = uint32(IAlgebraCallback.algebraSwapCallback.selector); } else { revertUnknownForkId(forkId); } diff --git a/src/core/univ3forks/Sheriff.sol b/src/core/univ3forks/Sheriff.sol new file mode 100644 index 000000000..05c294ba2 --- /dev/null +++ b/src/core/univ3forks/Sheriff.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +// Sheriff is an Algebra Integral (v1.2.2) DEX on RobinHood. `sheriffFactory` is the +// Algebra pool deployer (the CREATE2 deployer of the pools), not the pool factory. +address constant sheriffFactory = 0x9ac30D72168a4498aE5C80226F4d3C86278e8f80; +bytes32 constant sheriffInitHash = 0x62441ebe4e4315cf3d49d5957f94d66b253dbabe7006f34ad7f70947e60bf15c; +uint8 constant sheriffForkId = 41; From d35d155c5d98ff27c239a212f6e37510d366dd34 Mon Sep 17 00:00:00 2001 From: Lazaro Raul Date: Tue, 14 Jul 2026 18:22:36 +0200 Subject: [PATCH 098/107] fix: changelog support for Across on Monad entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 857e57337..1de6e0d29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ * Add PrjxV3 (Project X) UniV3 fork to HyperEVM with fork ID 39 * Add Up UniV3 fork to RobinHood with fork ID 40 * Add Sheriff (Algebra-like) UniV3 fork to RobinHood with fork ID 41 -* Add `BRIDGE_ERC20_TO_ACROSS` and `BRIDGE_NATIVE_TO_ACROSS` to Base +* Add `BRIDGE_ERC20_TO_ACROSS` and `BRIDGE_NATIVE_TO_ACROSS` to Monad * Fix several bugs reported by Nethermind * SettlerMetaTxn now reverts on short actions * Fix wrong `buyToken` in `TooMuchSlippage` revert reason in MaverickV2 From cbd2c53aedd2a651d566fbd1d314ae80f75f841b Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 22:10:47 +0200 Subject: [PATCH 099/107] Simplify --- src/vendor/Exp.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 50ceaabd9..c954bfae8 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -62,8 +62,8 @@ library Exp { function mulExpRay(int128 y, int256 x) internal pure returns (int128) { unchecked { // Split `y` into a sign mask and a magnitude - uint256 sign = uint256(int256(y) >> 255); - uint256 ay = (uint256(int256(y)) ^ sign) - sign; + int256 sign = int256(y) >> 255; + uint256 ay = uint256((int256(y) ^ sign) - sign); // The top-bit term admits ay = abs(type(int128).min) at s = 0 while leaving every // smaller magnitude's normalization unchanged. From 0b8267c06e14729c80288fecc2b14670e1eab4ff Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Tue, 14 Jul 2026 22:19:28 +0200 Subject: [PATCH 100/107] Typo --- src/vendor/Exp.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index c954bfae8..2d5c3d922 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -51,7 +51,7 @@ library Exp { /// nonincreasing if y < 0. For a fixed `x`, among accepted inputs, the result is /// nondecreasing in `y`. Jointly, for accepted (y₁, x₁, r₁ = mulExpRay(y₁, x₁)) and (y₂, /// x₂, r₂ = mulExpRay(y₂, x₂)), r₁ ≤ r₂ when 0 ≤ y₁ ≤ y₂ ∧ x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 ∧ x₂ - /// ≤ x₁, and when y₁ ≤ 0 ≤ y₂ for any (x₁, x₂). + /// ≤ x₁, and when y₁ ≤ 0 ≤ y₂ (for any x₁, x₂). /// @dev Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ /// (regardless of y), or when round(x / (10²⁷⋅ln(2))) exceeds s - 2, with 2ˢ the scale /// headroom above |y|; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. The From 116b3daa4ab6e551f9fd4e589745031c39d2ceb5 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Jul 2026 12:03:16 +0200 Subject: [PATCH 101/107] Certify tighter Ln approximation margin Use generated mixed interval-Horner/Kronecker and Bernstein cell certificates with variable-propagated Horner errors to certify the runtime core bound. Set the Solidity Q72 bias from the 0.3288640403604298097806-ulp bound, with reproducible formal generation and cache keys. Co-Authored-By: OpenAI Codex --- .github/actions/build-ln-proof/action.yml | 12 +- .../actions/cache-formal-package/action.yml | 9 +- formal/common/Common.lean | 2 + .../Common/Foundation/PackedBernstein.lean | 254 ++++ .../common/Common/Foundation/PackedShift.lean | 82 ++ formal/common/Common/Seam/RealExpBridge.lean | 46 + formal/ln/LnProof/.gitignore | 4 +- formal/ln/LnProof/GenApproximationCert.lean | 406 +++++++ formal/ln/LnProof/GenBranchCertHard.lean | 50 - formal/ln/LnProof/GenCover.lean | 72 +- formal/ln/LnProof/GenErrLit.lean | 52 +- formal/ln/LnProof/GenFloorCertLit.lean | 18 +- formal/ln/LnProof/LnProof.lean | 20 +- formal/ln/LnProof/LnProof/Error.lean | 9 - formal/ln/LnProof/LnProof/Error/Bound.lean | 141 ++- formal/ln/LnProof/LnProof/Error/Cert.lean | 28 - formal/ln/LnProof/LnProof/Error/Core.lean | 28 - .../LnProof/LnProof/Error/Core/Assembly.lean | 336 +----- .../ln/LnProof/LnProof/Error/Core/Bounds.lean | 730 ----------- .../LnProof/LnProof/Error/Core/BranchBn.lean | 12 +- .../LnProof/Error/Core/BranchCert.lean | 584 --------- .../Error/Core/BranchCertHardDefs.lean | 19 - .../LnProof/LnProof/Error/Core/BranchNeg.lean | 20 +- .../LnProof/LnProof/Error/Core/BranchPos.lean | 335 +++-- .../ln/LnProof/LnProof/Error/Core/Budget.lean | 75 +- .../ln/LnProof/LnProof/Error/Core/C160.lean | 21 +- .../LnProof/LnProof/Error/Core/CutDefs.lean | 59 +- .../ln/LnProof/LnProof/Error/Core/Direct.lean | 264 ---- .../LnProof/LnProof/Error/Core/ExpMargin.lean | 516 -------- .../LnProof/Error/Core/PhaseCover.lean | 492 -------- .../LnProof/LnProof/Error/Core/PhaseGe.lean | 324 ----- .../LnProof/LnProof/Error/Core/PhaseLt.lean | 461 ------- .../LnProof/LnProof/Error/Core/Residue.lean | 295 +---- .../LnProof/Error/Core/ResidueCover.lean | 487 -------- .../ln/LnProof/LnProof/Error/FactoredCap.lean | 245 ---- formal/ln/LnProof/LnProof/Error/GeBridge.lean | 118 -- formal/ln/LnProof/LnProof/Error/LtBridge.lean | 13 +- .../LnProof/LnProof/Error/LtFactoredCap.lean | 153 ++- formal/ln/LnProof/LnProof/Floor.lean | 11 - formal/ln/LnProof/LnProof/Floor/Assembly.lean | 1075 ++--------------- formal/ln/LnProof/LnProof/Floor/Bracket.lean | 389 +----- formal/ln/LnProof/LnProof/Floor/Budget.lean | 45 +- formal/ln/LnProof/LnProof/Floor/Caps.lean | 233 +--- .../CarryIndependent/AnalyticRuntime.lean | 554 +++++++++ .../Floor/CarryIndependent/Approximation.lean | 77 ++ .../CarryIndependent/ApproximationReal.lean | 304 +++++ .../CarryIndependent/ApproximationSound.lean | 233 ++++ .../Floor/CarryIndependent/Arithmetic.lean | 46 + .../LnProof/Floor/CarryIndependent/Atanh.lean | 126 ++ .../Floor/CarryIndependent/Bounds.lean | 151 +++ .../CarryIndependent/CertificateRuntime.lean | 96 ++ .../LnProof/Floor/CarryIndependent/Cut.lean | 264 ++++ .../Floor/CarryIndependent/Horner.lean | 53 + .../CarryIndependent/HornerCorrelation.lean | 170 +++ .../Floor/CarryIndependent/Normalization.lean | 455 +++++++ .../LnProof/Floor/CarryIndependent/Phase.lean | 150 +++ .../Floor/CarryIndependent/Runtime.lean | 62 + .../Floor/CarryIndependent/StageErrors.lean | 467 +++++++ .../LnProof/Floor/CarryIndependent/Upper.lean | 46 + .../Floor/CarryIndependent/WordRuntime.lean | 388 ++++++ formal/ln/LnProof/LnProof/Floor/CertAux.lean | 24 - formal/ln/LnProof/LnProof/Floor/CertDefs.lean | 16 - formal/ln/LnProof/LnProof/Floor/CertGeLo.lean | 56 +- formal/ln/LnProof/LnProof/Floor/CertGeUp.lean | 129 -- formal/ln/LnProof/LnProof/Floor/CertLtLo.lean | 56 +- formal/ln/LnProof/LnProof/Floor/CertLtUp.lean | 119 -- .../LnProof/LnProof/Floor/CertTightLit.lean | 470 ------- formal/ln/LnProof/LnProof/Floor/Consts.lean | 15 +- formal/ln/LnProof/LnProof/Floor/Model.lean | 87 +- formal/ln/LnProof/LnProof/Floor/Spec.lean | 144 +-- formal/ln/LnProof/LnProof/Floor/Window.lean | 65 +- formal/ln/LnProof/LnProof/Foundation.lean | 16 - formal/ln/LnProof/LnProof/Model/Body.lean | 9 +- formal/ln/LnProof/LnProof/Mono.lean | 9 - formal/ln/LnProof/LnProof/Mono/Octave.lean | 4 +- formal/ln/LnProof/LnProof/Seam.lean | 10 - formal/ln/LnProof/LnProof/Seam/RealLog.lean | 26 + formal/ln/LnProof/LnProof/Spec.lean | 10 - formal/ln/README.md | 40 +- src/vendor/Ln.sol | 15 +- 80 files changed, 5252 insertions(+), 8255 deletions(-) create mode 100644 formal/common/Common/Foundation/PackedBernstein.lean create mode 100644 formal/common/Common/Foundation/PackedShift.lean create mode 100644 formal/ln/LnProof/GenApproximationCert.lean delete mode 100644 formal/ln/LnProof/GenBranchCertHard.lean delete mode 100644 formal/ln/LnProof/LnProof/Error.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/Bounds.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/Direct.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/ExpMargin.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/PhaseGe.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/PhaseLt.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/Core/ResidueCover.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/FactoredCap.lean delete mode 100644 formal/ln/LnProof/LnProof/Error/GeBridge.lean delete mode 100644 formal/ln/LnProof/LnProof/Floor.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Approximation.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationSound.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Arithmetic.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Atanh.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Bounds.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/CertificateRuntime.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Cut.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Horner.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/HornerCorrelation.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Runtime.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/StageErrors.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/Upper.lean create mode 100644 formal/ln/LnProof/LnProof/Floor/CarryIndependent/WordRuntime.lean delete mode 100644 formal/ln/LnProof/LnProof/Floor/CertGeUp.lean delete mode 100644 formal/ln/LnProof/LnProof/Floor/CertLtUp.lean delete mode 100644 formal/ln/LnProof/LnProof/Floor/CertTightLit.lean delete mode 100644 formal/ln/LnProof/LnProof/Foundation.lean delete mode 100644 formal/ln/LnProof/LnProof/Mono.lean delete mode 100644 formal/ln/LnProof/LnProof/Seam.lean delete mode 100644 formal/ln/LnProof/LnProof/Spec.lean diff --git a/.github/actions/build-ln-proof/action.yml b/.github/actions/build-ln-proof/action.yml index 2e0dde4a0..ac3697659 100644 --- a/.github/actions/build-ln-proof/action.yml +++ b/.github/actions/build-ln-proof/action.yml @@ -39,22 +39,20 @@ runs: lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts Common.GenCover lake env lean GenFloorCertLit.lean lake build \ - LnProof.Cert.FloorCertGeUpLit \ LnProof.Cert.FloorCertGeLoLit \ - LnProof.Cert.FloorCertLtUpLit \ LnProof.Cert.FloorCertLtLoLit lake env lean GenCover.lean lake env lean GenErr1.lean lake build \ - LnProof.Error.Core.ExpMargin \ - LnProof.Error.Core.Budget \ - LnProof.Error.Core.BranchCertHardDefs + LnProof.Floor.CarryIndependent.Approximation \ + Common.GenBernstein \ + Common.Foundation.PackedShift + lake env lean GenApproximationCert.lean + lake build LnProof.Error.Core.Budget lake env lean GenErrLit.lean - lake env lean GenBranchCertHard.lean - name: Build Ln proof package shell: bash working-directory: formal/ln/LnProof run: | - lake build LnProof.Cert.HardMantissaLtGap lake build diff --git a/.github/actions/cache-formal-package/action.yml b/.github/actions/cache-formal-package/action.yml index 697c975c8..0e3cb6e96 100644 --- a/.github/actions/cache-formal-package/action.yml +++ b/.github/actions/cache-formal-package/action.yml @@ -1,8 +1,9 @@ name: Cache formal package description: >- Restore one Lean proof package under a key that includes its direct - dependency sources and its own sources. Restore-only consumers require the - exact cache produced by their ordered publisher. + dependency sources, its own sources, and the workflow that orchestrates it. + Restore-only consumers require the exact cache produced by their ordered + publisher. inputs: cache-name: @@ -36,7 +37,7 @@ runs: uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ${{ inputs.cache-path }} - key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} + key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/workflows/formal.yml', '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} restore-keys: | ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}- ${{ runner.os }}-formal-${{ inputs.cache-name }}- @@ -47,7 +48,7 @@ runs: uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ${{ inputs.cache-path }} - key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} + key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/workflows/formal.yml', '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} - name: Require exact ${{ inputs.cache-name }} cache from its publisher if: inputs.publish != 'true' && steps.restore.outputs.cache-hit != 'true' diff --git a/formal/common/Common.lean b/formal/common/Common.lean index b4079496a..2640c72d8 100644 --- a/formal/common/Common.lean +++ b/formal/common/Common.lean @@ -14,7 +14,9 @@ import Common.Foundation.ExpSum import Common.Foundation.ShiftCert import Common.Foundation.Kronecker import Common.Foundation.KroneckerShift +import Common.Foundation.PackedShift import Common.Foundation.Bernstein +import Common.Foundation.PackedBernstein import Common.Seam.RealExpBridge import Common.GenCover import Common.GenBernstein diff --git a/formal/common/Common/Foundation/PackedBernstein.lean b/formal/common/Common/Foundation/PackedBernstein.lean new file mode 100644 index 000000000..769f80a7e --- /dev/null +++ b/formal/common/Common/Foundation/PackedBernstein.lean @@ -0,0 +1,254 @@ +import Common.Foundation.Bernstein +import Common.Foundation.PackedShift +import Mathlib.Algebra.BigOperators.Intervals +import Mathlib.Data.List.GetD +import Mathlib.Data.Nat.Choose.Sum + +namespace Common.Poly + +open Finset + +def binomialWeight (q : Nat → Int) (n i : Nat) : Int := + ∑ j ∈ Ico 0 (i + 1), q j * (Nat.choose (n - j) (i - j) : Int) + +lemma binomial_row (n j : Nat) (x y : Int) (hj : j ≤ n) : + (∑ i ∈ Ico j (n + 1), + (Nat.choose (n - j) (i - j) : Int) * x ^ i * y ^ (n - i)) = + x ^ j * (x + y) ^ (n - j) := by + rw [Finset.sum_Ico_eq_sum_range] + have hlen : n + 1 - j = n - j + 1 := by omega + rw [hlen] + calc + (∑ k ∈ range (n - j + 1), + (Nat.choose (n - j) (j + k - j) : Int) * x ^ (j + k) * + y ^ (n - (j + k))) = + x ^ j * (∑ k ∈ range (n - j + 1), + (Nat.choose (n - j) k : Int) * x ^ k * y ^ (n - j - k)) := by + rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro k hk + simp only [Finset.mem_range] at hk + have hkj : k ≤ n - j := by omega + have hsub : n - (j + k) = n - j - k := by omega + rw [Nat.add_sub_cancel_left, hsub, pow_add] + ring + _ = x ^ j * (x + y) ^ (n - j) := by + rw [add_pow] + congr 1 + apply Finset.sum_congr rfl + intro k hk + ring + +lemma binomial_transform_identity (q : Nat → Int) (n : Nat) (x y : Int) : + (∑ i ∈ Ico 0 (n + 1), + binomialWeight q n i * x ^ i * y ^ (n - i)) = + ∑ j ∈ Ico 0 (n + 1), q j * x ^ j * (x + y) ^ (n - j) := by + simp only [binomialWeight, Finset.sum_mul] + rw [← Finset.sum_Ico_Ico_comm 0 (n + 1) + (fun j i ↦ q j * (Nat.choose (n - j) (i - j) : Int) * + x ^ i * y ^ (n - i))] + apply Finset.sum_congr rfl + intro j hj + simp only [Finset.mem_Ico] at hj + simp only [mul_assoc] + rw [← Finset.mul_sum] + congr 1 + simpa [mul_assoc] using binomial_row n j x y (by omega) + +lemma foldl_add_eq_sum (xs : List Nat) (f : Nat → Int) (z : Int) : + xs.foldl (fun acc j ↦ acc + f j) z = z + (xs.map f).sum := by + induction xs generalizing z with + | nil => simp + | cons j js ih => + simp only [List.foldl_cons, List.map_cons, List.sum_cons] + rw [ih] + ring + +lemma list_sum_map_range (f : Nat → Int) : ∀ n : Nat, + ((List.range n).map f).sum = ∑ j ∈ Finset.range n, f j := by + intro n + induction n with + | zero => simp + | succ n ih => + rw [List.range_succ, List.map_append, List.sum_append, + Finset.sum_range_succ, ih] + simp + +lemma bernsteinWeight_eq_binomialWeight (q : List Int) (n i : Nat) : + bernsteinWeight q n i = binomialWeight (fun j ↦ q.getD j 0) n i := by + unfold bernsteinWeight binomialWeight + rw [foldl_add_eq_sum] + rw [zero_add, list_sum_map_range] + simp + +lemma homEvalI_eq_sum (q : List Int) (x y : Int) : + homEvalI q x y = + ∑ j ∈ Finset.range q.length, + q.getD j 0 * x ^ j * y ^ (q.length - 1 - j) := by + induction q with + | nil => simp [homEvalI] + | cons c cs ih => + rw [homEvalI] + simp only [List.length_cons] + rw [Finset.sum_range_succ'] + simp only [List.getD_cons_zero, pow_zero, mul_one, + Nat.add_sub_cancel] + rw [ih, Finset.mul_sum] + rw [add_comm] + congr 1 + apply Finset.sum_congr rfl + intro j hj + simp only [Finset.mem_range] at hj + rw [List.getD_cons_succ] + have hsub : cs.length - (j + 1) = cs.length - 1 - j := by + omega + rw [hsub, pow_succ] + ring + +lemma bernstein_sum_eq_homEvalI (q : List Int) (n : Nat) (x y : Int) + (hlen : q.length = n + 1) : + (∑ i ∈ Ico 0 (n + 1), + bernsteinWeight q n i * x ^ i * y ^ (n - i)) = + homEvalI q x (x + y) := by + simp_rw [bernsteinWeight_eq_binomialWeight] + rw [binomial_transform_identity, homEvalI_eq_sum, hlen] + simp + +lemma scaleVariableAux_length (w : Int) (i : Nat) : ∀ C : List Int, + (scaleVariableAux w i C).length = C.length := by + intro C + induction C generalizing i with + | nil => rfl + | cons c cs ih => + simp only [scaleVariableAux, List.length_cons] + rw [ih] + +lemma scaleVariable_length (w : Int) (C : List Int) : + (scaleVariable w C).length = C.length := by + exact scaleVariableAux_length w 0 C + +lemma homEvalI_scaleVariableAux (w x : Int) (k : Nat) : ∀ C : List Int, + homEvalI (scaleVariableAux w k C) x w = + w ^ k * homEvalI C (x * w) w := by + intro C + induction C generalizing k with + | nil => simp [scaleVariableAux, homEvalI] + | cons c cs ih => + simp only [scaleVariableAux, homEvalI, scaleVariableAux_length] + rw [ih, pow_succ] + ring + +lemma homEvalI_scaleVariable (w x : Int) (C : List Int) : + homEvalI (scaleVariable w C) x w = homEvalI C (x * w) w := by + simpa [scaleVariable] using homEvalI_scaleVariableAux w x 0 C + +lemma homEvalI_scaleVariable_collapse (w x : Int) (C : List Int) + (hC : C ≠ []) : + homEvalI (scaleVariable w C) x w = + w ^ (C.length - 1) * evalPoly C x := by + rw [homEvalI_scaleVariable] + match C with + | [] => contradiction + | c :: cs => + simpa using homEvalI_collapse x w c cs + +def checkBernsteinWeightChunk (shifted weights : List Int) + (width : Int) (n start count : Nat) : Bool := + let q := scaleVariable width shifted + (Array.range count).all fun k ↦ + let i := start + k + decide (weights.getD i 0 = bernsteinWeight q n i) + +theorem checkBernsteinWeightChunk_sound + (shifted weights : List Int) (width : Int) (n start count : Nat) + (hcheck : checkBernsteinWeightChunk shifted weights width n start count = true) : + ∀ i : Nat, start ≤ i → i < start + count → + weights.getD i 0 = + bernsteinWeight (scaleVariable width shifted) n i := by + intro i hlo hhi + unfold checkBernsteinWeightChunk at hcheck + have hall : (Array.range count).all (fun k ↦ + decide (weights.getD (start + k) 0 = + bernsteinWeight (scaleVariable width shifted) n (start + k))) := by + simpa using hcheck + rw [Array.all_iff_forall] at hall + have h := hall (i - start) (by simp; omega) (by simp; omega) + simpa [Nat.add_sub_of_le hlo] using h + +lemma bernstein_emitted_shift_identity + (C shifted : List Int) (a b t : Int) + (hC : C ≠ []) (hlen : shifted.length = C.length) + (heval : ∀ x : Int, evalPoly shifted x = evalPoly C (a + x)) : + (∑ i ∈ Ico 0 (C.length - 1 + 1), + bernsteinWeight (scaleVariable (b - a) shifted) + (C.length - 1) i * + (t - a) ^ i * (b - t) ^ (C.length - 1 - i)) = + (b - a) ^ (C.length - 1) * evalPoly C t := by + have hshifted : shifted ≠ [] := by + intro hs + have : C.length = 0 := by simpa [hs] using hlen.symm + exact hC (List.eq_nil_of_length_eq_zero this) + have hscaled : + (scaleVariable (b - a) shifted).length = C.length - 1 + 1 := by + rw [scaleVariable_length, hlen] + have hpos : 0 < C.length := List.length_pos_iff.mpr hC + omega + rw [bernstein_sum_eq_homEvalI _ _ _ _ hscaled] + have hxy : t - a + (b - t) = b - a := by ring + rw [hxy] + rw [homEvalI_scaleVariable_collapse _ _ _ hshifted, hlen, heval] + rw [show a + (t - a) = t by ring] + +theorem nonnegOn_of_emittedTaylor + (C shifted weights : List Int) (a b : Int) + (hC : C ≠ []) (hab : a < b) + (hlen : shifted.length = C.length) + (heval : ∀ x : Int, evalPoly shifted x = evalPoly C (a + x)) + (hweightsLen : weights.length = C.length) + (hweights : ∀ i : Nat, i < C.length → + weights.getD i 0 = + bernsteinWeight (scaleVariable (b - a) shifted) + (C.length - 1) i) + (hnonneg : ∀ d ∈ weights, 0 ≤ d) : NonnegOn C a b := by + intro t hat htb + have hsum : 0 ≤ + ∑ i ∈ Ico 0 (C.length - 1 + 1), + bernsteinWeight (scaleVariable (b - a) shifted) + (C.length - 1) i * + (t - a) ^ i * (b - t) ^ (C.length - 1 - i) := by + apply Finset.sum_nonneg + intro i hi + simp only [Finset.mem_Ico] at hi + have hiC : i < C.length := by + have hpos : 0 < C.length := List.length_pos_iff.mpr hC + omega + rw [← hweights i hiC] + have hiw : i < weights.length := by omega + have hd := hnonneg (weights[i]) (List.getElem_mem hiw) + rw [List.getD_eq_getElem weights 0 hiw] + have hx : 0 ≤ t - a := by omega + have hy : 0 ≤ b - t := by omega + positivity + rw [bernstein_emitted_shift_identity C shifted a b t hC hlen heval] at hsum + have hw : 0 < (b - a) ^ (C.length - 1) := by + have : 0 < b - a := by omega + positivity + nlinarith + +theorem nonnegOn_of_packedBernstein + {B : Nat} (C shifted weights : List Int) (a b : Int) + {scalars : PackedShiftScalars} + (hpacked : checkPackedShiftScalars B scalars = true) + (hevidence : PackedShiftEvidence B C shifted a scalars) + (hC : C ≠ []) (hab : a < b) + (hlen : shifted.length = C.length) + (hweightsLen : weights.length = C.length) + (hweights : ∀ i : Nat, i < C.length → + weights.getD i 0 = + bernsteinWeight (scaleVariable (b - a) shifted) + (C.length - 1) i) + (hnonneg : ∀ d ∈ weights, 0 ≤ d) : NonnegOn C a b := by + exact nonnegOn_of_emittedTaylor C shifted weights a b hC hab hlen + (packedShift_eval hpacked hevidence) hweightsLen hweights hnonneg + +end Common.Poly diff --git a/formal/common/Common/Foundation/PackedShift.lean b/formal/common/Common/Foundation/PackedShift.lean new file mode 100644 index 000000000..53c6f5a19 --- /dev/null +++ b/formal/common/Common/Foundation/PackedShift.lean @@ -0,0 +1,82 @@ +import Common.Foundation.KroneckerShift + +namespace Common.Poly + +structure PackedShiftScalars where + shiftedL1Bound : Nat + sourceAevalBound : Nat + evalAtRadix : Int + +def literalPackedShiftScalars (B : Nat) (C S : List Int) (a : Int) : + PackedShiftScalars where + shiftedL1Bound := polyL1 S + sourceAevalBound := aeval C (1 + a.natAbs) + evalAtRadix := evalPoly S (((2 ^ B : Nat) : Int)) + +def checkPackedShiftScalars (B : Nat) (s : PackedShiftScalars) : Bool := + decide (s.shiftedL1Bound * 2 < 2 ^ B) && + decide (s.sourceAevalBound * 2 < 2 ^ B) + +theorem checkPackedShiftScalars_sound {B : Nat} {s : PackedShiftScalars} + (h : checkPackedShiftScalars B s = true) : + s.shiftedL1Bound * 2 < 2 ^ B ∧ s.sourceAevalBound * 2 < 2 ^ B := by + simpa only [checkPackedShiftScalars, Bool.and_eq_true, decide_eq_true_eq] using h + +structure PackedShiftEvidence (B : Nat) (C S : List Int) (a : Int) + (s : PackedShiftScalars) : Prop where + shiftedL1_le : polyL1 S ≤ s.shiftedL1Bound + sourceAeval_le : aeval C (1 + a.natAbs) ≤ s.sourceAevalBound + shifted_eval : evalPoly S (((2 ^ B : Nat) : Int)) = s.evalAtRadix + source_eval : evalPoly C (a + ((2 ^ B : Nat) : Int)) = s.evalAtRadix + +theorem literalPackedShiftEvidence {B : Nat} {C S : List Int} {a : Int} + (heval : evalPoly S (((2 ^ B : Nat) : Int)) = + evalPoly C (a + ((2 ^ B : Nat) : Int))) : + PackedShiftEvidence B C S a (literalPackedShiftScalars B C S a) where + shiftedL1_le := Nat.le_refl _ + sourceAeval_le := Nat.le_refl _ + shifted_eval := rfl + source_eval := heval.symm + +theorem packedShift_eval {B : Nat} {C S : List Int} {a : Int} + {s : PackedShiftScalars} + (hcheck : checkPackedShiftScalars B s = true) + (he : PackedShiftEvidence B C S a s) : + ∀ x : Int, evalPoly S x = evalPoly C (a + x) := by + obtain ⟨hshifted, hsource⟩ := checkPackedShiftScalars_sound hcheck + have hS : polyL1 S * 2 < 2 ^ B := by + have hbound := he.shiftedL1_le + omega + have htrueShift : polyL1 (polyShift C a) * 2 < 2 ^ B := by + have hpolyShift := polyL1_polyShift C a + have hbound := he.sourceAeval_le + omega + have hradix : + evalPoly S ((2 : Int) ^ B) = evalPoly (polyShift C a) ((2 : Int) ^ B) := by + rw [int_two_pow, polyShift_eval] + exact he.shifted_eval.trans he.source_eval.symm + intro x + rw [evalPoly_ext S (polyShift C a) hS htrueShift hradix x] + exact polyShift_eval C a x + +def checkPackedCell (B : Nat) (S : List Int) (w : Int) + (s : PackedShiftScalars) : Bool := + checkPackedShiftScalars B s && decide (0 ≤ w) && + decide (0 ≤ (hornerIv S 0 w).1) + +theorem checkPackedCell_nonnegOn {B : Nat} {C S : List Int} {a w : Int} + {s : PackedShiftScalars} + (he : PackedShiftEvidence B C S a s) + (hcheck : checkPackedCell B S w s = true) : + NonnegOn C a (a + w) := by + simp only [checkPackedCell, Bool.and_eq_true, decide_eq_true_eq] at hcheck + obtain ⟨⟨hpacked, hw⟩, hhorner⟩ := hcheck + have heval := packedShift_eval hpacked he + intro x hxlo hxhi + have hs := (hornerIv_sound S (lo := 0) (hi := w) (x := x - a) + (Int.le_refl 0) (by omega) (by omega)).1 + rw [heval (x - a)] at hs + rw [show a + (x - a) = x by omega] at hs + omega + +end Common.Poly diff --git a/formal/common/Common/Seam/RealExpBridge.lean b/formal/common/Common/Seam/RealExpBridge.lean index 8f2b8720a..8612a4c10 100644 --- a/formal/common/Common/Seam/RealExpBridge.lean +++ b/formal/common/Common/Seam/RealExpBridge.lean @@ -143,6 +143,52 @@ lemma le_exp_of_capLB {p q y w : Nat} (hq : 0 < q) (hw : 0 < w) _ ≤ ∑' i : Nat, ((p : Real) / q) ^ i / ((fact i : Nat) : Real) := by exact Summable.sum_le_tsum _ (fun i hi => expTerm_nonneg hq i) hs.summable +lemma partial_sum_le_exp {p q : Nat} (hq : 0 < q) (n : Nat) : + (expNum n p q : Real) / ((fact n * q ^ n : Nat) : Real) ≤ + Real.exp ((p : Real) / q) := by + have hs := exp_hasSum ((p : Real) / q) + rw [expNum_div_eq_sum_range n p q hq, ← hs.tsum_eq] + exact Summable.sum_le_tsum (Finset.range (n + 1)) + (fun i _ => expTerm_nonneg hq i) hs.summable + +lemma capUB_of_exp_le {p q y w : Nat} (hq : 0 < q) (hw : 0 < w) + (h : Real.exp ((p : Real) / q) ≤ (y : Real) / w) : capUB p q y w := by + intro n + have hratio : + (expNum n p q : Real) / ((fact n * q ^ n : Nat) : Real) ≤ (y : Real) / w := + (partial_sum_le_exp hq n).trans h + have hdenpos : 0 < ((fact n * q ^ n : Nat) : Real) := by + exact_mod_cast Nat.mul_pos (fact_pos n) (Nat.pow_pos hq) + have hwpos : 0 < (w : Real) := by exact_mod_cast hw + have hcross : + (expNum n p q : Real) * (w : Real) ≤ + (y : Real) * ((fact n * q ^ n : Nat) : Real) := + (div_le_div_iff₀ hdenpos hwpos).mp hratio + exact_mod_cast hcross + +lemma capLB_of_lt_exp {p q y w : Nat} (hq : 0 < q) (hw : 0 < w) + (h : (y : Real) / w < Real.exp ((p : Real) / q)) : capLB p q y w := by + have hs := exp_hasSum ((p : Real) / q) + have heventually : ∀ᶠ n : Nat in Filter.atTop, + (y : Real) / w < ∑ i ∈ Finset.range n, + ((p : Real) / q) ^ i / ((fact i : Nat) : Real) := + (tendsto_order.mp hs.tendsto_sum_nat).1 _ h + obtain ⟨n, hn⟩ := heventually.exists + have hterm : 0 ≤ ((p : Real) / q) ^ n / ((fact n : Nat) : Real) := + expTerm_nonneg hq n + have hratio : (y : Real) / w ≤ + (expNum n p q : Real) / ((fact n * q ^ n : Nat) : Real) := by + rw [expNum_div_eq_sum_range n p q hq, Finset.sum_range_succ] + linarith + have hwpos : 0 < (w : Real) := by exact_mod_cast hw + have hdenpos : 0 < ((fact n * q ^ n : Nat) : Real) := by + exact_mod_cast Nat.mul_pos (fact_pos n) (Nat.pow_pos hq) + have hcross : (y : Real) * ((fact n * q ^ n : Nat) : Real) ≤ + (expNum n p q : Real) * (w : Real) := + (div_le_div_iff₀ hwpos hdenpos).mp hratio + refine ⟨n, ?_⟩ + exact_mod_cast hcross + end end Common.RealExpBridge diff --git a/formal/ln/LnProof/.gitignore b/formal/ln/LnProof/.gitignore index 14418c3de..137b4a68e 100644 --- a/formal/ln/LnProof/.gitignore +++ b/formal/ln/LnProof/.gitignore @@ -5,7 +5,7 @@ /LnProof/LnYulRuntime.lean /LnProof/LnYulProof.lean -# Lean-generated certificate literals and cell covers — the whole Cert/ tree is -# machine output (floor + error-bound literals, cell covers, bias cap numerator). +# Lean-generated certificate literals, cells, and aggregate covers — the whole +# Cert/ tree is machine output. /LnProof/Cert/* !/LnProof/Cert/.gitkeep diff --git a/formal/ln/LnProof/GenApproximationCert.lean b/formal/ln/LnProof/GenApproximationCert.lean new file mode 100644 index 000000000..88980e2d8 --- /dev/null +++ b/formal/ln/LnProof/GenApproximationCert.lean @@ -0,0 +1,406 @@ +import LnProof.Floor.CarryIndependent.Approximation +import Common.GenBernstein + +open Common.Poly Common.GenBernstein Common.GenCover + +namespace GenApproximationCert + +set_option maxRecDepth 100000 + +inductive Family where + | low + | high + +inductive CellKind where + | horner + | bernstein + +structure CellMeta where + family : Family + index : Nat + lo : Nat + hi : Nat + candidate : Nat + kind : CellKind + artifactLength : Nat + +def dependencyLaneCount : Option Nat := some 4 + +def totalCellCount : Nat := 310 +def lowCellCount : Nat := 131 +def highCellCount : Nat := 179 +def lowBernsteinIndices : List Nat := [6, 7, 55, 56, 91, 92, 114, 115, 116] +def highBernsteinIndices : List Nat := [0, 93, 94, 130, 131, 156, 157, 158, 174, 175] + +def candidateAt (hi : Nat) : Nat := + Nat.sqrt (LnFloorCarry.approximationEnvelopeSquareBudget / (hi + 1)) + +def certificate (family : Family) (a : Nat) : List Int := + match family with + | .low => LnFloorCarry.approximationLowCert a + | .high => LnFloorCarry.approximationHighCert a + +def familyStem : Family → String + | .low => "Low" + | .high => "High" + +def familyCoverName : Family → String + | .low => "approximationLowCover" + | .high => "approximationHighCover" + +def familyCertName : Family → String + | .low => "approximationLowCert" + | .high => "approximationHighCert" + +def pad3 (i : Nat) : String := + (if i < 10 then "00" else if i < 100 then "0" else "") ++ toString i + +def cellModuleName (family : Family) (index : Nat) : String := + s!"Approximation{familyStem family}C{pad3 index}" + +def cellName (family : Family) (index : Nat) : String := + s!"approximation{familyStem family}Cell{pad3 index}" + +def parentRange (i : Nat) : Nat × Nat := + let U := LnFloorCarry.approximationMaxU + let lo := U * i / 64 + let hi := if i = 63 then U else U * (i + 1) / 64 - 1 + (lo, hi) + +def tryCell (family : Family) (lo hi : Nat) : Option BernsteinCell := + acceptedCell (certificate family (candidateAt hi)) 128 lo hi + +partial def split (family : Family) : Nat → Nat → Nat → Option (List BernsteinCell) + | 0, _, _ => none + | fuel + 1, lo, hi => + match tryCell family lo hi with + | some cell => some [cell] + | none => + if hi ≤ lo + 1 then none + else + let mid := (lo + hi) / 2 + match split family fuel lo mid, split family fuel (mid + 1) hi with + | some lhs, some rhs => some (lhs ++ rhs) + | _, _ => none + +def allCells (family : Family) : Option (List BernsteinCell) := + (List.range 64).foldlM (init := []) fun acc i => do + let (lo, hi) := parentRange i + let cells ← split family 12 lo hi + pure (acc ++ cells) + +def packedBits (C shifted : List Int) (lo : Int) : Nat := + max + (strictPow2Bits (polyL1 shifted * 2)) + (strictPow2Bits (aeval C (1 + lo.natAbs) * 2)) + +def laneStarts (laneCount : Nat) : List Nat := + (List.range laneCount).map fun i => totalCellCount * i / laneCount + +def laneTips (laneCount : Nat) : List Nat := + (List.range laneCount).map fun i => totalCellCount * (i + 1) / laneCount - 1 + +def isLaneStart (laneCount index : Nat) : Bool := + (laneStarts laneCount).contains index + +def familyAndIndex (globalIndex : Nat) : Family × Nat := + if globalIndex < lowCellCount then (.low, globalIndex) + else (.high, globalIndex - lowCellCount) + +def importText (laneCount globalIndex : Nat) : String := + if isLaneStart laneCount globalIndex then + "import LnProof.Floor.CarryIndependent.Approximation\n" + else + let (family, index) := familyAndIndex (globalIndex - 1) + s!"import LnProof.Cert.{cellModuleName family index}\n" + +def sourceText (family : Family) (candidate : Nat) : String := + s!"{familyCertName family} {candidate}" + +def hornerCellText (laneCount globalIndex : Nat) (family : Family) + (index : Nat) (cell : BernsteinCell) (candidate bits : Nat) + (shifted : List Int) : String := + let stem := cellName family index + let source := sourceText family candidate + let lo := cell.spec.lo + let hi := cell.spec.hi + let width := hi - lo + importText laneCount globalIndex ++ + "import Common.Foundation.PackedShift\n\n" ++ + "namespace LnFloorCarry\n\n" ++ + "open Common.Poly\n\n" ++ + "set_option maxRecDepth 100000\n" ++ + s!"set_option exponentiation.threshold {bits}\n\n" ++ + litText s!"{stem}Shifted" shifted ++ + s!"theorem {stem}Candidate :\n" ++ + s!" approximationEnvelopeCandidate {hi} {candidate} := by\n" ++ + s!" change {candidate} ^ 2 * ({hi} + 1) ≤ approximationEnvelopeSquareBudget\n" ++ + " decide +kernel\n\n" ++ + s!"theorem {stem}Radix :\n" ++ + s!" evalPoly {stem}Shifted (((2 ^ {bits} : Nat) : Int)) =\n" ++ + s!" evalPoly ({source})\n" ++ + s!" ({lo} + (((2 ^ {bits} : Nat) : Int))) := by\n" ++ + " decide +kernel\n\n" ++ + s!"theorem {stem}ScalarCheck :\n" ++ + s!" checkPackedShiftScalars {bits}\n" ++ + s!" (literalPackedShiftScalars {bits} ({source})\n" ++ + s!" {stem}Shifted {lo}) = true := by\n" ++ + " decide +kernel\n\n" ++ + s!"theorem {stem}HornerCheck :\n" ++ + s!" decide (0 ≤ (hornerIv {stem}Shifted 0 {width}).1) = true := by\n" ++ + " decide +kernel\n\n" ++ + s!"theorem {stem}Check :\n" ++ + s!" checkPackedCell {bits} {stem}Shifted {width}\n" ++ + s!" (literalPackedShiftScalars {bits} ({source})\n" ++ + s!" {stem}Shifted {lo}) = true := by\n" ++ + " simp only [checkPackedCell, Bool.and_eq_true]\n" ++ + s!" exact ⟨⟨{stem}ScalarCheck, by decide +kernel⟩,\n" ++ + s!" {stem}HornerCheck⟩\n\n" ++ + s!"theorem {stem}NonnegOn :\n" ++ + s!" NonnegOn ({source}) {lo} {hi} := by\n" ++ + s!" have hevidence := literalPackedShiftEvidence {stem}Radix\n" ++ + s!" simpa using checkPackedCell_nonnegOn hevidence {stem}Check\n\n" ++ + "end LnFloorCarry\n" + +def bernsteinCellText (laneCount globalIndex : Nat) (family : Family) + (index : Nat) (cell : BernsteinCell) (candidate : Nat) : String := + let stem := cellName family index + let source := sourceText family candidate + let lo := cell.spec.lo + let hi := cell.spec.hi + importText laneCount globalIndex ++ + "import Common.Foundation.Bernstein\n\n" ++ + "namespace LnFloorCarry\n\n" ++ + "open Common.Poly\n\n" ++ + "set_option maxRecDepth 100000\n\n" ++ + weightsText s!"{stem}Weights" cell.weights ++ + s!"theorem {stem}Candidate :\n" ++ + s!" approximationEnvelopeCandidate {hi} {candidate} := by\n" ++ + s!" change {candidate} ^ 2 * ({hi} + 1) ≤ approximationEnvelopeSquareBudget\n" ++ + " decide +kernel\n\n" ++ + s!"theorem {stem}Check :\n" ++ + s!" checkBernsteinKWithWitness {cell.spec.bits} ({source})\n" ++ + s!" {lo} {hi} {stem}Weights = true := by\n" ++ + " decide +kernel\n\n" ++ + s!"theorem {stem}NonnegOn :\n" ++ + s!" NonnegOn ({source}) {lo} {hi} :=\n" ++ + s!" checkBernsteinKWithWitness_nonnegOn {cell.spec.bits} ({source})\n" ++ + s!" {lo} {hi} {stem}Weights {stem}Check\n\n" ++ + "end LnFloorCarry\n" + +def emitCell (outDir : System.FilePath) (laneCount globalIndex : Nat) + (family : Family) (index : Nat) (cell : BernsteinCell) : IO CellMeta := do + let lo := cell.spec.lo.toNat + let hi := cell.spec.hi.toNat + let candidate := candidateAt hi + let C := certificate family candidate + let shifted := polyShiftM C cell.spec.lo + let horner := decide (0 ≤ (hornerIv shifted 0 (cell.spec.hi - cell.spec.lo)).1) + let kind := if horner then CellKind.horner else CellKind.bernstein + let text := if horner then + hornerCellText laneCount globalIndex family index cell candidate + (packedBits C shifted cell.spec.lo) shifted + else + bernsteinCellText laneCount globalIndex family index cell candidate + IO.FS.writeFile (outDir / s!"{cellModuleName family index}.lean") text + let artifactLength := if horner then shifted.length else cell.weights.length + pure ⟨family, index, lo, hi, candidate, kind, artifactLength⟩ + +def emitFamily (outDir : System.FilePath) (laneCount globalOffset : Nat) + (family : Family) (cells : List BernsteinCell) : IO (List CellMeta) := do + let mut result := [] + for (cell, index) in cells.zipIdx do + let cellMeta ← emitCell outDir laneCount (globalOffset + index) family index cell + result := cellMeta :: result + pure result.reverse + +def bernsteinIndices (cells : List CellMeta) : List Nat := + cells.filterMap fun cell => + match cell.kind with + | .horner => none + | .bernstein => some cell.index + +def contiguousCover : Nat → List CellMeta → Bool + | next, [] => next == LnFloorCarry.approximationMaxU + 1 + | next, cell :: cells => + cell.lo == next && contiguousCover (cell.hi + 1) cells + +def aggregateImports (laneCount : Nat) : String := + String.join <| (laneTips laneCount).map fun tip => + let (family, index) := familyAndIndex tip + s!"import LnProof.Cert.{cellModuleName family index}\n" + +def coverStep (cellMeta : CellMeta) (last : Bool) : String := + let stem := cellName cellMeta.family cellMeta.index + let result := + s!"⟨{cellMeta.hi}, {cellMeta.candidate}, by omega, {stem}Candidate, " ++ + s!"{stem}NonnegOn (u : Int) (by exact_mod_cast hlo) " ++ + "(by exact_mod_cast hhi)⟩" + if last then + s!" have hhi : u ≤ {cellMeta.hi} := by simpa [approximationMaxU] using hu\n" ++ + s!" exact {result}\n" + else + s!" by_cases hhi : u ≤ {cellMeta.hi}\n" ++ + s!" · exact {result}\n" ++ + s!" have hlo : {cellMeta.hi + 1} ≤ u := by omega\n" + +def coverText (family : Family) (cells : List CellMeta) : String := + let cert := familyCertName family + let name := familyCoverName family + let header := + s!"theorem {name} " ++ "{u : Nat}" ++ + " (hu : u ≤ approximationMaxU) :\n" ++ + s!" ∃ hi a, u ≤ hi ∧ approximationEnvelopeCandidate hi a ∧\n" ++ + s!" 0 ≤ evalPoly ({cert} a) (u : Int) := by\n" ++ + " have hlo : 0 ≤ u := Nat.zero_le u\n" + let steps := String.join <| cells.zipIdx.map fun (cellMeta, i) => + coverStep cellMeta (i + 1 == cells.length) + header ++ steps ++ "\n" + +def aggregateText (laneCount : Nat) (low high : List CellMeta) : String := + aggregateImports laneCount ++ + "\nnamespace LnFloorCarry\n\n" ++ + "open Common.Poly\n\n" ++ + "set_option maxRecDepth 100000\n\n" ++ + coverText .low low ++ coverText .high high ++ + "end LnFloorCarry\n" + +def hornerCorrelationPErrorNum : List Int := + [2 ^ 274, 2 ^ 187, 2 ^ 90, 1] + +def hornerCorrelationDErrorNum : List Int := + [2 ^ 273, 2 ^ 178, 2 ^ 90, 1] + +def hornerCorrelationDNum : List Int := polyNeg LnYul.QQc + +def hornerCorrelationNum : List Int := + polyScale (2 ^ 112) <| + polyAdd + (polyScale (2 ^ 29) + (polyMul LnYul.PPc hornerCorrelationDErrorNum)) + (polyMul hornerCorrelationPErrorNum hornerCorrelationDNum) + +def hornerCorrelationDen : List Int := + polyMul hornerCorrelationDNum + (polyAdd hornerCorrelationDNum + (polyScale (2 ^ 113) hornerCorrelationDErrorNum)) + +def hornerCorrelationEndpointNum : Int := + evalPoly hornerCorrelationNum (LnYul.Uc : Int) + +def hornerCorrelationEndpointDen : Int := + evalPoly hornerCorrelationDen (LnYul.Uc : Int) + +def hornerCorrelationCert : List Int := + polyAdd + (polyScale hornerCorrelationEndpointNum hornerCorrelationDen) + (polyScale (-hornerCorrelationEndpointDen) hornerCorrelationNum) + +def correlationDefinitionsText : String := + "def hornerCorrelationPErrorNum : List Int :=\n" ++ + " [2 ^ 274, 2 ^ 187, 2 ^ 90, 1]\n\n" ++ + "def hornerCorrelationDErrorNum : List Int :=\n" ++ + " [2 ^ 273, 2 ^ 178, 2 ^ 90, 1]\n\n" ++ + "def hornerCorrelationDNum : List Int := polyNeg QQc\n\n" ++ + "def hornerCorrelationNum : List Int :=\n" ++ + " polyScale (2 ^ 112) <|\n" ++ + " polyAdd\n" ++ + " (polyScale (2 ^ 29)\n" ++ + " (polyMul PPc hornerCorrelationDErrorNum))\n" ++ + " (polyMul hornerCorrelationPErrorNum hornerCorrelationDNum)\n\n" ++ + "def hornerCorrelationDen : List Int :=\n" ++ + " polyMul hornerCorrelationDNum\n" ++ + " (polyAdd hornerCorrelationDNum\n" ++ + " (polyScale (2 ^ 113) hornerCorrelationDErrorNum))\n\n" + +def hornerCorrelationText (bits : Nat) (weights : List Int) : String := + "import LnProof.Model.Body\n" ++ + "import Common.Foundation.Bernstein\n\n" ++ + "namespace LnFloorCarry\n\n" ++ + "open Common.Poly LnYul\n\n" ++ + "set_option maxRecDepth 100000\n\n" ++ + correlationDefinitionsText ++ + "def endpointNum : Int := evalPoly hornerCorrelationNum (Uc : Int)\n" ++ + "def endpointDen : Int := evalPoly hornerCorrelationDen (Uc : Int)\n\n" ++ + "def hornerCorrelationCert : List Int :=\n" ++ + " polyAdd (polyScale endpointNum hornerCorrelationDen)\n" ++ + " (polyScale (-endpointDen) hornerCorrelationNum)\n\n" ++ + weightsText "hornerCorrelationWeights" weights ++ + "theorem hornerCorrelationCheck :\n" ++ + s!" checkBernsteinKWithWitness {bits} hornerCorrelationCert\n" ++ + " 0 (Uc : Int) hornerCorrelationWeights = true := by\n" ++ + " decide +kernel\n\n" ++ + "theorem hornerCorrelation_nonnegOn :\n" ++ + " NonnegOn hornerCorrelationCert 0 (Uc : Int) :=\n" ++ + s!" checkBernsteinKWithWitness_nonnegOn {bits} hornerCorrelationCert\n" ++ + " 0 (Uc : Int) hornerCorrelationWeights hornerCorrelationCheck\n\n" ++ + "theorem hornerCorrelationCert_eval (u : Int) :\n" ++ + " evalPoly hornerCorrelationCert u =\n" ++ + " endpointNum * evalPoly hornerCorrelationDen u -\n" ++ + " endpointDen * evalPoly hornerCorrelationNum u := by\n" ++ + " simp only [hornerCorrelationCert, evalPoly_polyAdd, evalPoly_polyScale]\n" ++ + " ring\n\n" ++ + "theorem hornerCorrelation_nonneg {u : Int}\n" ++ + " (hlo : 0 ≤ u) (hhi : u ≤ (Uc : Int)) :\n" ++ + " 0 ≤ evalPoly hornerCorrelationCert u :=\n" ++ + " hornerCorrelation_nonnegOn u hlo hhi\n\n" ++ + "end LnFloorCarry\n" + +def emitHornerCorrelation (outDir : System.FilePath) : IO Unit := do + let weights := generatedWeights hornerCorrelationCert 0 LnYul.Uc + let some bits := firstBernsteinBWithWeights hornerCorrelationCert 0 LnYul.Uc weights 128 + | throw (IO.userError "Horner-correlation certificate was rejected") + IO.FS.writeFile (outDir / "HornerCorrelation.lean") + (hornerCorrelationText bits weights) + +def expectedOutputs : List String := + (List.range lowCellCount).map (fun i => s!"{cellModuleName .low i}.lean") ++ + (List.range highCellCount).map (fun i => s!"{cellModuleName .high i}.lean") ++ + ["Approximation.lean", "HornerCorrelation.lean"] + +def generate (laneCount : Nat) : IO Unit := do + unless laneCount == 2 || laneCount == 4 || laneCount == 8 do + throw (IO.userError "dependencyLaneCount must be 2, 4, or 8") + let outDir : System.FilePath := "LnProof/Cert" + let some lowCells := allCells .low + | throw (IO.userError "low approximation cover failed") + unless lowCells.length == lowCellCount do + throw (IO.userError s!"expected {lowCellCount} low cells, got {lowCells.length}") + let low ← emitFamily outDir laneCount 0 .low lowCells + let some highCells := allCells .high + | throw (IO.userError "high approximation cover failed") + unless highCells.length == highCellCount do + throw (IO.userError s!"expected {highCellCount} high cells, got {highCells.length}") + let high ← emitFamily outDir laneCount lowCellCount .high highCells + unless contiguousCover 0 low do + throw (IO.userError "low approximation cells are not contiguous") + unless contiguousCover 0 high do + throw (IO.userError "high approximation cells are not contiguous") + unless bernsteinIndices low == lowBernsteinIndices do + throw (IO.userError s!"unexpected low Bernstein cells: {bernsteinIndices low}") + unless bernsteinIndices high == highBernsteinIndices do + throw (IO.userError s!"unexpected high Bernstein cells: {bernsteinIndices high}") + let hornerCount := (low ++ high).countP fun cell => + match cell.kind with + | .horner => true + | .bernstein => false + unless hornerCount == 291 do + throw (IO.userError s!"expected 291 Horner cells, got {hornerCount}") + let literalCount := (low ++ high).foldl (fun n cell => n + cell.artifactLength) 0 + unless literalCount == 14701 do + throw (IO.userError s!"expected 14701 coefficient literals, got {literalCount}") + reconcileOutputs outDir + ["ApproximationLowC", "ApproximationHighC", "Approximation.lean", + "HornerCorrelation.lean"] expectedOutputs + IO.FS.writeFile (outDir / "Approximation.lean") + (aggregateText laneCount low high) + emitHornerCorrelation outDir + +def main : IO Unit := + match dependencyLaneCount with + | none => throw (IO.userError "dependencyLaneCount is not selected") + | some laneCount => generate laneCount + +end GenApproximationCert + +#eval GenApproximationCert.main diff --git a/formal/ln/LnProof/GenBranchCertHard.lean b/formal/ln/LnProof/GenBranchCertHard.lean deleted file mode 100644 index 4ea6696fb..000000000 --- a/formal/ln/LnProof/GenBranchCertHard.lean +++ /dev/null @@ -1,50 +0,0 @@ -import LnProof.Error.Core.BranchCertHardDefs -import Common.GenCover - -namespace GenBranchCertHard - -open Common.GenCover - -def outDir : String := "LnProof/Cert" -def chunkSize : Nat := 16 -def caseCount : Nat := 159 - -def chunkCount : Nat := (caseCount + chunkSize - 1) / chunkSize - -def chunkImport (chunk : Nat) : String := - if chunk = 0 ∨ chunk = chunkCount / 2 then - "LnProof.Error.Core.BranchCertHardDefs" - else - s!"LnProof.Cert.HardMantissaLtGapC{pad2 (chunk - 1)}" - -def chunkText (chunk start count : Nat) : String := - s!"import {chunkImport chunk}\n\nnamespace LnFloorCert\n\nset_option maxRecDepth 100000\n\ntheorem hardMantissaLtGapBranch_chunk{pad2 chunk} :\n (List.range {count}).all (fun i => hardMantissaLtGapBranchB (i + {start})) = true := by\n decide +kernel\n\nend LnFloorCert\n" - -def aggregateText : String := - let cases := (List.range chunkCount).map fun chunk => - let offset := chunk * chunkSize - let upper := min caseCount (offset + chunkSize) - if offset = 0 then s!"i < {upper}" else s!"({offset} ≤ i ∧ i < {upper})" - let caseProofs := (List.range chunkCount).map fun chunk => - s!" · exact hardMantissaLtGapBranch_of_chunk hardMantissaLtGapBranch_chunk{pad2 chunk}\n (by omega) (by omega)" - s!"import LnProof.Cert.HardMantissaLtGapC04\nimport LnProof.Cert.HardMantissaLtGapC09\n\nnamespace LnFloorCert\n\nset_option maxRecDepth 100000\n\nprivate theorem hardMantissaLtGapBranch_of_chunk {lb}start count i : Nat{rb}\n (hchunk : (List.range count).all\n (fun j => hardMantissaLtGapBranchB (j + start)) = true)\n (hlo : start ≤ i + 1) (hhi : i + 1 < start + count) :\n hardMantissaLtGapBranchB (i + 1) = true := by\n have h := List.all_eq_true.mp hchunk (i + 1 - start)\n (List.mem_range.mpr (by omega))\n rw [show i + 1 - start + start = i + 1 by omega] at h\n exact h\n\ntheorem hardMantissaLtGapBranch_all :\n (List.range {caseCount}).all (fun i => hardMantissaLtGapBranchB (i + 1)) = true := by\n rw [List.all_eq_true]\n intro i hi\n have hlt : i < {caseCount} := List.mem_range.mp hi\n have hcases :\n {String.intercalate " ∨\n " cases} := by\n omega\n rcases hcases with {String.intercalate " | " ((List.range chunkCount).map fun _ => "h")}\n{String.intercalate "\n" caseProofs}\n\nend LnFloorCert\n" -where - lb := "{" - rb := "}" - -def expectedOutputs : List String := - "HardMantissaLtGap.lean" :: (List.range chunkCount).map fun i => - s!"HardMantissaLtGapC{pad2 i}.lean" - -def generate : IO Unit := do - reconcileOutputs outDir ["HardMantissaLtGap"] expectedOutputs - let chunkOutputs := expectedOutputs.drop 1 - for (name, chunk) in chunkOutputs.zipIdx do - let offset := chunk * chunkSize - let count := min chunkSize (caseCount - offset) - IO.FS.writeFile s!"{outDir}/{name}" (chunkText chunk (offset + 1) count) - IO.FS.writeFile s!"{outDir}/HardMantissaLtGap.lean" aggregateText - -end GenBranchCertHard - -#eval GenBranchCertHard.generate diff --git a/formal/ln/LnProof/GenCover.lean b/formal/ln/LnProof/GenCover.lean index 994d2d921..f0802212b 100644 --- a/formal/ln/LnProof/GenCover.lean +++ b/formal/ln/LnProof/GenCover.lean @@ -1,6 +1,4 @@ -import LnProof.Cert.FloorCertGeUpLit import LnProof.Cert.FloorCertGeLoLit -import LnProof.Cert.FloorCertLtUpLit import LnProof.Cert.FloorCertLtLoLit import Common.Foundation.KroneckerShift import Common.GenCover @@ -12,10 +10,10 @@ Greedily walks `[lo, hi]` for a certificate polynomial, computing at each anchor `a` the largest cell width `w` with `0 ≤ (hornerIv (kShiftWitness kB C a) 0 w).1` — exactly the predicate the in-kernel `checkCoverK` decides, so the emitted covers are guaranteed `decide`-acceptable. Writes one `…C.lean` cell file -per sub-cell and prints the `NonnegOn` ladder, its pointwise compatibility -theorem, and the import block for the cover module. +per sub-cell and one aggregate module containing the complete literal +`NonnegOn` proof. -Run with `lake env lean GenCover.lean` after building the four +Run with `lake env lean GenCover.lean` after building the two `LnProof.Cert.FloorCert*Lit` modules and `Common.GenCover`. -/ @@ -23,43 +21,38 @@ open Common.Poly LnFloorCert Common.GenCover namespace GenCover -/-- Emit cell files `.lean` and return the ladder text. -/ -def emit (nm litModule litName symName evalEqName modPrefix cellPrefix nonnegName : String) +/-- Render the aggregate that imports every cell and joins their intervals. -/ +def aggregateText (litName modPrefix cellPrefix nonnegName : String) + (cells : List (Int × Int)) (lo hi : Int) : String := + let imports := String.join <| cells.zipIdx.map fun (_, i) => + s!"import LnProof.Cert.{modPrefix}{pad2 i}\n" + let header := + "\nnamespace LnFloorCert\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\n" ++ + s!"theorem {nonnegName} : NonnegOn {litName} {lo} {hi} := by\n" ++ + " intro m h1 h2\n" + let n := cells.length + let ladder := String.join <| cells.zipIdx.map fun ((a, w), i) => + ladderStep s!"{cellPrefix}{pad2 i}" "m" a w (i + 1 == n) + imports ++ header ++ ladder ++ "\nend LnFloorCert\n" + +/-- Emit the complete declared output set for one cover. -/ +def emit (nm litModule litName modPrefix cellPrefix aggregateModule nonnegName : String) (C : List Int) (lo hi : Int) : IO Unit := do let (ok, cells) := walk C lo hi - IO.println s!"-- {nm}: reached={ok} ncells={cells.length}" if ! ok then - IO.println s!"-- FAILED tail: {cells.drop (cells.length - 2)}" - return - let expected := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" - reconcileOutputs "LnProof/Cert" [modPrefix] expected - -- write one cell file per sub-cell + throw <| IO.userError s!"{nm}: cover did not reach {hi}; tail={cells.drop (cells.length - 2)}" + let cellOutputs := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" + let aggregateOutput := s!"{aggregateModule}.lean" + let expected := cellOutputs ++ [aggregateOutput] + reconcileOutputs "LnProof/Cert" [modPrefix, aggregateModule] expected for (aw, i) in cells.zipIdx do let (a, w) := aw let nn := pad2 i IO.FS.writeFile s!"LnProof/Cert/{modPrefix}{nn}.lean" (cellText s!"LnProof.Cert.{litModule}" "LnFloorCert" s!"{cellPrefix}{nn}" litName a w) - -- ladder + imports - let mut imps := "" - for (_, i) in cells.zipIdx do - imps := imps ++ s!"import LnProof.Cert.{modPrefix}{pad2 i}\n" - IO.println "==== IMPORTS ====" - IO.println imps - IO.println "==== LADDER ====" - let lb := "{" - let rb := "}" - IO.println s!"theorem {nonnegName}On : NonnegOn {symName} {lo} {hi} := by" - IO.println " intro m h1 h2" - IO.println s!" have hev := {evalEqName} m" - IO.println " rw [hev]" - let n := cells.length - for (aw, i) in cells.zipIdx do - let (a, w) := aw - IO.print (ladderStep s!"{cellPrefix}{pad2 i}" "m" a w (i + 1 == n)) - IO.println "" - IO.println s!"theorem {nonnegName} {lb}m : Int{rb} (h1 : {lo} ≤ m) (h2 : m ≤ {hi}) :" - IO.println s!" 0 ≤ evalPoly {symName} m :=" - IO.println s!" {nonnegName}On m h1 h2" + IO.FS.writeFile s!"LnProof/Cert/{aggregateOutput}" + (aggregateText litName modPrefix cellPrefix nonnegName cells lo hi) + IO.println s!"{nm}: wrote {cells.length} cells and {aggregateOutput}" end GenCover @@ -70,10 +63,7 @@ def hiLT : Int := 56022770974786139918731938181 -- Sc - 46 def loGE : Int := 56022770974786139918731938273 -- Sc + 46 def hiGE : Int := 79228162514264337593543950335 -- 2^96 - 1 --- Generate the floor cert covers: never-overshoot upper forms (GeUp/LtUp) and --- not-too-low lower forms (GeLo/LtLo). The cover modules keep their hand-written --- eval_eq; only the cell files and the `NonnegOn` ladder are generated. -#eval emit "certGeUp" "FloorCertGeUpLit" "certGeUpLit" "certGeUp" "geUp_eval_eq" "FloorCertGeUpC" "geUp_cell" "geUp_nonneg" certGeUpLit loGE hiGE -#eval emit "certLtUp" "FloorCertLtUpLit" "certLtUpLit" "certLtUp" "ltUp_eval_eq" "FloorCertLtUpC" "ltUp_cell" "ltUp_nonneg" certLtUpLit loLT hiLT -#eval emit "certGeLo" "FloorCertGeLoLit" "certGeLoLit" "certGeLo" "geLo_eval_eq" "FloorCertGeLoC" "geLo_cell" "geLo_nonneg" certGeLoLit loGE hiGE -#eval emit "certLtLo" "FloorCertLtLoLit" "certLtLoLit" "certLtLo" "ltLo_eval_eq" "FloorCertLtLoC" "ltLo_cell" "ltLo_nonneg" certLtLoLit loLT hiLT +#eval emit "certGeLo" "FloorCertGeLoLit" "certGeLoLit" "FloorCertGeLoC" + "geLo_cell" "FloorCertGeLoCover" "certGeLoLit_nonnegOn" certGeLoLit loGE hiGE +#eval emit "certLtLo" "FloorCertLtLoLit" "certLtLoLit" "FloorCertLtLoC" + "ltLo_cell" "FloorCertLtLoCover" "certLtLoLit_nonnegOn" certLtLoLit loLT hiLT diff --git a/formal/ln/LnProof/GenErrLit.lean b/formal/ln/LnProof/GenErrLit.lean index 8d2f00144..78c29ecc0 100644 --- a/formal/ln/LnProof/GenErrLit.lean +++ b/formal/ln/LnProof/GenErrLit.lean @@ -1,30 +1,22 @@ -import LnProof.Cert.FloorCertGeLoLit import LnProof.Cert.FloorCertLtLoLit -import LnProof.Error.Core.ExpMargin import LnProof.Error.Core.Budget import Common.Foundation.KroneckerShift import Common.GenCover -/-! Generate the error-bound cert literals (ErrCertLtLit / ErrCertGeLit) and -their covers for the current BIASc and `lnErrorBoundNum`. Computes -`certErrLt`/`certErrGe` -inline (mirroring the ErrCert*Bridge constructions) so it does not depend on the -bridges building, then walks the `checkCoverK` covers (literal signature, as the -checked `errLt_nonnegOn`/`errGe_nonnegOn` theorems use). -/ +/-! Generate the error-bound certificate literal `ErrCertLtLit` and its cover +for the current `BIASc` and `lnErrorBoundNum`. Computes `certErrLt` inline so +generation does not depend on the bridge building, then walks the `checkCoverK` +cover used by `errLt_nonnegOn`. -/ open Common.Poly LnFloorCert Common.Exp LnFloor LnYul open Common.GenCover hiding litText namespace GenErrLit --- All derived from the model inputs (BIASc in the model and `lnErrorBoundNum` --- in ErrorBoundCert), so generation tracks changes to those. def biasCapNum : Nat := (Common.Exp.expNum 130 (BIASc * 2 ^ 27) QS * (10 ^ 18 * 10 ^ 42)) / (Common.Exp.fact 130 * QS ^ 130) def errLtK : Int := (10 ^ 31 * (10 ^ 18 * 10 ^ 42) * lnErrQ * (10 ^ 40 + 160) : Nat) -def errGeK : Int := errLtK def errLtW : Nat := biasCapNum * (lnErrQ + minPosAvail) * wadRayStrictDen * 10 ^ 40 -def errGeW : Nat := biasCapNum * (lnErrQ + (692115493 * 2 ^ 99 + 2 ^ 27 * 10 ^ 9)) * wadRayStrictDen * 10 ^ 40 def cLt : List Int := polyAdd (polyScale ((errLtW : Int) * (fact 23 : Int)) (polyPow ltTDLit 23)) @@ -32,24 +24,26 @@ def cLt : List Int := (polyAdd (polyScale 23 (polyMul (expPolyNum ltTNLit ltTDLit 22) ltTDLit)) (polyScale 2 (polyPow ltTNLit 23))))) -def cGe : List Int := - expMarginPoly 22 geTN2bLit geTD2bLit (polyScale errGeK [1, 1]) errGeW +/-- A literal block wrapped in the namespace consumed by the cover. -/ +def litText (name : String) (c : List Int) : String := + "namespace LnFloorCert\n\n" ++ Common.GenCover.litText name c ++ "end LnFloorCert\n" -/-- Walk `[lo,hi]`, write one cell file per sub-cell, and write the complete -cover module `coverMod` (cell imports + the literal-signature `nonnegName` -ladder). The error covers carry no hand-written content, so they are fully -generated. -/ +/-- Emit the literal, cells, and aggregate for the complete cover. -/ def emit (litFile litName coverMod modPrefix cellPrefix nonnegName : String) (C : List Int) (lo hi : Int) : IO Unit := do let (ok, cells) := walk C lo hi IO.println s!"-- {coverMod}: reached={ok} ncells={cells.length}" - if ! ok then IO.println s!"-- FAILED tail: {cells.drop (cells.length-2)}"; return - let expected := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" - reconcileOutputs "LnProof/Cert" [modPrefix] expected + if ! ok then + throw <| IO.userError s!"{coverMod}: cover did not reach {hi}; tail={cells.drop (cells.length - 2)}" + let cellOutputs := cells.zipIdx.map fun (_, i) => s!"{modPrefix}{pad2 i}.lean" + let litOutput := s!"{litFile}.lean" + let coverOutput := s!"{coverMod}.lean" + let expected := cellOutputs ++ [litOutput, coverOutput] + reconcileOutputs "LnProof/Cert" [modPrefix, litFile, coverMod] expected + IO.FS.writeFile s!"LnProof/Cert/{litOutput}" (litText litName (ptrim C)) for (aw, i) in cells.zipIdx do let (a, w) := aw IO.FS.writeFile s!"LnProof/Cert/{modPrefix}{pad2 i}.lean" (cellText s!"LnProof.Cert.{litFile}" "LnFloorCert" s!"{cellPrefix}{pad2 i}" litName a w) - let lb := "{"; let rb := "}" let mut s := "" for (_, i) in cells.zipIdx do s := s ++ s!"import LnProof.Cert.{modPrefix}{pad2 i}\n" s := s ++ s!"\nnamespace LnFloorCert\nopen Common.Poly\n\nset_option maxRecDepth 100000\n\n" @@ -58,25 +52,13 @@ def emit (litFile litName coverMod modPrefix cellPrefix nonnegName : String) (C for (aw, i) in cells.zipIdx do let (a, w) := aw s := s ++ ladderStep s!"{cellPrefix}{pad2 i}" "m" a w (i + 1 == n) - s := s ++ s!"\ntheorem {nonnegName} {lb}m : Int{rb} (h1 : {lo} ≤ m) (h2 : m ≤ {hi}) :\n 0 ≤ evalPoly {litName} m :=\n {nonnegName}On m h1 h2\n" s := s ++ "\nend LnFloorCert\n" - IO.FS.writeFile s!"LnProof/Cert/{coverMod}.lean" s - -/-- A shared-emitter literal block wrapped in the `LnFloorCert` namespace (each error-cert -literal is written to its own self-contained module). -/ -def litText (name : String) (c : List Int) : String := - "namespace LnFloorCert\n\n" ++ Common.GenCover.litText name c ++ "end LnFloorCert\n" + IO.FS.writeFile s!"LnProof/Cert/{coverOutput}" s end GenErrLit open GenErrLit def loLT : Int := 39614081257132168796771975168 def hiLT : Int := 56022770974786139918731938181 -def loGE : Int := 56022770974786139918731938273 -def hiGE : Int := 79228162514264337593543950335 #eval do - IO.FS.writeFile "LnProof/Cert/ErrCertLtLit.lean" (litText "certErrLtLit" (ptrim cLt)) - IO.FS.writeFile "LnProof/Cert/ErrCertGeLit.lean" (litText "certErrGeLit" (ptrim cGe)) - IO.println "literals written" emit "ErrCertLtLit" "certErrLtLit" "ErrCertLt" "ErrCertLtC" "errLt_cell" "errLt_nonneg" (ptrim cLt) loLT hiLT - emit "ErrCertGeLit" "certErrGeLit" "ErrCertGe" "ErrCertGeC" "errGe_cell" "errGe_nonneg" (ptrim cGe) loGE hiGE diff --git a/formal/ln/LnProof/GenFloorCertLit.lean b/formal/ln/LnProof/GenFloorCertLit.lean index b37f18184..7d5cab4a1 100644 --- a/formal/ln/LnProof/GenFloorCertLit.lean +++ b/formal/ln/LnProof/GenFloorCertLit.lean @@ -11,21 +11,11 @@ def fileText (body : String) : String := body ++ "end LnFloorCert\n" -def geUpText : String := fileText <| - litText "geTNLit" geTN ++ - litText "geTDLit" geTD ++ - litText "certGeUpLit" (ptrim certGeUp) - def geLoText : String := fileText <| litText "geTN2bLit" geTN2b ++ litText "geTD2bLit" geTD2b ++ litText "certGeLoLit" (ptrim certGeLo) -def ltUpText : String := fileText <| - litText "ltTN2bLit" ltTN2b ++ - litText "ltTD2bLit" ltTD2b ++ - litText "certLtUpLit" (ptrim certLtUp) - def ltLoText : String := fileText <| litText "ltTNLit" ltTN ++ litText "ltTDLit" ltTD ++ @@ -35,11 +25,7 @@ end GenFloorCertLit #eval do reconcileOutputs "LnProof/Cert" - ["FloorCertLit", "FloorCertGeUpLit", "FloorCertGeLoLit", "FloorCertLtUpLit", - "FloorCertLtLoLit"] - ["FloorCertGeUpLit.lean", "FloorCertGeLoLit.lean", "FloorCertLtUpLit.lean", - "FloorCertLtLoLit.lean"] - IO.FS.writeFile "LnProof/Cert/FloorCertGeUpLit.lean" GenFloorCertLit.geUpText + ["FloorCertGeLoLit", "FloorCertLtLoLit"] + ["FloorCertGeLoLit.lean", "FloorCertLtLoLit.lean"] IO.FS.writeFile "LnProof/Cert/FloorCertGeLoLit.lean" GenFloorCertLit.geLoText - IO.FS.writeFile "LnProof/Cert/FloorCertLtUpLit.lean" GenFloorCertLit.ltUpText IO.FS.writeFile "LnProof/Cert/FloorCertLtLoLit.lean" GenFloorCertLit.ltLoText diff --git a/formal/ln/LnProof/LnProof.lean b/formal/ln/LnProof/LnProof.lean index ece0d137c..5d8d52953 100644 --- a/formal/ln/LnProof/LnProof.lean +++ b/formal/ln/LnProof/LnProof.lean @@ -1,4 +1,18 @@ --- This module serves as the root of the `LnProof` library. --- `Theorems` is the signpost: it states every proven property of the compiled --- runtime and runs the axiom gate, transitively importing the whole proof. +-- The library root aggregates the public proof layers and the runtime theorem +-- signpost, whose axiom gate checks every published property. +import LnProof.Foundation.Word +import LnProof.Foundation.WordDiv +import Common.Foundation.ExpSum +import Common.Foundation.Poly +import Common.Foundation.ShiftCert +import Common.Foundation.Kronecker +import Common.Foundation.KroneckerShift +import LnProof.Spec.Real +import LnProof.Spec.Cut +import LnProof.Mono.Top +import LnProof.Seam.RuntimeModel +import LnProof.Seam.RealLog +import LnProof.Floor.Spec +import LnProof.Floor.CutEquiv +import LnProof.Error.Bound import LnProof.Theorems diff --git a/formal/ln/LnProof/LnProof/Error.lean b/formal/ln/LnProof/LnProof/Error.lean deleted file mode 100644 index 40d46326c..000000000 --- a/formal/ln/LnProof/LnProof/Error.lean +++ /dev/null @@ -1,9 +0,0 @@ -/-! -# Error facade - -The model-level `1.6986`-ulp error bound. `Bound` is the published cut -statement (`lnWadToRayBody_error_bound_1_6986`); the rest of the `Error/` -directory holds the cell covers, factored-octave caps, and certificate -bridges that discharge it. The runtime transport is `LnProof.ErrorBoundRuntime`. --/ -import LnProof.Error.Bound diff --git a/formal/ln/LnProof/LnProof/Error/Bound.lean b/formal/ln/LnProof/LnProof/Error/Bound.lean index c6f901082..3fa3d3477 100644 --- a/formal/ln/LnProof/LnProof/Error/Bound.lean +++ b/formal/ln/LnProof/LnProof/Error/Bound.lean @@ -1,4 +1,4 @@ -import LnProof.Error.Core +import LnProof.Error.Core.Assembly import LnProof.Error.LtBridge open FormalYul @@ -25,6 +25,89 @@ open LnYul LnFloor Common.Exp Common.Poly attribute [local irreducible] lnWadToRayBody +theorem posPhaseNatLt_cast {m c : Nat} + (hX : int256 (x1W (zWord m)) ≤ 0) + (hneg : posNegXNat m ≤ posConstNat c) : + ((posPhaseNatLt m c : Nat) : Int) = + posPhaseI m c * (lnErrorBoundDen : Int) := by + have hconst := posConstNat_cast c + have hnegc := posNegXNat_cast (m := m) hX + have hsub : ((posConstNat c - posNegXNat m : Nat) : Int) = + ((posConstNat c : Nat) : Int) - ((posNegXNat m : Nat) : Int) := by + omega + unfold posPhaseNatLt + rw [hsub, hconst, hnegc] + unfold posPhaseI + rw [Int.add_mul, Int.add_mul, Int.add_mul] + rw [show (-int256 (x1W (zWord m)) * lnPhaseScaleI) * + (lnErrorBoundDen : Int) = + -(int256 (x1W (zWord m)) * lnPhaseScaleI * (lnErrorBoundDen : Int)) by + rw [Int.neg_mul, Int.neg_mul]] + omega + +theorem minPosAvail_cast : + ((minPosAvail : Nat) : Int) = + (lnErrorExtraNum : Int) * twoPow99I + + twoPow27I * (lnErrorBoundDen : Int) := by + unfold minPosAvail lnPhaseExtraArg twoPow99N twoPow27N twoPow99I twoPow27I + unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen + decide +kernel + +theorem posPhaseNatLt_minAvail_le_lnErrArg {m c : Nat} + (hmlo : MLO ≤ m) (hmlt : m < Sc) (hc : c < 160) : + posPhaseNatLt m c + minPosAvail ≤ + lnErrArg (int256 (lnTail (evmSub 160 c) m)) := by + let r := int256 (lnTail (evmSub 160 c) m) + have hmhi : m < MHI := by + simp only [Sc, MHI] at hmlt ⊢ + omega + have hX := x1_nonpos_ltF hmlo hmlt + have hV0 : 0 ≤ + int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + lnBiasI := by + simpa [posAccI] using posAccI_nonneg hmlo hmhi hc + have hneg := posNegXNat_le_posConstNat hX (by omega : c ≤ 160) hV0 + have hgap : 1 ≤ posResidueGap m c r := by + simpa [r] using (posResidueGap_bounds hmlo hmhi hc).1 + have hdecomp := lnErrArg_eq_posPhase_gap (m := m) (c := c) hmlo hmhi hc + change ((lnErrArg r : Nat) : Int) = + posPhaseI m c * (lnErrorBoundDen : Int) + + (lnErrorExtraNum : Int) * twoPow99I + + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) at hdecomp + apply Int.ofNat_le.mp + rw [Int.natCast_add, posPhaseNatLt_cast hX hneg, minPosAvail_cast, hdecomp] + have h27 : 0 ≤ twoPow27I := by + unfold twoPow27I + decide + have hden : 0 ≤ (lnErrorBoundDen : Int) := by + change (0 : Int) ≤ 1000000000 + decide + have hgap27 : + 1 * twoPow27I ≤ posResidueGap m c r * twoPow27I := + Int.mul_le_mul_of_nonneg_right hgap h27 + have hgapDen : + 1 * twoPow27I * (lnErrorBoundDen : Int) ≤ + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := + Int.mul_le_mul_of_nonneg_right hgap27 hden + have hgapDen' : + twoPow27I * (lnErrorBoundDen : Int) ≤ + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := by + simpa [Int.one_mul] using hgapDen + have hinner : + (lnErrorExtraNum : Int) * twoPow99I + + twoPow27I * (lnErrorBoundDen : Int) ≤ + (lnErrorExtraNum : Int) * twoPow99I + + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := + Int.add_le_add_left hgapDen' _ + have hmain : + posPhaseI m c * (lnErrorBoundDen : Int) + + ((lnErrorExtraNum : Int) * twoPow99I + + twoPow27I * (lnErrorBoundDen : Int)) ≤ + posPhaseI m c * (lnErrorBoundDen : Int) + + ((lnErrorExtraNum : Int) * twoPow99I + + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int)) := + Int.add_le_add_left hinner _ + simpa [Int.add_assoc] using hmain + /-- Uniform coarse residue (full positive-shift): holds for every mantissa from the floor bracket because `lnErrorCoarsePosResidue = 0`. -/ theorem PosShiftResidueOk_uniform {m c : Nat} (hmlo : MLO ≤ m) (hmhi : m < MHI) @@ -56,37 +139,47 @@ theorem PosShiftGeResidueOk_uniform {m c : Nat} (hmlo : MLO ≤ m) (hmhi : m < M · unfold twoPow27I; decide · unfold lnErrorBoundDen; decide -theorem lnWadToRayBody_positive_shift_ge_residue_or_direct_cert {x : Nat} +theorem lnWadToRayBody_positive_shift_ge_residue_cert {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) - (hclt : evmClz x < 160) (_hge : Sc ≤ mant x) : - PosShiftGeResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x)) ∨ - PosShiftTopDirectOk 320 (mant x) (evmClz x) := by + (hclt : evmClz x < 160) : + PosShiftGeResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x)) := by have hx256 : x < 2 ^ 256 := by omega have htail : lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256]; rfl + rw [lnWadToRayBody_eq_tail hx256] + rfl obtain ⟨me, hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_lo : MLO ≤ mant x := by unfold mant; rw [me]; exact hmlo - have hmant_hi : mant x < MHI := by unfold mant; rw [me]; exact hmhi - obtain ⟨hc1, _hc255⟩ := clz_bounds h1 h2 + have hmant_lo : MLO ≤ mant x := by + unfold mant + rw [me] + exact hmlo + have hmant_hi : mant x < MHI := by + unfold mant + rw [me] + exact hmhi rw [htail] - exact Or.inl (PosShiftGeResidueOk_uniform hmant_lo hmant_hi hclt) + exact PosShiftGeResidueOk_uniform hmant_lo hmant_hi hclt -theorem lnWadToRayBody_positive_shift_lt_residue_or_direct_cert {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (_hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (_hlt : mant x < Sc) : - PosShiftResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x)) ∨ - PosShiftTopDirectOk 320 (mant x) (evmClz x) := by +theorem lnWadToRayBody_positive_shift_lt_residue_cert {x : Nat} + (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) + (hclt : evmClz x < 160) : + PosShiftResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x)) := by have hx256 : x < 2 ^ 256 := by omega have htail : lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256]; rfl + rw [lnWadToRayBody_eq_tail hx256] + rfl obtain ⟨me, hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_lo : MLO ≤ mant x := by unfold mant; rw [me]; exact hmlo - have hmant_hi : mant x < MHI := by unfold mant; rw [me]; exact hmhi - obtain ⟨hc1, _hc255⟩ := clz_bounds h1 h2 + have hmant_lo : MLO ≤ mant x := by + unfold mant + rw [me] + exact hmlo + have hmant_hi : mant x < MHI := by + unfold mant + rw [me] + exact hmhi rw [htail] - exact Or.inl (PosShiftResidueOk_uniform hmant_lo hmant_hi hclt) + exact PosShiftResidueOk_uniform hmant_lo hmant_hi hclt theorem lnWadToRayBody_error_bound_upper_pos_shift {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) @@ -136,10 +229,10 @@ theorem lnWadToRayBody_error_bound_upper_pos_shift {x : Nat} _ = x * 10 ^ 31 * 10 ^ 18 := by simp only [Nat.mul_comm, Nat.mul_left_comm] · -- residue band: `Sc - 45 ≤ mant x < Sc` - exact lnWadToRayBody_positive_shift_lt_residue_or_direct h1 h2 hne hclt hbranch hband - (lnWadToRayBody_positive_shift_lt_residue_or_direct_cert h1 h2 hne hclt hbranch) - · exact lnWadToRayBody_positive_shift_ge_residue_or_direct h1 h2 hclt hbranch - (lnWadToRayBody_positive_shift_ge_residue_or_direct_cert h1 h2 hclt hbranch) + exact lnWadToRayBody_positive_shift_lt_residue h1 h2 hne hclt hbranch hband + (lnWadToRayBody_positive_shift_lt_residue_cert h1 h2 hclt) + · exact lnWadToRayBody_positive_shift_ge_residue h1 h2 hclt hbranch + (lnWadToRayBody_positive_shift_ge_residue_cert h1 h2 hclt) /-- The body decomposition satisfies the `1.6986` ulp error-bound cut: the lt octave is covered by the degree-22 curved-cap cell cover on `[2^95, Sc-46]` and a residue diff --git a/formal/ln/LnProof/LnProof/Error/Cert.lean b/formal/ln/LnProof/LnProof/Error/Cert.lean index 4f6494274..36752d45a 100644 --- a/formal/ln/LnProof/LnProof/Error/Cert.lean +++ b/formal/ln/LnProof/LnProof/Error/Cert.lean @@ -11,13 +11,11 @@ def lnErrorBoundNum : Nat := 1698600000 def lnErrorBoundDen : Nat := 1000000000 def lnErrorExtraNum : Nat := lnErrorBoundNum - lnErrorBoundDen def lnErrorExtraCap : Nat := 6986 -def lnErrorBiasCap : Nat := 3384 def lnErrorCoarseGePosBudgetCap : Nat := 6961 def lnErrorCoarsePosBudgetCap : Nat := 6986 def lnErrorCoarseNegBudgetCap : Nat := 6785 def lnErrorCoarseGePosResidue : Nat := 0 def lnErrorCoarsePosResidue : Nat := 0 -def lnErrorDirectResidueGap : Nat := 336460000000000000 /-- `e^((0.698600000)·10^-27) ≥ 1 + 6986·10^-31`. -/ theorem capEFracL : @@ -47,11 +45,6 @@ theorem capECoarseNegL : (10 ^ 31 + lnErrorCoarseNegBudgetCap) (10 ^ 31) := ⟨1, by decide +kernel⟩ -theorem capBiasL3403 : - capLB (BIASc * 2 ^ 27) QS (Sc * (10 ^ 31 - lnErrorBiasCap)) - (10 ^ 18 * 10 ^ 31) := - ⟨130, by unfold lnErrorBiasCap; decide +kernel⟩ - /-- Nonnegative-shift strict lower budget with the fractional extra ulp. -/ def errBudgetL (k : Nat) : Bool := decide (((Sc - 45) + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142 ≤ @@ -71,14 +64,6 @@ def errBudgetLn (j : Nat) : Bool := 2 ^ j * (10 ^ 40 : Nat) ^ j * (10 ^ 31 - 3385) * (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarseNegBudgetCap) * (10 ^ 31 - 10) * 10 ^ 18) -/-- Reciprocal nonnegative-shift strict budget with the fractional extra ulp. -/ -def errBudgetB (k : Nat) : Bool := - decide ((10 : Nat) ^ 31 * (10 ^ 40 : Nat) ^ k * (10 ^ 18 * 10 ^ 31) * 10 ^ 31 * - (((Sc - 45) + 1) * 2 ^ k) * 10 ^ 31 ≤ - 10 ^ 18 * (10 ^ 31 - 10) * (Sc - 45) * (10 ^ 31 - 3385) * - (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * - (10 ^ 31 + lnErrorCoarsePosBudgetCap)) - /-- Reciprocal negative-shift strict budget with the fractional extra ulp. -/ def errBudgetBn (j : Nat) : Bool := decide ((2 * (10 ^ 40 + 1)) ^ j * (10 : Nat) ^ 31 * (10 ^ 18 * 10 ^ 31) * @@ -95,9 +80,6 @@ theorem errBudgetLGe_all : (List.range 160).all errBudgetLGe = true := by theorem errBudgetLn_all : (List.range 96).all errBudgetLn = true := by decide +kernel -theorem errBudgetB_all : (List.range 160).all errBudgetB = true := by - decide +kernel - theorem errBudgetBn_all : (List.range 96).all errBudgetBn = true := by decide +kernel @@ -125,16 +107,6 @@ theorem errBudgetLn_le {j : Nat} (hj : j ≤ 95) : simp only [errBudgetLn, decide_eq_true_eq] at h exact h -theorem errBudgetB_le {k : Nat} (hk : k ≤ 159) : - (10 : Nat) ^ 31 * (10 ^ 40 : Nat) ^ k * (10 ^ 18 * 10 ^ 31) * 10 ^ 31 * - (((Sc - 45) + 1) * 2 ^ k) * 10 ^ 31 ≤ - 10 ^ 18 * (10 ^ 31 - 10) * (Sc - 45) * (10 ^ 31 - 3385) * - (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * - (10 ^ 31 + lnErrorCoarsePosBudgetCap) := by - have h := List.all_eq_true.mp errBudgetB_all k (List.mem_range.mpr (by omega)) - simp only [errBudgetB, decide_eq_true_eq] at h - exact h - theorem errBudgetBn_le {j : Nat} (hj : j ≤ 95) : (2 * (10 ^ 40 + 1)) ^ j * (10 : Nat) ^ 31 * (10 ^ 18 * 10 ^ 31) * 10 ^ 31 * 10 ^ 31 ≤ diff --git a/formal/ln/LnProof/LnProof/Error/Core.lean b/formal/ln/LnProof/LnProof/Error/Core.lean deleted file mode 100644 index 8d03586ba..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core.lean +++ /dev/null @@ -1,28 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.ExpMargin -import LnProof.Error.Core.Args -import LnProof.Error.Core.Residue -import LnProof.Error.Core.ResidueCover -import LnProof.Error.Core.Budget -import LnProof.Error.Core.PhaseGe -import LnProof.Error.Core.Direct -import LnProof.Error.Core.PhaseCover -import LnProof.Error.Core.PhaseLt -import LnProof.Error.Core.Bounds -import LnProof.Error.Core.C160 -import LnProof.Error.Core.BranchPos -import LnProof.Error.Core.BranchNeg -import LnProof.Error.Core.BranchBn -import LnProof.Error.Core.Assembly -import LnProof.Error.Core.BranchCert - -/-! -# Public cut statement for the `lnWadToRay` error bound - -This module re-exports the error-bound machinery, decomposed into the -`Error/Core/` components (see each for its role). The upper side is a -rational strict upper cut over denominator `QS * den`; the lower side is -the established floor cut. --/ diff --git a/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean b/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean index 2fd8b476d..7bdfcb78f 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/Assembly.lean @@ -1,12 +1,6 @@ import LnProof.Floor.CutEquiv import LnProof.Error.Cert import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.ExpMargin -import LnProof.Error.Core.ResidueCover -import LnProof.Error.Core.Budget -import LnProof.Error.Core.Direct -import LnProof.Error.Core.PhaseCover -import LnProof.Error.Core.Bounds import LnProof.Error.Core.C160 import LnProof.Error.Core.BranchPos import LnProof.Error.Core.BranchNeg @@ -15,7 +9,7 @@ import LnProof.Error.Core.BranchBn /-! # Error bound — Assembly -Upper-bound assembly: the `lnWadToRayBody_*` positive/negative-shift error-bound theorems that `Error.Bound` consumes. +Upper-bound assembly for the zero-, negative-, and positive-shift branches. -/ open FormalYul @@ -32,9 +26,9 @@ attribute [local irreducible] lnWadToRayBody theorem r_nonneg_of_c160_v_nonneg {m : Nat} {R : Int} (hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516294209054209107914) + 116873961749927929127912020551560854268589826112230) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516294209054209107914 < (R + 1) * 2 ^ 72) : + 116873961749927929127912020551560854268589826112230 < (R + 1) * 2 ^ 72) : 0 ≤ R := by rcases Int.lt_or_le R 0 with hneg | hnon · exfalso @@ -76,7 +70,7 @@ theorem lnWadToRayBody_error_bound_upper_c160 {x : Nat} (h1 : 1 ≤ x) (h2 : x < obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 have hbr2' : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < + ln2kInt (evmClz x) + 116873961749927929127912020551560854268589826112230 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by @@ -98,7 +92,7 @@ theorem lnWadToRayBody_error_bound_upper_c160 {x : Nat} (h1 : 1 ≤ x) (h2 : x < rw [hc160] at hw2 simpa only [Nat.sub_self, Nat.pow_zero, Nat.mul_one] using hw2 have hbr2c : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt 160 + 116873961749927929127912020551516294209054209107914 < + ln2kInt 160 + 116873961749927929127912020551560854268589826112230 < (R + 1) * 2 ^ 72 := by simpa [hc160] using hbr2' apply CutLogWadRayLtRational_of_strict (by omega) @@ -113,7 +107,7 @@ theorem lnWadToRayBody_error_bound_upper_c160 {x : Nat} (h1 : 1 ≤ x) (h2 : x < · have hmhi : mant x < MHI := hmant_hi have hV0I := v_c160_nonneg hmant_lo hmhi have hV0 : 0 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt 160 + 116873961749927929127912020551516294209054209107914 := by + ln2kInt 160 + 116873961749927929127912020551560854268589826112230 := by simpa [lnBiasI] using hV0I have hr0 := r_nonneg_of_c160_v_nonneg hV0 hbr2c unfold lnErrorBoundDen lnErrorBoundNum @@ -130,7 +124,7 @@ theorem lnWadToRayBody_error_bound_upper_neg_shift_nonneg {x : Nat} obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 have hbr2' : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < + ln2kInt (evmClz x) + 116873961749927929127912020551560854268589826112230 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by @@ -163,7 +157,7 @@ theorem lnWadToRayBody_error_bound_upper_neg_shift_rec_ge {x : Nat} obtain ⟨_hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr2 have hbrHi : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < + ln2kInt (evmClz x) + 116873961749927929127912020551560854268589826112230 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by @@ -189,317 +183,33 @@ theorem lnWadToRayBody_error_bound_upper_neg_shift_rec_ge {x : Nat} · exact bn_lt_neg_exact hmant_lo hbranch hcgt hc255 hbrHi hrneg hw · exact bn_ge_neg_exact hbranch hmant_hi hcgt hc255 hbrHi hrneg hw -theorem lnWadToRayBody_positive_shift_ge_top_or_direct {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hge : Sc ≤ mant x) - (hcert : PosShiftGeTopBudgetIneqOk (mant x) (evmClz x) ∨ - PosShiftTopDirectOk 320 (mant x) (evmClz x)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - have hx256 : x < 2 ^ 256 := by omega - have htail : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - rcases hcert with htopBudget | hdirect - · have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - obtain ⟨_hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne - rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr2 - have hbrHi : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI < - (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by - have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = - int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by - rw [Int.add_mul, Int.one_mul] - rw [e] - simpa [lnBiasI] using hbr2 - obtain ⟨me, _hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_hi : mant x < MHI := by - unfold mant - rw [me] - exact hmhi - have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - have hphase : - posPhaseNatGe (mant x) (evmClz x) ≤ lnErrArg (int256 (lnWadToRayBody x)) := - posPhaseNatGe_le_lnErrArg hge hmant_hi (by omega) hbrHi (by omega) - have hineq : PosShiftGeBudgetIneqOk (mant x) (evmClz x) x - (int256 (lnWadToRayBody x)) := by - change PosShiftGeBudgetIneqOk (mant x) (evmClz x) - (posTopX (evmClz x) (mant x)) (int256 (lnTail (evmSub 160 (evmClz x)) (mant x))) at htopBudget - rw [← htail] at htopBudget - unfold PosShiftGeBudgetIneqOk at htopBudget ⊢ - have hnum : wadRayNum x ≤ wadRayNum (posTopX (evmClz x) (mant x)) := by - unfold wadRayNum - exact Nat.mul_le_mul_right (10 ^ 31) htop - exact Nat.le_trans (Nat.mul_le_mul_right (posBaseWGe (evmClz x) * lnErrQ) hnum) - htopBudget - exact capLB_strict_to_exact - (lo_ge_pos_budget_exact hge hmant_hi hclt ⟨hphase, hineq⟩) - · unfold PosShiftTopDirectOk at hdirect - exact pos_shift_direct_exact_of_sumGE h1 h2 hclt hdirect - -theorem lnWadToRayBody_positive_shift_lt_top_or_direct {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hlt : mant x < Sc) - (hcert : PosShiftLtTopBudgetIneqOk (mant x) (evmClz x) ∨ - PosShiftTopDirectOk 320 (mant x) (evmClz x)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - have hx256 : x < 2 ^ 256 := by omega - have htail : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - rcases hcert with htopBudget | hdirect - · have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne - rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 - have hbrHi : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI < - (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by - have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = - int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by - rw [Int.add_mul, Int.one_mul] - rw [e] - simpa [lnBiasI] using hbr2 - obtain ⟨me, hmlo, _hmhi⟩ := mant_facts h1 h2 - have hmant_lo : MLO ≤ mant x := by - unfold mant - rw [me] - exact hmlo - have hX := x1_nonpos_ltF hmant_lo hlt - have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - have hV0 : 0 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI := by - have hR0 : 0 ≤ int256 (lnWadToRayBody x) * 2 ^ 72 := - Int.mul_nonneg hr0 (by decide) - have h := Int.le_trans hR0 hbr1 - simpa [lnBiasI] using h - have hneg := posNegXNat_le_posConstNat hX (by omega) hV0 - have hphase : - posPhaseNatLt (mant x) (evmClz x) ≤ lnErrArg (int256 (lnWadToRayBody x)) := - posPhaseNatLt_le_lnErrArg hX (by omega) hneg hbrHi (by omega) - have hineq : PosShiftLtBudgetIneqOk (mant x) (evmClz x) x - (int256 (lnWadToRayBody x)) := by - change PosShiftLtBudgetIneqOk (mant x) (evmClz x) - (posTopX (evmClz x) (mant x)) (int256 (lnTail (evmSub 160 (evmClz x)) (mant x))) at htopBudget - rw [← htail] at htopBudget - unfold PosShiftLtBudgetIneqOk at htopBudget ⊢ - have hnum : wadRayNum x ≤ wadRayNum (posTopX (evmClz x) (mant x)) := by - unfold wadRayNum - exact Nat.mul_le_mul_right (10 ^ 31) htop - exact Nat.le_trans (Nat.mul_le_mul_right (posBaseWLt (evmClz x) * lnErrQ) hnum) - htopBudget - exact capLB_strict_to_exact - (lo_lt_pos_budget_exact hmant_lo hlt hclt ⟨hneg, hphase, hineq⟩) - · unfold PosShiftTopDirectOk at hdirect - exact pos_shift_direct_exact_of_sumGE h1 h2 hclt hdirect - -theorem lnWadToRayBody_positive_shift_ge_residue_or_direct {x : Nat} +theorem lnWadToRayBody_positive_shift_ge_residue {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hclt : evmClz x < 160) (hge : Sc ≤ mant x) - (hcert : PosShiftGeResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x)) ∨ - PosShiftTopDirectOk 320 (mant x) (evmClz x)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - rcases hcert with hres | hdirect - · obtain ⟨_me, _hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_hi : mant x < MHI := by - unfold mant - rw [_me] - exact hmhi - obtain ⟨hc1, _hc255⟩ := clz_bounds h1 h2 - obtain ⟨_hw1, hw2⟩ := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - exact capLB_strict_to_exact - (lo_ge_pos_exact_ge_residue hge hmant_hi hc1 hclt hr0 hres hw2) - · unfold PosShiftTopDirectOk at hdirect - exact pos_shift_direct_exact_of_sumGE h1 h2 hclt hdirect - -theorem lnWadToRayBody_positive_shift_lt_residue_or_direct {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hlt : mant x < Sc) (hband_lo : Sc - 45 ≤ mant x) - (hcert : PosShiftResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x)) ∨ - PosShiftTopDirectOk 320 (mant x) (evmClz x)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - rcases hcert with hres | hdirect - · obtain ⟨hbr1, _hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne - rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 - obtain ⟨hc1, _hc255⟩ := clz_bounds h1 h2 - obtain ⟨_hw1, hw2⟩ := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - exact capLB_strict_to_exact - (lo_lt_pos_exact hband_lo hlt hc1 hclt hbr1 hr0 hres hw2) - · unfold PosShiftTopDirectOk at hdirect - exact pos_shift_direct_exact_of_sumGE h1 h2 hclt hdirect - -theorem lnWadToRayBody_positive_shift_ge_phase_direct {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hge : Sc ≤ mant x) - (hcert : PosShiftGePhaseDirectOk 320 (mant x) (evmClz x)) : + (hres : PosShiftGeResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x))) : capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - obtain ⟨_hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne - rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr2 - have hbrHi : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI < - (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by - have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = - int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by - rw [Int.add_mul, Int.one_mul] - rw [e] - simpa [lnBiasI] using hbr2 obtain ⟨me, _hmlo, hmhi⟩ := mant_facts h1 h2 have hmant_hi : mant x < MHI := by unfold mant rw [me] exact hmhi + obtain ⟨hc1, _hc255⟩ := clz_bounds h1 h2 + obtain ⟨_hw1, hw2⟩ := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - have hp := posPhaseNatGe_extra_le_lnErrArg hge hmant_hi (by omega) hbrHi (by omega) - have cap0 : capLB (posPhaseNatGe (mant x) (evmClz x) + lnPhaseExtraArg) - lnErrQ (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - unfold PosShiftGePhaseDirectOk at hcert - exact ⟨320, hcert⟩ - have capR : capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - refine capLB_arg (q' := lnErrQ) (by unfold lnErrQ; decide) ?_ cap0 - exact Nat.mul_le_mul_right lnErrQ hp - have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - refine capLB_weaken (p := lnErrArg (int256 (lnWadToRayBody x))) (q := lnErrQ) - (y := posTopX (evmClz x) (mant x)) (w := 10 ^ 18) - (y' := x) (w' := 10 ^ 18) (by decide) capR ?_ - exact Nat.mul_le_mul_right (10 ^ 18) htop + exact capLB_strict_to_exact + (lo_ge_pos_exact_ge_residue hge hmant_hi hc1 hclt hr0 hres hw2) -theorem lnWadToRayBody_positive_shift_lt_phase_direct {x : Nat} +theorem lnWadToRayBody_positive_shift_lt_residue {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hlt : mant x < Sc) - (hcert : PosShiftLtPhaseDirectOk 320 (mant x) (evmClz x)) : + (hclt : evmClz x < 160) (hlt : mant x < Sc) (hband_lo : Sc - 45 ≤ mant x) + (hres : PosShiftResidueOk (mant x) (evmClz x) (int256 (lnWadToRayBody x))) : capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne - rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 - have hbrHi : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI < - (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by - have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = - int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by - rw [Int.add_mul, Int.one_mul] - rw [e] - simpa [lnBiasI] using hbr2 - obtain ⟨me, hmlo, _hmhi⟩ := mant_facts h1 h2 - have hmant_lo : MLO ≤ mant x := by - unfold mant - rw [me] - exact hmlo - have hX := x1_nonpos_ltF hmant_lo hlt + obtain ⟨hbr1, _hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne + rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 + obtain ⟨hc1, _hc255⟩ := clz_bounds h1 h2 + obtain ⟨_hw1, hw2⟩ := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - have hV0 : 0 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI := by - have hR0 : 0 ≤ int256 (lnWadToRayBody x) * 2 ^ 72 := - Int.mul_nonneg hr0 (by decide) - have h := Int.le_trans hR0 hbr1 - simpa [lnBiasI] using h - have hneg := posNegXNat_le_posConstNat hX (by omega) hV0 - have hp := posPhaseNatLt_extra_le_lnErrArg hX (by omega) hneg hbrHi (by omega) - have cap0 : capLB (posPhaseNatLt (mant x) (evmClz x) + lnPhaseExtraArg) - lnErrQ (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - unfold PosShiftLtPhaseDirectOk at hcert - exact ⟨320, hcert⟩ - have capR : capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - refine capLB_arg (q' := lnErrQ) (by unfold lnErrQ; decide) ?_ cap0 - exact Nat.mul_le_mul_right lnErrQ hp - have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - refine capLB_weaken (p := lnErrArg (int256 (lnWadToRayBody x))) (q := lnErrQ) - (y := posTopX (evmClz x) (mant x)) (w := 10 ^ 18) - (y' := x) (w' := 10 ^ 18) (by decide) capR ?_ - exact Nat.mul_le_mul_right (10 ^ 18) htop - -theorem lnWadToRayBody_positive_shift_ge_min_phase_direct {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) - (hclt : evmClz x < 160) (hge : Sc ≤ mant x) - (hcert : PosShiftGeMinPhaseDirectOk 320 (mant x) (evmClz x)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - have hx256 : x < 2 ^ 256 := by omega - have htail : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - obtain ⟨me, _hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_hi : mant x < MHI := by - unfold mant - rw [me] - exact hmhi - have hp := posPhaseNatGe_minAvail_le_lnErrArg hge hmant_hi hclt - rw [← htail] at hp - have cap0 : capLB (posPhaseNatGe (mant x) (evmClz x) + minPosAvail) - lnErrQ (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - unfold PosShiftGeMinPhaseDirectOk at hcert - exact ⟨320, hcert⟩ - have capR : capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - refine capLB_arg (q' := lnErrQ) (by unfold lnErrQ; decide) ?_ cap0 - exact Nat.mul_le_mul_right lnErrQ hp - have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - refine capLB_weaken (p := lnErrArg (int256 (lnWadToRayBody x))) (q := lnErrQ) - (y := posTopX (evmClz x) (mant x)) (w := 10 ^ 18) - (y' := x) (w' := 10 ^ 18) (by decide) capR ?_ - exact Nat.mul_le_mul_right (10 ^ 18) htop - -theorem lnWadToRayBody_positive_shift_lt_min_phase_direct {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) - (hclt : evmClz x < 160) (hlt : mant x < Sc) - (hcert : PosShiftLtMinPhaseDirectOk 320 (mant x) (evmClz x)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - have hx256 : x < 2 ^ 256 := by omega - have htail : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - obtain ⟨me, hmlo, _hmhi⟩ := mant_facts h1 h2 - have hmant_lo : MLO ≤ mant x := by - unfold mant - rw [me] - exact hmlo - have hp := posPhaseNatLt_minAvail_le_lnErrArg hmant_lo hlt hclt - rw [← htail] at hp - have cap0 : capLB (posPhaseNatLt (mant x) (evmClz x) + minPosAvail) - lnErrQ (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - unfold PosShiftLtMinPhaseDirectOk at hcert - exact ⟨320, hcert⟩ - have capR : capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - refine capLB_arg (q' := lnErrQ) (by unfold lnErrQ; decide) ?_ cap0 - exact Nat.mul_le_mul_right lnErrQ hp - have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - refine capLB_weaken (p := lnErrArg (int256 (lnWadToRayBody x))) (q := lnErrQ) - (y := posTopX (evmClz x) (mant x)) (w := 10 ^ 18) - (y' := x) (w' := 10 ^ 18) (by decide) capR ?_ - exact Nat.mul_le_mul_right (10 ^ 18) htop + exact capLB_strict_to_exact + (lo_lt_pos_exact hband_lo hlt hc1 hclt hbr1 hr0 hres hw2) end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/Bounds.lean b/formal/ln/LnProof/LnProof/Error/Core/Bounds.lean deleted file mode 100644 index ece4e125b..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/Bounds.lean +++ /dev/null @@ -1,730 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.Args -import LnProof.Error.Core.Residue -import LnProof.Error.Core.ResidueCover -import LnProof.Error.Core.Budget -import LnProof.Error.Core.Direct -import LnProof.Error.Core.PhaseCover - -/-! -# Error bound — Bounds - -`minPosAvail` casts, the `posPhaseNat*_le_lnErrArg` family, top-budget cells, and the `lo_*_budget_exact` bridges. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -theorem minPosAvail_cast : - ((minPosAvail : Nat) : Int) = - (lnErrorExtraNum : Int) * twoPow99I + - twoPow27I * (lnErrorBoundDen : Int) := by - unfold minPosAvail lnPhaseExtraArg twoPow99N twoPow27N twoPow99I twoPow27I - unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen - decide +kernel - -theorem posPhaseNatGe_minAvail_le_lnErrArg {m c : Nat} - (hge : Sc ≤ m) (hmhi : m < MHI) (hc : c < 160) : - posPhaseNatGe m c + minPosAvail ≤ - lnErrArg (int256 (lnTail (evmSub 160 c) m)) := by - let r := int256 (lnTail (evmSub 160 c) m) - have hmlo : MLO ≤ m := by - simp only [Sc, MLO] at hge ⊢ - omega - have hX := x1_nonneg_geF hge hmhi - have hgap : 1 ≤ posResidueGap m c r := by - simpa [r] using (posResidueGap_bounds hmlo hmhi hc).1 - have hdecomp := lnErrArg_eq_posPhase_gap (m := m) (c := c) hmlo hmhi hc - change ((lnErrArg r : Nat) : Int) = - posPhaseI m c * (lnErrorBoundDen : Int) + - (lnErrorExtraNum : Int) * twoPow99I + - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) at hdecomp - apply Int.ofNat_le.mp - rw [Int.natCast_add, posPhaseNatGe_cast hX, minPosAvail_cast, hdecomp] - have h27 : 0 ≤ twoPow27I := by - unfold twoPow27I - decide - have hden : 0 ≤ (lnErrorBoundDen : Int) := by - change (0 : Int) ≤ 1000000000 - decide - have hgap27 : - 1 * twoPow27I ≤ posResidueGap m c r * twoPow27I := - Int.mul_le_mul_of_nonneg_right hgap h27 - have hgapDen : - 1 * twoPow27I * (lnErrorBoundDen : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := - Int.mul_le_mul_of_nonneg_right hgap27 hden - have hgapDen' : - twoPow27I * (lnErrorBoundDen : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := by - simpa [Int.one_mul] using hgapDen - have hinner : - (lnErrorExtraNum : Int) * twoPow99I + - twoPow27I * (lnErrorBoundDen : Int) ≤ - (lnErrorExtraNum : Int) * twoPow99I + - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := - Int.add_le_add_left hgapDen' _ - have hmain : - posPhaseI m c * (lnErrorBoundDen : Int) + - ((lnErrorExtraNum : Int) * twoPow99I + - twoPow27I * (lnErrorBoundDen : Int)) ≤ - posPhaseI m c * (lnErrorBoundDen : Int) + - ((lnErrorExtraNum : Int) * twoPow99I + - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int)) := - Int.add_le_add_left hinner _ - simpa [Int.add_assoc] using hmain - -theorem posPhaseNatLt_minAvail_le_lnErrArg {m c : Nat} - (hmlo : MLO ≤ m) (hmlt : m < Sc) (hc : c < 160) : - posPhaseNatLt m c + minPosAvail ≤ - lnErrArg (int256 (lnTail (evmSub 160 c) m)) := by - let r := int256 (lnTail (evmSub 160 c) m) - have hmhi : m < MHI := by - simp only [Sc, MHI] at hmlt ⊢ - omega - have hX := x1_nonpos_ltF hmlo hmlt - have hV0 : 0 ≤ - int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + lnBiasI := by - simpa [posAccI] using posAccI_nonneg hmlo hmhi hc - have hneg := posNegXNat_le_posConstNat hX (by omega : c ≤ 160) hV0 - have hgap : 1 ≤ posResidueGap m c r := by - simpa [r] using (posResidueGap_bounds hmlo hmhi hc).1 - have hdecomp := lnErrArg_eq_posPhase_gap (m := m) (c := c) hmlo hmhi hc - change ((lnErrArg r : Nat) : Int) = - posPhaseI m c * (lnErrorBoundDen : Int) + - (lnErrorExtraNum : Int) * twoPow99I + - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) at hdecomp - apply Int.ofNat_le.mp - rw [Int.natCast_add, posPhaseNatLt_cast hX hneg, minPosAvail_cast, hdecomp] - have h27 : 0 ≤ twoPow27I := by - unfold twoPow27I - decide - have hden : 0 ≤ (lnErrorBoundDen : Int) := by - change (0 : Int) ≤ 1000000000 - decide - have hgap27 : - 1 * twoPow27I ≤ posResidueGap m c r * twoPow27I := - Int.mul_le_mul_of_nonneg_right hgap h27 - have hgapDen : - 1 * twoPow27I * (lnErrorBoundDen : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := - Int.mul_le_mul_of_nonneg_right hgap27 hden - have hgapDen' : - twoPow27I * (lnErrorBoundDen : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := by - simpa [Int.one_mul] using hgapDen - have hinner : - (lnErrorExtraNum : Int) * twoPow99I + - twoPow27I * (lnErrorBoundDen : Int) ≤ - (lnErrorExtraNum : Int) * twoPow99I + - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) := - Int.add_le_add_left hgapDen' _ - have hmain : - posPhaseI m c * (lnErrorBoundDen : Int) + - ((lnErrorExtraNum : Int) * twoPow99I + - twoPow27I * (lnErrorBoundDen : Int)) ≤ - posPhaseI m c * (lnErrorBoundDen : Int) + - ((lnErrorExtraNum : Int) * twoPow99I + - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int)) := - Int.add_le_add_left hinner _ - simpa [Int.add_assoc] using hmain - -theorem posAvailGe_min {m c : Nat} - (hge : Sc ≤ m) (hmhi : m < MHI) (hc : c < 160) : - minPosAvail ≤ - posAvailGe m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold posAvailGe - have h := posPhaseNatGe_minAvail_le_lnErrArg hge hmhi hc - omega - -theorem posAvailLt_min {m c : Nat} - (hmlo : MLO ≤ m) (hmlt : m < Sc) (hc : c < 160) : - minPosAvail ≤ - posAvailLt m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold posAvailLt - have h := posPhaseNatLt_minAvail_le_lnErrArg hmlo hmlt hc - omega - -theorem wadRayNum_mono {x y : Nat} (hxy : x ≤ y) : wadRayNum x ≤ wadRayNum y := by - unfold wadRayNum - exact Nat.mul_le_mul_right _ hxy - -theorem posBaseYGe_mono_m {lo m c : Nat} (hlom : lo ≤ m) : - posBaseYGe lo c ≤ posBaseYGe m c := by - unfold posBaseYGe - have h1 : - lo * 9999999999999999999999999996615 ≤ - m * 9999999999999999999999999996615 := - Nat.mul_le_mul_right _ hlom - have h2 : - (lo * 9999999999999999999999999996615) * - (2 * (10 ^ 40 - 1)) ^ (160 - c) ≤ - (m * 9999999999999999999999999996615) * - (2 * (10 ^ 40 - 1)) ^ (160 - c) := - Nat.mul_le_mul_right _ h1 - exact Nat.mul_le_mul_right _ h2 - -theorem posBaseYLt_mono_m {lo m c : Nat} (hlom : lo ≤ m) : - posBaseYLt lo c ≤ posBaseYLt m c := by - unfold posBaseYLt - have h1 : - lo * 9999999999999999999999999996615 ≤ - m * 9999999999999999999999999996615 := - Nat.mul_le_mul_right _ hlom - exact Nat.mul_le_mul_left _ h1 - -theorem geTopBudgetCoarseCellOkB_sound {lo hi m c : Nat} - (h : geTopBudgetCoarseCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeTopBudgetIneqOk m c := by - unfold geTopBudgetCoarseCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, hc⟩, hineq⟩ := h - unfold PosShiftGeTopBudgetIneqOk PosShiftGeBudgetIneqOk - let r := int256 (lnTail (evmSub 160 c) m) - have hleft : - wadRayNum (posTopX c m) * (posBaseWGe c * lnErrQ) ≤ - wadRayNum (posTopX c hi) * (posBaseWGe c * lnErrQ) := by - exact Nat.mul_le_mul_right _ (wadRayNum_mono (posTopX_mono_m hmhi)) - have hbase : posBaseYGe lo c ≤ posBaseYGe m c := - posBaseYGe_mono_m hlom - have havail : minPosAvail ≤ posAvailGe m c r := - posAvailGe_min (m := m) (c := c) (by omega) (by omega) hc - have hmargin : lnErrQ + minPosAvail ≤ lnErrQ + posAvailGe m c r := - Nat.add_le_add_left havail lnErrQ - have hright : - (posBaseYGe lo c * (lnErrQ + minPosAvail)) * wadRayStrictDen ≤ - (posBaseYGe m c * (lnErrQ + posAvailGe m c r)) * wadRayStrictDen := by - exact Nat.mul_le_mul_right _ (Nat.mul_le_mul hbase hmargin) - exact Nat.le_trans hleft (Nat.le_trans hineq hright) - -theorem ltTopBudgetCoarseCellOkB_sound {lo hi m c : Nat} - (h : ltTopBudgetCoarseCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtTopBudgetIneqOk m c := by - unfold ltTopBudgetCoarseCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, hc⟩, hineq⟩ := h - unfold PosShiftLtTopBudgetIneqOk PosShiftLtBudgetIneqOk - let r := int256 (lnTail (evmSub 160 c) m) - have hleft : - wadRayNum (posTopX c m) * (posBaseWLt c * lnErrQ) ≤ - wadRayNum (posTopX c hi) * (posBaseWLt c * lnErrQ) := by - exact Nat.mul_le_mul_right _ (wadRayNum_mono (posTopX_mono_m hmhi)) - have hbase : posBaseYLt lo c ≤ posBaseYLt m c := - posBaseYLt_mono_m hlom - have havail : minPosAvail ≤ posAvailLt m c r := - posAvailLt_min (m := m) (c := c) (by omega) (by omega) hc - have hmargin : lnErrQ + minPosAvail ≤ lnErrQ + posAvailLt m c r := - Nat.add_le_add_left havail lnErrQ - have hright : - (posBaseYLt lo c * (lnErrQ + minPosAvail)) * wadRayStrictDen ≤ - (posBaseYLt m c * (lnErrQ + posAvailLt m c r)) * wadRayStrictDen := by - exact Nat.mul_le_mul_right _ (Nat.mul_le_mul hbase hmargin) - exact Nat.le_trans hleft (Nat.le_trans hineq hright) - -theorem geTopBudgetRunCellOkB_sound {lo hi m c : Nat} - (h : geTopBudgetRunCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeTopBudgetIneqOk m c := by - unfold geTopBudgetRunCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hloSc, hlohi⟩, hhi⟩, hc⟩, hrun⟩ := h - obtain ⟨hboundary, hineq⟩ := hrun - have hlo : MLO ≤ lo := by - simp only [Sc, MLO] at hloSc ⊢ - omega - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - let rhi := int256 (lnTail (evmSub 160 c) hi) - have hmhi' : m < MHI := by omega - have htailM : rm = rlo := by - simpa [rm, rlo] using - lnTail_eq_of_residue_run hlo hlom hmhi hhi hc hboundary - have htailHi : rhi = rlo := by - simpa [rhi, rlo] using - lnTail_eq_of_residue_run hlo hlohi (Nat.le_refl hi) hhi hc hboundary - unfold PosShiftGeTopBudgetIneqOk PosShiftGeBudgetIneqOk - have hleft : - wadRayNum (posTopX c m) * (posBaseWGe c * lnErrQ) ≤ - wadRayNum (posTopX c hi) * (posBaseWGe c * lnErrQ) := by - exact Nat.mul_le_mul_right _ (wadRayNum_mono (posTopX_mono_m hmhi)) - have hbase : posBaseYGe lo c ≤ posBaseYGe m c := - posBaseYGe_mono_m hlom - have hphase_m_hi : posPhaseNatGe m c ≤ posPhaseNatGe hi c := - posPhaseNatGe_mono_m (lo := m) (m := hi) (c := c) (by omega) hmhi hhi - have havail : posAvailGe hi c rlo ≤ posAvailGe m c rm := by - unfold posAvailGe - rw [htailM] - exact Nat.sub_le_sub_left hphase_m_hi (lnErrArg rlo) - have hmargin : lnErrQ + posAvailGe hi c rlo ≤ lnErrQ + posAvailGe m c rm := - Nat.add_le_add_left havail lnErrQ - have hright : - (posBaseYGe lo c * (lnErrQ + posAvailGe hi c rlo)) * wadRayStrictDen ≤ - (posBaseYGe m c * (lnErrQ + posAvailGe m c rm)) * wadRayStrictDen := by - exact Nat.mul_le_mul_right _ (Nat.mul_le_mul hbase hmargin) - have hineq' : - wadRayNum (posTopX c hi) * (posBaseWGe c * lnErrQ) ≤ - (posBaseYGe lo c * (lnErrQ + posAvailGe hi c rlo)) * wadRayStrictDen := by - simpa [rlo] using hineq - have hle := Nat.le_trans hleft (Nat.le_trans hineq' hright) - simpa [rm] using hle - -theorem ltTopBudgetRunCellOkB_sound {lo hi m c : Nat} - (h : ltTopBudgetRunCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtTopBudgetIneqOk m c := by - unfold ltTopBudgetRunCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, hlohi⟩, hhiSc⟩, hc⟩, hrun⟩ := h - obtain ⟨hboundary, hineq⟩ := hrun - have hhi : hi < MHI := by - simp only [Sc, MHI] at hhiSc ⊢ - omega - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - let rhi := int256 (lnTail (evmSub 160 c) hi) - have hmhi' : m < MHI := by omega - have htailM : rm = rlo := by - simpa [rm, rlo] using - lnTail_eq_of_residue_run hlo hlom hmhi hhi hc hboundary - have htailHi : rhi = rlo := by - simpa [rhi, rlo] using - lnTail_eq_of_residue_run hlo hlohi (Nat.le_refl hi) hhi hc hboundary - unfold PosShiftLtTopBudgetIneqOk PosShiftLtBudgetIneqOk - have hleft : - wadRayNum (posTopX c m) * (posBaseWLt c * lnErrQ) ≤ - wadRayNum (posTopX c hi) * (posBaseWLt c * lnErrQ) := by - exact Nat.mul_le_mul_right _ (wadRayNum_mono (posTopX_mono_m hmhi)) - have hbase : posBaseYLt lo c ≤ posBaseYLt m c := - posBaseYLt_mono_m hlom - have hphase_m_hi : posPhaseNatLt m c ≤ posPhaseNatLt hi c := - posPhaseNatLt_mono_m (lo := m) (m := hi) (c := c) (by omega) hmhi (by - simp only [Sc, MHI] at hhiSc ⊢ - omega) - have havail : posAvailLt hi c rlo ≤ posAvailLt m c rm := by - unfold posAvailLt - rw [htailM] - exact Nat.sub_le_sub_left hphase_m_hi (lnErrArg rlo) - have hmargin : lnErrQ + posAvailLt hi c rlo ≤ lnErrQ + posAvailLt m c rm := - Nat.add_le_add_left havail lnErrQ - have hright : - (posBaseYLt lo c * (lnErrQ + posAvailLt hi c rlo)) * wadRayStrictDen ≤ - (posBaseYLt m c * (lnErrQ + posAvailLt m c rm)) * wadRayStrictDen := by - exact Nat.mul_le_mul_right _ (Nat.mul_le_mul hbase hmargin) - have hineq' : - wadRayNum (posTopX c hi) * (posBaseWLt c * lnErrQ) ≤ - (posBaseYLt lo c * (lnErrQ + posAvailLt hi c rlo)) * wadRayStrictDen := by - simpa [rlo] using hineq - have hle := Nat.le_trans hleft (Nat.le_trans hineq' hright) - simpa [rm] using hle - -theorem posPhaseNatLt_le_lnErrArg {m c : Nat} {r : Int} - (hX : int256 (x1W (zWord m)) ≤ 0) (hc : c ≤ 160) - (hneg : posNegXNat m ≤ posConstNat c) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI < (r + 1) * 2 ^ 72) - (hr0 : -1 ≤ r) : - posPhaseNatLt m c ≤ lnErrArg r := by - have hphase := posPhaseI_le_of_floor hc hr - have hcore := c160_arg_le_int (A := posPhaseI m c) (r := r) hphase - have harg : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - have h0 : 0 ≤ r + 1 := by omega - have hp : 0 ≤ (r + 1) * (1000000000 : Int) := - Int.mul_nonneg h0 (by decide) - have e : (r + 1) * (1000000000 : Int) + 698600000 = - r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - unfold lnErrorBoundDen lnErrorBoundNum - rw [Int.add_mul, Int.one_mul] - omega - rw [← e] - exact Int.add_nonneg hp (by decide) - apply Int.ofNat_le.mp - rw [posPhaseNatLt_cast hX hneg] - unfold lnErrArg - rw [Int.natCast_mul, Int.toNat_of_nonneg harg] - have hnon : 0 ≤ 698600000 * twoPow99I := by - unfold twoPow99I - decide - have hle := Int.le_trans (Int.le_add_of_nonneg_right hnon) hcore - simpa [lnErrorBoundDen, lnErrorBoundNum, twoPow99I] using hle - -theorem posPhaseNatGe_extra_le_lnErrArg {m c : Nat} {r : Int} - (hge : Sc ≤ m) (hmhi : m < MHI) (hc : c ≤ 160) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI < (r + 1) * 2 ^ 72) - (hr0 : -1 ≤ r) : - posPhaseNatGe m c + lnPhaseExtraArg ≤ lnErrArg r := by - have hX := x1_nonneg_geF hge hmhi - have hphase := posPhaseI_le_of_floor hc hr - have hcore := c160_arg_le_int (A := posPhaseI m c) (r := r) hphase - have harg : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - have h0 : 0 ≤ r + 1 := by omega - have hp : 0 ≤ (r + 1) * (1000000000 : Int) := - Int.mul_nonneg h0 (by decide) - have e : (r + 1) * (1000000000 : Int) + 698600000 = - r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - unfold lnErrorBoundDen lnErrorBoundNum - rw [Int.add_mul, Int.one_mul] - omega - rw [← e] - exact Int.add_nonneg hp (by decide) - apply Int.ofNat_le.mp - rw [Int.natCast_add, posPhaseNatGe_cast hX] - unfold lnPhaseExtraArg lnErrArg - have htarget : ((((r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)).toNat * - 2 ^ 99 : Nat) : Int)) = - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - rw [Int.natCast_mul, Int.toNat_of_nonneg harg] - unfold twoPow99I - rfl - have hextra : (((lnErrorExtraNum * twoPow99N : Nat) : Int)) = - (lnErrorExtraNum : Int) * twoPow99I := by - unfold twoPow99N twoPow99I - rfl - rw [htarget, hextra] - simpa [lnErrorBoundDen, lnErrorBoundNum, lnErrorExtraNum, twoPow99N, twoPow99I] - using hcore - -theorem posPhaseNatLt_extra_le_lnErrArg {m c : Nat} {r : Int} - (hX : int256 (x1W (zWord m)) ≤ 0) (hc : c ≤ 160) - (hneg : posNegXNat m ≤ posConstNat c) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI < (r + 1) * 2 ^ 72) - (hr0 : -1 ≤ r) : - posPhaseNatLt m c + lnPhaseExtraArg ≤ lnErrArg r := by - have hphase := posPhaseI_le_of_floor hc hr - have hcore := c160_arg_le_int (A := posPhaseI m c) (r := r) hphase - have harg : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - have h0 : 0 ≤ r + 1 := by omega - have hp : 0 ≤ (r + 1) * (1000000000 : Int) := - Int.mul_nonneg h0 (by decide) - have e : (r + 1) * (1000000000 : Int) + 698600000 = - r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - unfold lnErrorBoundDen lnErrorBoundNum - rw [Int.add_mul, Int.one_mul] - omega - rw [← e] - exact Int.add_nonneg hp (by decide) - apply Int.ofNat_le.mp - rw [Int.natCast_add, posPhaseNatLt_cast hX hneg] - unfold lnPhaseExtraArg lnErrArg - have htarget : ((((r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)).toNat * - 2 ^ 99 : Nat) : Int)) = - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - rw [Int.natCast_mul, Int.toNat_of_nonneg harg] - unfold twoPow99I - rfl - have hextra : (((lnErrorExtraNum * twoPow99N : Nat) : Int)) = - (lnErrorExtraNum : Int) * twoPow99I := by - unfold twoPow99N twoPow99I - rfl - rw [htarget, hextra] - simpa [lnErrorBoundDen, lnErrorBoundNum, lnErrorExtraNum, twoPow99N, twoPow99I] - using hcore - -theorem posPhaseNatGe_gap_extra_le_lnErrArg {m c : Nat} {r : Int} - (hX : 0 ≤ int256 (x1W (zWord m))) (hc : c ≤ 160) (hr0 : -1 ≤ r) - (hgap : PosShiftDirectResidueGapOk m c r) : - posPhaseNatGe m c + lnPhaseExtraArg + lnDirectGapArg ≤ lnErrArg r := by - have hres := direct_residue_phase_bound (m := m) (c := c) (r := r) hc hgap - have hcore := pos_direct_residue_arg_le_int hres - have harg : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - have h0 : 0 ≤ r + 1 := by omega - have hp : 0 ≤ (r + 1) * (1000000000 : Int) := - Int.mul_nonneg h0 (by decide) - have e : (r + 1) * (1000000000 : Int) + 698600000 = - r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - unfold lnErrorBoundDen lnErrorBoundNum - rw [Int.add_mul, Int.one_mul] - omega - rw [← e] - exact Int.add_nonneg hp (by decide) - apply Int.ofNat_le.mp - rw [Int.natCast_add, Int.natCast_add, posPhaseNatGe_cast hX] - unfold lnPhaseExtraArg lnDirectGapArg lnErrArg - have htarget : ((((r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)).toNat * - 2 ^ 99 : Nat) : Int)) = - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - rw [Int.natCast_mul, Int.toNat_of_nonneg harg] - unfold twoPow99I - rfl - have hextra : (((lnErrorExtraNum * twoPow99N : Nat) : Int)) = - (lnErrorExtraNum : Int) * twoPow99I := by - unfold twoPow99N twoPow99I - rfl - have hgapcast : - (((lnErrorDirectResidueGap * twoPow27N * lnErrorBoundDen : Nat) : Int)) = - (lnErrorDirectResidueGap : Int) * twoPow27I * (lnErrorBoundDen : Int) := by - unfold lnErrorDirectResidueGap twoPow27N twoPow27I lnErrorBoundDen - decide - rw [htarget, hextra, hgapcast] - simpa [lnErrorBoundDen, lnErrorBoundNum, lnErrorExtraNum, twoPow99I] - using hcore - -theorem posPhaseNatLt_gap_extra_le_lnErrArg {m c : Nat} {r : Int} - (hX : int256 (x1W (zWord m)) ≤ 0) (hc : c ≤ 160) - (hneg : posNegXNat m ≤ posConstNat c) (hr0 : -1 ≤ r) - (hgap : PosShiftDirectResidueGapOk m c r) : - posPhaseNatLt m c + lnPhaseExtraArg + lnDirectGapArg ≤ lnErrArg r := by - have hres := direct_residue_phase_bound (m := m) (c := c) (r := r) hc hgap - have hcore := pos_direct_residue_arg_le_int hres - have harg : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - have h0 : 0 ≤ r + 1 := by omega - have hp : 0 ≤ (r + 1) * (1000000000 : Int) := - Int.mul_nonneg h0 (by decide) - have e : (r + 1) * (1000000000 : Int) + 698600000 = - r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - unfold lnErrorBoundDen lnErrorBoundNum - rw [Int.add_mul, Int.one_mul] - omega - rw [← e] - exact Int.add_nonneg hp (by decide) - apply Int.ofNat_le.mp - rw [Int.natCast_add, Int.natCast_add, posPhaseNatLt_cast hX hneg] - unfold lnPhaseExtraArg lnDirectGapArg lnErrArg - have htarget : ((((r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)).toNat * - 2 ^ 99 : Nat) : Int)) = - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - rw [Int.natCast_mul, Int.toNat_of_nonneg harg] - unfold twoPow99I - rfl - have hextra : (((lnErrorExtraNum * twoPow99N : Nat) : Int)) = - (lnErrorExtraNum : Int) * twoPow99I := by - unfold twoPow99N twoPow99I - rfl - have hgapcast : - (((lnErrorDirectResidueGap * twoPow27N * lnErrorBoundDen : Nat) : Int)) = - (lnErrorDirectResidueGap : Int) * twoPow27I * (lnErrorBoundDen : Int) := by - unfold lnErrorDirectResidueGap twoPow27N twoPow27I lnErrorBoundDen - decide - rw [htarget, hextra, hgapcast] - simpa [lnErrorBoundDen, lnErrorBoundNum, lnErrorExtraNum, twoPow99I] - using hcore - -theorem ge_phase_gap_direct_to_top {n m c : Nat} {r : Int} - (hX : 0 ≤ int256 (x1W (zWord m))) (hc : c ≤ 160) (hr0 : -1 ≤ r) - (hgap : PosShiftDirectResidueGapOk m c r) - (hdirect : PosShiftGePhaseGapDirectOk n m c) : - sumGE n (lnErrArg r) lnErrQ (posTopX c m) (10 ^ 18) := by - unfold PosShiftGePhaseGapDirectOk at hdirect - exact sumGE_exact_mono - (posPhaseNatGe_gap_extra_le_lnErrArg hX hc hr0 hgap) - (Nat.le_refl _) hdirect - -theorem lt_phase_gap_direct_to_top {n m c : Nat} {r : Int} - (hX : int256 (x1W (zWord m)) ≤ 0) (hc : c ≤ 160) - (hneg : posNegXNat m ≤ posConstNat c) (hr0 : -1 ≤ r) - (hgap : PosShiftDirectResidueGapOk m c r) - (hdirect : PosShiftLtPhaseGapDirectOk n m c) : - sumGE n (lnErrArg r) lnErrQ (posTopX c m) (10 ^ 18) := by - unfold PosShiftLtPhaseGapDirectOk at hdirect - exact sumGE_exact_mono - (posPhaseNatLt_gap_extra_le_lnErrArg hX hc hneg hr0 hgap) - (Nat.le_refl _) hdirect - -theorem capLB_first_order_self (p q : Nat) : - capLB p q (q + p) q := by - refine ⟨1, ?_⟩ - simp only [fact, expNum, Nat.pow_one, Nat.mul_one, Nat.one_mul, Nat.zero_add] - exact Nat.le_refl _ - -theorem capLB_cancel_first_order_budget {arg const neg q C W G V yT wT : Nat} - (hq : 0 < q) - (hconst : capLB const q C W) - (hneg : capUB neg q G V) - (hneg_le : neg ≤ const) - (hphase : const - neg ≤ arg) - (hW : 0 < W) - (hG : 0 < G) - (hbudget : yT * ((W * q) * G) ≤ - ((C * (q + (arg - (const - neg)))) * V) * wT) : - capLB arg q yT wT := by - have capE := capLB_first_order_self (arg - (const - neg)) q - have hsum0 := capLB_mul hconst capE - have hsplit : const + (arg - (const - neg)) = - ((const - neg) + (arg - (const - neg))) + neg := by - calc - const + (arg - (const - neg)) = - (const - neg + neg) + (arg - (const - neg)) := by - rw [Nat.sub_add_cancel hneg_le] - _ = ((const - neg) + (arg - (const - neg))) + neg := by - omega - rw [hsplit] at hsum0 - have capV := capLB_cancel (q := q) hq hsum0 hneg - have harg : (const - neg) + (arg - (const - neg)) = arg := by - exact Nat.add_sub_of_le hphase - rw [harg] at capV - refine capLB_weaken ?_ capV hbudget - exact Nat.mul_pos (Nat.mul_pos hW hq) hG - -theorem pos_residue_arg_le_int {A r : Int} - (hres : A * (lnErrorBoundDen : Int) + (lnErrorCoarsePosResidue : Int) ≤ - (r + 1) * twoPow99I * (lnErrorBoundDen : Int)) : - A * (lnErrorBoundDen : Int) + (lnErrorExtraNum : Int) * twoPow99I + - (lnErrorCoarsePosResidue : Int) ≤ - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - have hnum : ((lnErrorBoundNum : Nat) : Int) = (1698600000 : Int) := by - unfold lnErrorBoundNum - rfl - have hextra : ((lnErrorExtraNum : Nat) : Int) = (698600000 : Int) := by - unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen - decide +kernel - rw [hden] at hres - rw [hden, hnum, hextra] - unfold twoPow99I at hres ⊢ - omega - -theorem pos_ge_residue_arg_le_int {A r : Int} - (hres : A * (lnErrorBoundDen : Int) + (lnErrorCoarseGePosResidue : Int) ≤ - (r + 1) * twoPow99I * (lnErrorBoundDen : Int)) : - A * (lnErrorBoundDen : Int) + (lnErrorExtraNum : Int) * twoPow99I + - (lnErrorCoarseGePosResidue : Int) ≤ - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - have hnum : ((lnErrorBoundNum : Nat) : Int) = (1698600000 : Int) := by - unfold lnErrorBoundNum - rfl - have hextra : ((lnErrorExtraNum : Nat) : Int) = (698600000 : Int) := by - unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen - decide +kernel - rw [hden] at hres - rw [hden, hnum, hextra] - unfold twoPow99I at hres ⊢ - omega - -theorem errBudgetL_fold {m k : Nat} (hm : Sc - 45 ≤ m) (hk : k ≤ 159) : - (m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) ≤ - m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * - (10 ^ 31 + lnErrorCoarsePosBudgetCap) * (10 ^ 31 - 10) * 10 ^ 18) := by - have hb := errBudgetL_le (k := k) hk - have hcross : (m + 1) * (Sc - 45) ≤ m * ((Sc - 45) + 1) := by - have e1 : (m + 1) * (Sc - 45) = m * (Sc - 45) + (Sc - 45) := by - rw [Nat.add_mul, Nat.one_mul] - have e2 : m * ((Sc - 45) + 1) = m * (Sc - 45) + m := by - rw [Nat.mul_add, Nat.mul_one] - omega - refine Nat.le_of_mul_le_mul_left ?_ (show 0 < Sc - 45 by decide) - calc (Sc - 45) * ((m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) - = ((m + 1) * (Sc - 45)) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by - simp only [Nat.mul_assoc, Nat.mul_left_comm] - _ ≤ (m * ((Sc - 45) + 1)) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := - Nat.mul_le_mul_right _ hcross - _ = m * (((Sc - 45) + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) := by - simp only [Nat.mul_assoc] - _ = m * (((Sc - 45) + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by - simp only [Nat.mul_assoc] - _ ≤ m * ((Sc - 45) * (10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18) := - Nat.mul_le_mul_left _ hb - _ = (Sc - 45) * (m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18)) := by - simp only [Nat.mul_comm, Nat.mul_left_comm] - -theorem errBudgetL_ge_fold {m k : Nat} (hm : Sc ≤ m) (hk : k ≤ 159) : - (m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) ≤ - m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * - (10 ^ 31 + lnErrorCoarseGePosBudgetCap) * (10 ^ 31 - 10) * 10 ^ 18) := by - have hb := errBudgetLGe_le (k := k) hk - have hcross : (m + 1) * Sc ≤ m * (Sc + 1) := by - have e1 : (m + 1) * Sc = m * Sc + Sc := by - rw [Nat.add_mul, Nat.one_mul] - have e2 : m * (Sc + 1) = m * Sc + m := by - rw [Nat.mul_add, Nat.mul_one] - omega - refine Nat.le_of_mul_le_mul_left ?_ (show 0 < Sc by decide) - calc Sc * ((m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) - = ((m + 1) * Sc) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by - simp only [Nat.mul_assoc, Nat.mul_left_comm] - _ ≤ (m * (Sc + 1)) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := - Nat.mul_le_mul_right _ hcross - _ = m * ((Sc + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) := by - simp only [Nat.mul_assoc] - _ = m * ((Sc + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by - simp only [Nat.mul_assoc] - _ ≤ m * (Sc * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarseGePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18)) := - Nat.mul_le_mul_left _ (by - simpa only [Nat.mul_assoc] using hb) - _ = Sc * (m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarseGePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18)) := by - simp only [Nat.mul_comm, Nat.mul_left_comm] - -theorem lo_ge_pos_budget_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) - (_hc : c < 160) - (hbudget : PosShiftGeBudgetOk m c x r) : - capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by - have cap1 := capLB_lift_right (den := lnErrorBoundDen) QS_pos (x1capGeLoF h1 h2) - have cap2LQ := capLB_lift_right (den := lnErrorBoundDen) QS_pos cap2L - have cap2 := capLB_pow cap2LQ (160 - c) - have capB := capLB_lift_right (den := lnErrorBoundDen) QS_pos capBL - have cap12 := capLB_mul cap1 cap2 - have cap123 := capLB_mul cap12 capB - change capLB (posPhaseNatGe m c) lnErrQ (posBaseYGe m c) (posBaseWGe c) at cap123 - have capE := capLB_first_order_self (posAvailGe m c r) lnErrQ - have capR0 := capLB_mul cap123 capE - have hphase : posPhaseNatGe m c ≤ lnErrArg r := hbudget.1 - have hsum : posPhaseNatGe m c + posAvailGe m c r = lnErrArg r := by - unfold posAvailGe - exact Nat.add_sub_of_le hphase - rw [hsum] at capR0 - refine capLB_weaken ?_ capR0 ?_ - · unfold posBaseWGe lnErrQ QS lnErrorBoundDen - exact Nat.mul_pos (Nat.mul_pos (Nat.mul_pos (by decide) (Nat.pow_pos (by decide))) - (by decide)) (by decide) - · exact hbudget.2 - -theorem lo_lt_pos_budget_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) - (_hc : c < 160) - (hbudget : PosShiftLtBudgetOk m c x r) : - capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by - have cap1 := capUB_lift_right (den := lnErrorBoundDen) QS_pos (x1capLtLoF h1 h2) - have cap2LQ := capLB_lift_right (den := lnErrorBoundDen) QS_pos cap2L - have cap2 := capLB_pow cap2LQ (160 - c) - have capB := capLB_lift_right (den := lnErrorBoundDen) QS_pos capBL - have hsum0 := capLB_mul cap2 capB - change capUB (posNegXNat m) lnErrQ - 560227709747861399187319382270000000000000000000000000000000 - (m * 9999999999999999999999999996615) at cap1 - change capLB (posConstNat c) lnErrQ - ((2 * (10 ^ 40 - 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3384))) - (((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31))) at hsum0 - refine capLB_cancel_first_order_budget - (arg := lnErrArg r) - (const := posConstNat c) - (neg := posNegXNat m) - (q := lnErrQ) - (C := ((2 * (10 ^ 40 - 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3384)))) - (W := (((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31)))) - (G := 560227709747861399187319382270000000000000000000000000000000) - (V := m * 9999999999999999999999999996615) - (yT := wadRayNum x) - (wT := wadRayStrictDen) - (by unfold lnErrQ; decide) - hsum0 cap1 hbudget.1 hbudget.2.1 ?_ ?_ ?_ - · exact Nat.mul_pos (Nat.pow_pos (by decide)) (by decide) - · decide - · simpa [PosShiftLtBudgetOk, posBaseYLt, posBaseWLt, posAvailLt, - posPhaseNatLt, Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] using hbudget.2.2 - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean index 24fae95e5..cb9b78438 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchBn.lean @@ -24,7 +24,7 @@ attribute [local irreducible] lnWadToRayBody theorem bn_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrneg : r ≤ -2) (hmx : m = x * 2 ^ (c - 160)) : capUB (lnErrNegArg r) lnErrQ wadRayStrictDen (wadRayNum x) := by @@ -38,11 +38,11 @@ theorem bn_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := Int.mul_le_mul_of_nonneg_right (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551560854268589826112230 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (by decide : (0 : Int) ≤ 2 ^ 27) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -275,7 +275,7 @@ theorem bn_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem bn_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrneg : r ≤ -2) (hmx : m = x * 2 ^ (c - 160)) : capUB (lnErrNegArg r) lnErrQ wadRayStrictDen (wadRayNum x) := by @@ -289,11 +289,11 @@ theorem bn_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := Int.mul_le_mul_of_nonneg_right (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551560854268589826112230 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (by decide : (0 : Int) ≤ 2 ^ 27) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean deleted file mode 100644 index 206bfa2b5..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchCert.lean +++ /dev/null @@ -1,584 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.ExpMargin -import LnProof.Error.Core.ResidueCover -import LnProof.Error.Core.Budget -import LnProof.Error.Core.Direct -import LnProof.Error.Core.PhaseCover -import LnProof.Error.Core.Bounds -import LnProof.Error.Core.Assembly -import LnProof.Cert.HardMantissaLtGap - -/-! -# Error bound — BranchCert - -Branch-certificate predicates, the decidable cell/cover deciders, and the `lnWadToRayBody_positive_shift_*_branch_cert` theorems. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def PosShiftGeBranchCert (m c : Nat) (r : Int) : Prop := - PosShiftGeResidueOk m c r ∨ - PosShiftGeTopBudgetIneqOk m c ∨ - PosShiftTopDirectOk 320 m c ∨ - PosShiftGePhaseDirectOk 320 m c ∨ - (PosShiftDirectResidueGapOk m c r ∧ PosShiftGePhaseGapDirectOk 320 m c) - -def PosShiftLtBranchCert (m c : Nat) (r : Int) : Prop := - PosShiftResidueOk m c r ∨ - PosShiftLtTopBudgetIneqOk m c ∨ - PosShiftTopDirectOk 320 m c ∨ - PosShiftLtPhaseDirectOk 320 m c ∨ - (PosShiftDirectResidueGapOk m c r ∧ PosShiftLtPhaseGapDirectOk 320 m c) - -def posShiftGeTopBudgetIneqOkB (m c : Nat) : Bool := - decide (wadRayNum (posTopX c m) * (posBaseWGe c * lnErrQ) ≤ - (posBaseYGe m c * - (lnErrQ + posAvailGe m c (int256 (lnTail (evmSub 160 c) m)))) * - wadRayStrictDen) - -def posShiftLtTopBudgetIneqOkB (m c : Nat) : Bool := - decide (wadRayNum (posTopX c m) * (posBaseWLt c * lnErrQ) ≤ - (posBaseYLt m c * - (lnErrQ + posAvailLt m c (int256 (lnTail (evmSub 160 c) m)))) * - wadRayStrictDen) - -def posShiftTopDirectOkB (m c : Nat) : Bool := - sumGEB 320 (lnErrArg (int256 (lnTail (evmSub 160 c) m))) lnErrQ - (posTopX c m) (10 ^ 18) - -def posShiftGePhaseDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatGe m c + lnPhaseExtraArg) lnErrQ - (posTopX c m) (10 ^ 18) - -def posShiftLtPhaseDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatLt m c + lnPhaseExtraArg) lnErrQ - (posTopX c m) (10 ^ 18) - -def posShiftGeMinPhaseDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatGe m c + minPosAvail) lnErrQ - (posTopX c m) (10 ^ 18) - -def posShiftLtMinPhaseDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatLt m c + minPosAvail) lnErrQ - (posTopX c m) (10 ^ 18) - -def posShiftGePhaseGapDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatGe m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ - (posTopX c m) (10 ^ 18) - -def posShiftGeBranchCertB (m c : Nat) (r : Int) : Bool := - geResidueGapOkB m c r || - (posShiftGeTopBudgetIneqOkB m c || - (posShiftTopDirectOkB m c || - (posShiftGePhaseDirectOkB m c || - (directResidueGapOkB m c r && posShiftGePhaseGapDirectOkB m c) - ))) - -def posShiftLtBranchCertB (m c : Nat) (r : Int) : Bool := - residueGapOkB m c r || - (posShiftLtTopBudgetIneqOkB m c || - (posShiftTopDirectOkB m c || - (posShiftLtPhaseDirectOkB m c || - (directResidueGapOkB m c r && posShiftLtPhaseGapDirectOkB m c) - ))) - -theorem hardMantissaLtGapBranch {c : Nat} (hc1 : 1 ≤ c) (hc : c < 160) : - PosShiftDirectResidueGapOk lnErrorHardMantissa c - (int256 (lnTail (evmSub 160 c) lnErrorHardMantissa)) ∧ - PosShiftLtPhaseGapDirectOk 320 lnErrorHardMantissa c := by - have h := List.all_eq_true.mp hardMantissaLtGapBranch_all (c - 1) - (List.mem_range.mpr (by omega : c - 1 < 159)) - rw [show c - 1 + 1 = c by omega] at h - unfold hardMantissaLtGapBranchB at h - rw [Bool.and_eq_true] at h - exact ⟨PosShiftDirectResidueGapOk.of_bool h.1, by - unfold posShiftLtPhaseGapDirectOkB at h - unfold PosShiftLtPhaseGapDirectOk - exact sumGE_of_sumGEB h.2⟩ - -theorem hardMantissaLtBranchCert {c : Nat} (hc1 : 1 ≤ c) (hc : c < 160) : - PosShiftLtBranchCert lnErrorHardMantissa c - (int256 (lnTail (evmSub 160 c) lnErrorHardMantissa)) := by - exact Or.inr (Or.inr (Or.inr (Or.inr (hardMantissaLtGapBranch hc1 hc)))) - -theorem posShiftGeBranchCert_of_bool {m c : Nat} {r : Int} (hc : c ≤ 160) - (h : posShiftGeBranchCertB m c r = true) : - PosShiftGeBranchCert m c r := by - unfold posShiftGeBranchCertB at h - unfold PosShiftGeBranchCert - rw [Bool.or_eq_true] at h - rcases h with hres | hrest - · exact Or.inl (PosShiftGeResidueOk_of_gapB hc hres) - · rw [Bool.or_eq_true] at hrest - rcases hrest with htop | hrest - · exact Or.inr (Or.inl (by - unfold posShiftGeTopBudgetIneqOkB at htop - unfold PosShiftGeTopBudgetIneqOk PosShiftGeBudgetIneqOk - exact of_decide_eq_true htop)) - · rw [Bool.or_eq_true] at hrest - rcases hrest with hdir | hrest - · exact Or.inr (Or.inr (Or.inl (by - unfold posShiftTopDirectOkB at hdir - unfold PosShiftTopDirectOk - exact sumGE_of_sumGEB hdir))) - · rw [Bool.or_eq_true] at hrest - rcases hrest with hphase | hgapBool - · exact Or.inr (Or.inr (Or.inr (Or.inl (by - unfold posShiftGePhaseDirectOkB at hphase - unfold PosShiftGePhaseDirectOk - exact sumGE_of_sumGEB hphase)))) - · rw [Bool.and_eq_true] at hgapBool - have hgap := hgapBool - exact Or.inr (Or.inr (Or.inr (Or.inr ⟨PosShiftDirectResidueGapOk.of_bool hgap.1, by - unfold posShiftGePhaseGapDirectOkB at hgap - unfold PosShiftGePhaseGapDirectOk - exact sumGE_of_sumGEB hgap.2⟩))) - -theorem posShiftLtBranchCert_of_bool {m c : Nat} {r : Int} - (hc : c ≤ 160) - (h : posShiftLtBranchCertB m c r = true) : - PosShiftLtBranchCert m c r := by - unfold posShiftLtBranchCertB at h - unfold PosShiftLtBranchCert - rw [Bool.or_eq_true] at h - rcases h with hres | hrest - · exact Or.inl (PosShiftResidueOk_of_gapB hc hres) - · rw [Bool.or_eq_true] at hrest - rcases hrest with htop | hrest - · exact Or.inr (Or.inl (by - unfold posShiftLtTopBudgetIneqOkB at htop - unfold PosShiftLtTopBudgetIneqOk PosShiftLtBudgetIneqOk - exact of_decide_eq_true htop)) - · rw [Bool.or_eq_true] at hrest - rcases hrest with hdir | hrest - · exact Or.inr (Or.inr (Or.inl (by - unfold posShiftTopDirectOkB at hdir - unfold PosShiftTopDirectOk - exact sumGE_of_sumGEB hdir))) - · rw [Bool.or_eq_true] at hrest - rcases hrest with hphase | hgapBool - · exact Or.inr (Or.inr (Or.inr (Or.inl (by - unfold posShiftLtPhaseDirectOkB at hphase - unfold PosShiftLtPhaseDirectOk - exact sumGE_of_sumGEB hphase)))) - · rw [Bool.and_eq_true] at hgapBool - have hgap := hgapBool - exact Or.inr (Or.inr (Or.inr (Or.inr ⟨PosShiftDirectResidueGapOk.of_bool hgap.1, by - unfold posShiftLtPhaseGapDirectOkB at hgap - unfold PosShiftLtPhaseGapDirectOk - exact sumGE_of_sumGEB hgap.2⟩))) - -def directTopCellOkB (lo hi c : Nat) : Bool := - ({ c := c, lo := lo, hi := hi, n := 320 } : PosShiftDirectCell).okB - -def geBranchCellOkB (lo hi c : Nat) : Bool := - geResidueRunCellOkB lo hi c || - (geResidueCellOkB lo hi c || - (geTopBudgetCoarseCellOkB lo hi c || - (geTopBudgetRunCellOkB lo hi c || - (directTopCellOkB lo hi c || - (gePhaseCellOkB lo hi c || - ((directResidueRunCellOkB lo hi c && gePhaseGapCellOkB lo hi c) || - (directResidueCellOkB lo hi c && gePhaseGapCellOkB lo hi c))))))) - -def ltBranchCellOkB (lo hi c : Nat) : Bool := - residueRunCellOkB lo hi c || - (ltTopBudgetCoarseCellOkB lo hi c || - (ltTopBudgetRunCellOkB lo hi c || - (directTopCellOkB lo hi c || - (ltPhaseCellOkB lo hi c || - ((directResidueRunCellOkB lo hi c && ltPhaseGapCellOkB lo hi c) || - (directResidueCellOkB lo hi c && ltPhaseGapCellOkB lo hi c)))))) - -theorem geBranchCellOkB_sound {lo hi m c : Nat} - (h : geBranchCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeBranchCert m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold geBranchCellOkB at h - simp only [Bool.or_eq_true, Bool.and_eq_true] at h - rcases h with hrun | hrest - · exact Or.inl (geResidueRunCellOkB_sound hrun hlom hmhi) - rcases hrest with hres | hrest - · exact Or.inl (geResidueCellOkB_sound hres hlom hmhi) - rcases hrest with htop | hrest - · exact Or.inr (Or.inl (geTopBudgetCoarseCellOkB_sound htop hlom hmhi)) - rcases hrest with htop | hrest - · exact Or.inr (Or.inl (geTopBudgetRunCellOkB_sound htop hlom hmhi)) - rcases hrest with hdir | hrest - · exact Or.inr (Or.inr (Or.inl - (PosShiftDirectCell.sound (PosShiftDirectCell.ok_of_okB hdir) - (by - unfold PosShiftDirectCell.Covers directTopCellOkB at * - exact ⟨rfl, hlom, hmhi⟩)))) - rcases hrest with hphase | hgap - · exact Or.inr (Or.inr (Or.inr (Or.inl (gePhaseCell_sound hphase hlom hmhi)))) - · rcases hgap with hgapRun | hgapCell - · exact Or.inr (Or.inr (Or.inr (Or.inr - ⟨directResidueRunCellOkB_sound hgapRun.1 hlom hmhi, - gePhaseGapCell_sound hgapRun.2 hlom hmhi⟩))) - · exact Or.inr (Or.inr (Or.inr (Or.inr - ⟨directResidueCellOkB_sound hgapCell.1 hlom hmhi, - gePhaseGapCell_sound hgapCell.2 hlom hmhi⟩))) - -theorem ltBranchCellOkB_sound {lo hi m c : Nat} - (h : ltBranchCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtBranchCert m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold ltBranchCellOkB at h - simp only [Bool.or_eq_true, Bool.and_eq_true] at h - rcases h with hres | hrest - · exact Or.inl (residueRunCellOkB_sound hres hlom hmhi) - rcases hrest with htop | hrest - · exact Or.inr (Or.inl (ltTopBudgetCoarseCellOkB_sound htop hlom hmhi)) - rcases hrest with htop | hrest - · exact Or.inr (Or.inl (ltTopBudgetRunCellOkB_sound htop hlom hmhi)) - rcases hrest with hdir | hrest - · exact Or.inr (Or.inr (Or.inl - (PosShiftDirectCell.sound (PosShiftDirectCell.ok_of_okB hdir) - (by - unfold PosShiftDirectCell.Covers directTopCellOkB at * - exact ⟨rfl, hlom, hmhi⟩)))) - rcases hrest with hphase | hgap - · exact Or.inr (Or.inr (Or.inr (Or.inl (ltPhaseCell_sound hphase hlom hmhi)))) - · rcases hgap with hgapRun | hgapCell - · exact Or.inr (Or.inr (Or.inr (Or.inr - ⟨directResidueRunCellOkB_sound hgapRun.1 hlom hmhi, - ltPhaseGapCell_sound hgapRun.2 hlom hmhi⟩))) - · exact Or.inr (Or.inr (Or.inr (Or.inr - ⟨directResidueCellOkB_sound hgapCell.1 hlom hmhi, - ltPhaseGapCell_sound hgapCell.2 hlom hmhi⟩))) - -def geBranchCellListCoverB (c : Nat) : Nat → Nat → List ResidueCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - geBranchCellOkB cell.lo cell.hi c && - geBranchCellListCoverB c (cell.hi + 1) hi cells - -def ltBranchCellListCoverB (c : Nat) : Nat → Nat → List ResidueCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - ltBranchCellOkB cell.lo cell.hi c && - ltBranchCellListCoverB c (cell.hi + 1) hi cells - -theorem geBranchCellListCoverB_sound {cells : List ResidueCell} {c lo hi m : Nat} - (h : geBranchCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeBranchCert m c (int256 (lnTail (evmSub 160 c) m)) := by - induction cells generalizing lo with - | nil => - unfold geBranchCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold geBranchCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact geBranchCellOkB_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -theorem ltBranchCellListCoverB_sound {cells : List ResidueCell} {c lo hi m : Nat} - (h : ltBranchCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtBranchCert m c (int256 (lnTail (evmSub 160 c) m)) := by - induction cells generalizing lo with - | nil => - unfold ltBranchCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold ltBranchCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact ltBranchCellOkB_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -def geBranchCoverB : Nat → Nat → Nat → Nat → Bool - | 0, _c, lo, hi => decide (hi < lo) - | fuel + 1, c, lo, hi => - if hi < lo then - true - else - let mx := phaseSearchMax phaseSearchFuel (fun h => geBranchCellOkB lo h c) - lo hi (lo - 1) - decide (lo ≤ mx) && - decide (mx ≤ hi) && - geBranchCellOkB lo mx c && - geBranchCoverB fuel c (mx + 1) hi - -def ltBranchCoverB : Nat → Nat → Nat → Nat → Bool - | 0, _c, lo, hi => decide (hi < lo) - | fuel + 1, c, lo, hi => - if hi < lo then - true - else - let mx := phaseSearchMax phaseSearchFuel (fun h => ltBranchCellOkB lo h c) - lo hi (lo - 1) - decide (lo ≤ mx) && - decide (mx ≤ hi) && - ltBranchCellOkB lo mx c && - ltBranchCoverB fuel c (mx + 1) hi - -theorem geBranchCoverB_sound {fuel c lo hi m : Nat} - (h : geBranchCoverB fuel c lo hi = true) (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeBranchCert m c (int256 (lnTail (evmSub 160 c) m)) := by - revert lo - induction fuel with - | zero => - intro lo h hlom - unfold geBranchCoverB at h - simp only [decide_eq_true_eq] at h - omega - | succ fuel ih => - intro lo h hlom - unfold geBranchCoverB at h - by_cases hdone : hi < lo - · rw [if_pos hdone] at h - omega - · rw [if_neg hdone] at h - let mx := phaseSearchMax phaseSearchFuel (fun h => geBranchCellOkB lo h c) - lo hi (lo - 1) - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨hlmx, hmxhi⟩, hcell⟩, hrest⟩ := h - by_cases hleft : m ≤ mx - · exact geBranchCellOkB_sound hcell hlom hleft - · exact ih (lo := mx + 1) hrest (by omega) - -theorem ltBranchCoverB_sound {fuel c lo hi m : Nat} - (h : ltBranchCoverB fuel c lo hi = true) (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtBranchCert m c (int256 (lnTail (evmSub 160 c) m)) := by - revert lo - induction fuel with - | zero => - intro lo h hlom - unfold ltBranchCoverB at h - simp only [decide_eq_true_eq] at h - omega - | succ fuel ih => - intro lo h hlom - unfold ltBranchCoverB at h - by_cases hdone : hi < lo - · rw [if_pos hdone] at h - omega - · rw [if_neg hdone] at h - let mx := phaseSearchMax phaseSearchFuel (fun h => ltBranchCellOkB lo h c) - lo hi (lo - 1) - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨hlmx, hmxhi⟩, hcell⟩, hrest⟩ := h - by_cases hleft : m ≤ mx - · exact ltBranchCellOkB_sound hcell hlom hleft - · exact ih (lo := mx + 1) hrest (by omega) - -def branchCoverFuel : Nat := 1024 - -def phaseYMax (n p q w : Nat) : Nat := - let s := expSumState p q n - s.1 * w / s.2.1 - -def phaseTopMaxHi (n p q w c hi : Nat) : Nat := - min hi (((phaseYMax n p q w + 1) / 2 ^ (160 - c)) - 1) - -def ltPhaseTopMaxHi (n p q w c lo hi : Nat) : Nat := - let mx := phaseTopMaxHi n p q w c hi - if lo < lnErrorHardMantissa ∧ lnErrorHardMantissa ≤ mx then - lnErrorHardMantissa - 1 - else - mx - -def gePhaseCoverFastB : Nat → Nat → Nat → Nat → Bool - | 0, _c, lo, hi => decide (hi < lo) - | fuel + 1, c, lo, hi => - if hi < lo then - true - else - let mx := phaseTopMaxHi 320 (posPhaseNatGe lo c + lnPhaseExtraArg) - lnErrQ (10 ^ 18) c hi - decide (lo ≤ mx) && - gePhaseCellOkB lo mx c && - gePhaseCoverFastB fuel c (mx + 1) hi - -def ltPhaseCoverFastB : Nat → Nat → Nat → Nat → Bool - | 0, _c, lo, hi => decide (hi < lo) - | fuel + 1, c, lo, hi => - if hi < lo then - true - else if lo = lnErrorHardMantissa then - ltPhaseCoverFastB fuel c (lo + 1) hi - else - let mx := ltPhaseTopMaxHi 320 (posPhaseNatLt lo c + lnPhaseExtraArg) - lnErrQ (10 ^ 18) c lo hi - decide (lo ≤ mx) && - ltPhaseCellOkB lo mx c && - ltPhaseCoverFastB fuel c (mx + 1) hi - -theorem gePhaseCoverFastB_sound {fuel c lo hi m : Nat} - (h : gePhaseCoverFastB fuel c lo hi = true) (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGePhaseDirectOk 320 m c := by - revert lo - induction fuel with - | zero => - intro lo h hlom - unfold gePhaseCoverFastB at h - simp only [decide_eq_true_eq] at h - omega - | succ fuel ih => - intro lo h hlom - unfold gePhaseCoverFastB at h - by_cases hdone : hi < lo - · rw [if_pos hdone] at h - omega - · rw [if_neg hdone] at h - let mx := phaseTopMaxHi 320 (posPhaseNatGe lo c + lnPhaseExtraArg) - lnErrQ (10 ^ 18) c hi - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨hlmx, hcell⟩, hrest⟩ := h - by_cases hleft : m ≤ mx - · exact gePhaseCell_sound hcell hlom hleft - · exact ih (lo := mx + 1) hrest (by omega) - -theorem ltPhaseCoverFastB_sound {fuel c lo hi m : Nat} - (h : ltPhaseCoverFastB fuel c lo hi = true) (hlom : lo ≤ m) (hmhi : m ≤ hi) : - m = lnErrorHardMantissa ∨ PosShiftLtPhaseDirectOk 320 m c := by - revert lo - induction fuel with - | zero => - intro lo h hlom - unfold ltPhaseCoverFastB at h - simp only [decide_eq_true_eq] at h - omega - | succ fuel ih => - intro lo h hlom - unfold ltPhaseCoverFastB at h - by_cases hdone : hi < lo - · rw [if_pos hdone] at h - omega - · rw [if_neg hdone] at h - by_cases hhard : lo = lnErrorHardMantissa - · rw [if_pos hhard] at h - by_cases hm : m = lo - · exact Or.inl (by omega) - · exact ih (lo := lo + 1) h (by omega) - · rw [if_neg hhard] at h - let mx := ltPhaseTopMaxHi 320 (posPhaseNatLt lo c + lnPhaseExtraArg) - lnErrQ (10 ^ 18) c lo hi - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨hlmx, hcell⟩, hrest⟩ := h - by_cases hleft : m ≤ mx - · exact Or.inr (ltPhaseCell_sound hcell hlom hleft) - · exact ih (lo := mx + 1) hrest (by omega) - -theorem lnWadToRayBody_positive_shift_ge_branch_cert {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hge : Sc ≤ mant x) - (hcert : PosShiftGeBranchCert (mant x) (evmClz x) - (int256 (lnWadToRayBody x))) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - rcases hcert with hres | hrest - · exact lnWadToRayBody_positive_shift_ge_residue_or_direct h1 h2 hclt hge - (Or.inl hres) - rcases hrest with htop | hrest - · exact lnWadToRayBody_positive_shift_ge_top_or_direct h1 h2 hne hclt hge - (Or.inl htop) - rcases hrest with hdirect | hrest - · exact lnWadToRayBody_positive_shift_ge_top_or_direct h1 h2 hne hclt hge - (Or.inr hdirect) - rcases hrest with hphase | hgap - · exact lnWadToRayBody_positive_shift_ge_phase_direct h1 h2 hne hclt hge hphase - · have hx256 : x < 2 ^ 256 := by omega - have htail : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - obtain ⟨me, _hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_hi : mant x < MHI := by - unfold mant - rw [me] - exact hmhi - have hX := x1_nonneg_geF hge hmant_hi - have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - have hc160 : evmClz x ≤ 160 := - Nat.le_of_lt_succ (Nat.lt_of_lt_of_le hclt (by decide : 160 ≤ 161)) - have hrm1 : -1 ≤ int256 (lnWadToRayBody x) := - Int.le_trans (by decide : (-1 : Int) ≤ 0) hr0 - have hsum := ge_phase_gap_direct_to_top - (m := mant x) (c := evmClz x) (r := int256 (lnWadToRayBody x)) - hX hc160 hrm1 hgap.1 hgap.2 - have hsumTail : - sumGE 320 - (lnErrArg (int256 (lnTail (evmSub 160 (evmClz x)) (mant x)))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - simpa [htail] using hsum - exact pos_shift_direct_exact_of_sumGE h1 h2 hclt hsumTail - -theorem lnWadToRayBody_positive_shift_lt_branch_cert {x : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 10 ^ 18) - (hclt : evmClz x < 160) (hlt : mant x < Sc) (hband_lo : Sc - 45 ≤ mant x) - (hcert : PosShiftLtBranchCert (mant x) (evmClz x) - (int256 (lnWadToRayBody x))) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - rcases hcert with hres | hrest - · exact lnWadToRayBody_positive_shift_lt_residue_or_direct h1 h2 hne hclt hlt hband_lo - (Or.inl hres) - rcases hrest with htop | hrest - · exact lnWadToRayBody_positive_shift_lt_top_or_direct h1 h2 hne hclt hlt - (Or.inl htop) - rcases hrest with hdirect | hrest - · exact lnWadToRayBody_positive_shift_lt_top_or_direct h1 h2 hne hclt hlt - (Or.inr hdirect) - rcases hrest with hphase | hgap - · exact lnWadToRayBody_positive_shift_lt_phase_direct h1 h2 hne hclt hlt hphase - · have hx256 : x < 2 ^ 256 := by omega - have htail : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - obtain ⟨hbr1, _hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne - rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 - obtain ⟨me, hmlo, _hmhi⟩ := mant_facts h1 h2 - have hmant_lo : MLO ≤ mant x := by - unfold mant - rw [me] - exact hmlo - have hX := x1_nonpos_ltF hmant_lo hlt - have hr0 := lnWadToRayBody_nonneg_of_clz_lt_160 h1 h2 hclt - have hc160 : evmClz x ≤ 160 := - Nat.le_of_lt_succ (Nat.lt_of_lt_of_le hclt (by decide : 160 ≤ 161)) - have hV0 : 0 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + lnBiasI := by - have hR0 : 0 ≤ int256 (lnWadToRayBody x) * 2 ^ 72 := - Int.mul_nonneg hr0 (by decide) - have h := Int.le_trans hR0 hbr1 - simpa [lnBiasI] using h - have hneg := posNegXNat_le_posConstNat hX hc160 hV0 - have hrm1 : -1 ≤ int256 (lnWadToRayBody x) := - Int.le_trans (by decide : (-1 : Int) ≤ 0) hr0 - have hsum := lt_phase_gap_direct_to_top - (m := mant x) (c := evmClz x) (r := int256 (lnWadToRayBody x)) - hX hc160 hneg hrm1 hgap.1 hgap.2 - have hsumTail : - sumGE 320 - (lnErrArg (int256 (lnTail (evmSub 160 (evmClz x)) (mant x)))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18) := by - simpa [htail] using hsum - exact pos_shift_direct_exact_of_sumGE h1 h2 hclt hsumTail - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean deleted file mode 100644 index b2aac9b32..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchCertHardDefs.lean +++ /dev/null @@ -1,19 +0,0 @@ -import LnProof.Error.Core.Direct - -open FormalYul -open FormalYul.Preservation - -namespace LnFloorCert - -open LnYul LnFloor - -def posShiftLtPhaseGapDirectOkB (m c : Nat) : Bool := - sumGEB 320 (posPhaseNatLt m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ - (posTopX c m) (10 ^ 18) - -def hardMantissaLtGapBranchB (c : Nat) : Bool := - directResidueGapOkB lnErrorHardMantissa c - (int256 (lnTail (evmSub 160 c) lnErrorHardMantissa)) && - posShiftLtPhaseGapDirectOkB lnErrorHardMantissa c - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean index 491f6fc75..5b41a04aa 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchNeg.lean @@ -25,9 +25,9 @@ attribute [local irreducible] lnWadToRayBody theorem lo_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) + 116873961749927929127912020551560854268589826112230) (hr0 : 0 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by @@ -41,12 +41,12 @@ theorem lo_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 := by have h0 : 0 ≤ r * 2 ^ 72 := Int.mul_nonneg hr0 (by decide) have hg : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ + 116873961749927929127912020551560854268589826112230 = V at hrlo ⊢ generalize hgR : r * 2 ^ 72 = R at hrlo h0 omega exact Int.mul_nonneg hg (by decide) @@ -280,9 +280,9 @@ theorem lo_ge_neg_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem lo_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) + 116873961749927929127912020551560854268589826112230) (hr0 : 0 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by @@ -296,12 +296,12 @@ theorem lo_lt_neg_exact {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 := by have h0 : 0 ≤ r * 2 ^ 72 := Int.mul_nonneg hr0 (by decide) have hg : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ + 116873961749927929127912020551560854268589826112230 = V at hrlo ⊢ generalize hgR : r * 2 ^ 72 = R at hrlo h0 omega exact Int.mul_nonneg hg (by decide) diff --git a/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean b/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean index 3205f6407..54720c71e 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/BranchPos.lean @@ -2,14 +2,13 @@ import LnProof.Floor.CutEquiv import LnProof.Error.Cert import LnProof.Error.Core.CutDefs import LnProof.Error.Core.Residue -import LnProof.Error.Core.ResidueCover -import LnProof.Error.Core.Bounds +import LnProof.Error.Core.Budget import LnProof.Error.Core.C160 /-! # Error bound — BranchPos -Positive-shift exact brackets: `lo_ge_pos_exact(_ge_residue)`, `lo_lt_pos_exact`. +Positive-shift exact brackets for the ge and lt residue branches. -/ open FormalYul @@ -24,183 +23,159 @@ open LnYul LnFloor Common.Exp Common.Poly attribute [local irreducible] lnWadToRayBody -theorem lo_ge_pos_exact {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) - (hc1 : 1 ≤ c) (hc : c < 160) - (hr0 : 0 ≤ r) - (hres : PosShiftResidueOk m c r) - (hxm : x < (m + 1) * 2 ^ (160 - c)) : - capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by - have harg_nonneg := ln_err_arg_nonneg (by omega : -1 ≤ r) - have hX1 := x1_nonneg_geF h1 h2 - have cap1 := capLB_lift_right (den := lnErrorBoundDen) QS_pos (x1capGeLoF h1 h2) - have cap2LQ := capLB_lift_right (den := lnErrorBoundDen) QS_pos cap2L - have cap2 := capLB_pow cap2LQ (160 - c) - have capB := capLB_lift_right (den := lnErrorBoundDen) QS_pos capBL - have cap12 := capLB_mul cap1 cap2 - have cap123 := capLB_mul cap12 capB - have cap1234 := capLB_mul cap123 capECoarsePosL - change capLB - (((int256 (x1W (zWord m))).toNat * lnPhaseScaleN * lnErrorBoundDen + - (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) + - BIASc * twoPow27N * lnErrorBoundDen) + - (lnErrorExtraNum * twoPow99N + lnErrorCoarsePosResidue)) - lnErrQ - (((m * 9999999999999999999999999996615) * - ((2 * (10 ^ 40 - 1)) ^ (160 - c))) * - (Sc * (10 ^ 31 - 3384)) * - (10 ^ 31 + lnErrorCoarsePosBudgetCap)) - (((560227709747861399187319382270000000000000000000000000000000 * - ((10 ^ 40 : Nat) ^ (160 - c))) * - (10 ^ 18 * 10 ^ 31)) * 10 ^ 31) at cap1234 - have hple : - ((int256 (x1W (zWord m))).toNat * lnPhaseScaleN * lnErrorBoundDen + - (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) + - BIASc * twoPow27N * lnErrorBoundDen) + - (lnErrorExtraNum * twoPow99N + lnErrorCoarsePosResidue) ≤ - lnErrArg r := by - apply Int.ofNat_le.mp - have htarget : (((r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)).toNat * - 2 ^ 99 : Nat) : Int) = - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - rw [Int.natCast_mul, Int.toNat_of_nonneg harg_nonneg] - unfold twoPow99I - rfl - have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = - int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX1 - have hBc : ((BIASc * twoPow27N : Nat) : Int) = lnBiasI * twoPow27I := by - unfold twoPow27N twoPow27I lnBiasI - decide +kernel - have hLc : (((160 - c) * (LN2c * twoPow27N) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) := by - simp only [Int.natCast_mul] - unfold twoPow27N twoPow27I - rfl - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - have hextra : ((lnErrorExtraNum * twoPow99N : Nat) : Int) = - (lnErrorExtraNum : Int) * twoPow99I := by - unfold twoPow99N twoPow99I - rfl - have hscale : ((lnPhaseScaleN : Nat) : Int) = lnPhaseScaleI := rfl - have hN : (((160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) : Nat) : Int) = - (((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I)) * - (1000000000 : Int) := by - rw [show (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) = - ((160 - c) * (LN2c * twoPow27N)) * lnErrorBoundDen by - simp only [Nat.mul_assoc]] - simp only [Int.natCast_mul, hLc, hden] - have hsum_cast : - ((((int256 (x1W (zWord m))).toNat * lnPhaseScaleN * lnErrorBoundDen + - (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) + - BIASc * twoPow27N * lnErrorBoundDen) + - (lnErrorExtraNum * twoPow99N + lnErrorCoarsePosResidue) : Nat) : Int) = - posPhaseI m c * (lnErrorBoundDen : Int) + - (lnErrorExtraNum : Int) * twoPow99I + - (lnErrorCoarsePosResidue : Int) := by - simp only [Int.natCast_add, Int.natCast_mul, hX1n, hBc, hN, hden, - hextra, hscale] - unfold posPhaseI - generalize int256 (x1W (zWord m)) * lnPhaseScaleI = A - generalize ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) = B - generalize lnBiasI * twoPow27I = C - generalize (lnErrorExtraNum : Int) * twoPow99I = E - generalize (lnErrorCoarsePosResidue : Int) = G - omega - rw [lnErrArg, htarget, hsum_cast] - exact pos_residue_arg_le_int hres - have hmul : - (((int256 (x1W (zWord m))).toNat * lnPhaseScaleN * lnErrorBoundDen + - (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) + - BIASc * twoPow27N * lnErrorBoundDen) + - (lnErrorExtraNum * twoPow99N + lnErrorCoarsePosResidue)) * lnErrQ ≤ - lnErrArg r * lnErrQ := - Nat.mul_le_mul_right _ hple - have capR := capLB_arg (q := lnErrQ) (by unfold lnErrQ; decide) hmul cap1234 - refine capLB_weaken (p := lnErrArg r) (q := lnErrQ) - (y := (((m * 9999999999999999999999999996615) * - ((2 * (10 ^ 40 - 1)) ^ (160 - c))) * - (Sc * (10 ^ 31 - 3384)) * - (10 ^ 31 + lnErrorCoarsePosBudgetCap))) - (w := (((560227709747861399187319382270000000000000000000000000000000 * - ((10 ^ 40 : Nat) ^ (160 - c))) * - (10 ^ 18 * 10 ^ 31)) * 10 ^ 31)) ?_ capR ?_ - · have h1' : 0 < (560227709747861399187319382270000000000000000000000000000000 : Nat) * - ((10 ^ 40 : Nat) ^ (160 - c)) := Nat.mul_pos (by decide) (Nat.pow_pos (by decide)) - have h2' : 0 < (560227709747861399187319382270000000000000000000000000000000 : Nat) * - ((10 ^ 40 : Nat) ^ (160 - c)) * (10 ^ 18 * 10 ^ 31) := - Nat.mul_pos h1' (by decide) - exact Nat.mul_pos h2' (by decide) - · have hMLO : Sc - 45 ≤ m := by omega - have hb := errBudgetL_fold (k := 160 - c) hMLO (by omega) - have hx1 : x + 1 ≤ (m + 1) * 2 ^ (160 - c) := by omega - have hxw : (x + 1) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) ≤ - (m + 1) * 2 ^ (160 - c) * - (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) := - Nat.mul_le_mul_right _ hx1 - have hfold : (m + 1) * 2 ^ (160 - c) * - (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) ≤ - m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ (160 - c) * +def PosShiftResidueOk (m c : Nat) (r : Int) : Prop := + posPhaseI m c * (lnErrorBoundDen : Int) + (lnErrorCoarsePosResidue : Int) ≤ + (r + 1) * twoPow99I * (lnErrorBoundDen : Int) + +def PosShiftGeResidueOk (m c : Nat) (r : Int) : Prop := + posPhaseI m c * (lnErrorBoundDen : Int) + (lnErrorCoarseGePosResidue : Int) ≤ + (r + 1) * twoPow99I * (lnErrorBoundDen : Int) + +def PosShiftResidueGapOk (m c : Nat) (r : Int) : Prop := + (lnErrorCoarsePosResidue : Int) ≤ + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) + +def PosShiftGeResidueGapOk (m c : Nat) (r : Int) : Prop := + (lnErrorCoarseGePosResidue : Int) ≤ + posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) + +theorem PosShiftResidueOk_of_gap {m c : Nat} {r : Int} + (hc : c ≤ 160) (hgap : PosShiftResidueGapOk m c r) : + PosShiftResidueOk m c r := by + have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc + have hVs' : posAccI m c * twoPow27I = posPhaseI m c := by + unfold posAccI posPhaseI + simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs + unfold PosShiftResidueGapOk posResidueGap at hgap + unfold PosShiftResidueOk + rw [← hVs'] + unfold twoPow72I twoPow27I at hgap + unfold twoPow27I twoPow99I + have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by + unfold lnErrorBoundDen + rfl + rw [hden] at hgap ⊢ + omega + +theorem PosShiftGeResidueOk_of_gap {m c : Nat} {r : Int} + (hc : c ≤ 160) (hgap : PosShiftGeResidueGapOk m c r) : + PosShiftGeResidueOk m c r := by + have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc + have hVs' : posAccI m c * twoPow27I = posPhaseI m c := by + unfold posAccI posPhaseI + simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs + unfold PosShiftGeResidueGapOk posResidueGap at hgap + unfold PosShiftGeResidueOk + rw [← hVs'] + unfold twoPow72I twoPow27I at hgap + unfold twoPow27I twoPow99I + have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by + unfold lnErrorBoundDen + rfl + rw [hden] at hgap ⊢ + omega + +theorem pos_residue_arg_le_int {A r : Int} + (hres : A * (lnErrorBoundDen : Int) + (lnErrorCoarsePosResidue : Int) ≤ + (r + 1) * twoPow99I * (lnErrorBoundDen : Int)) : + A * (lnErrorBoundDen : Int) + (lnErrorExtraNum : Int) * twoPow99I + + (lnErrorCoarsePosResidue : Int) ≤ + (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by + have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by + unfold lnErrorBoundDen + rfl + have hnum : ((lnErrorBoundNum : Nat) : Int) = (1698600000 : Int) := by + unfold lnErrorBoundNum + rfl + have hextra : ((lnErrorExtraNum : Nat) : Int) = (698600000 : Int) := by + unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen + decide +kernel + rw [hden] at hres + rw [hden, hnum, hextra] + unfold twoPow99I at hres ⊢ + omega + +theorem pos_ge_residue_arg_le_int {A r : Int} + (hres : A * (lnErrorBoundDen : Int) + (lnErrorCoarseGePosResidue : Int) ≤ + (r + 1) * twoPow99I * (lnErrorBoundDen : Int)) : + A * (lnErrorBoundDen : Int) + (lnErrorExtraNum : Int) * twoPow99I + + (lnErrorCoarseGePosResidue : Int) ≤ + (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by + have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by + unfold lnErrorBoundDen + rfl + have hnum : ((lnErrorBoundNum : Nat) : Int) = (1698600000 : Int) := by + unfold lnErrorBoundNum + rfl + have hextra : ((lnErrorExtraNum : Nat) : Int) = (698600000 : Int) := by + unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen + decide +kernel + rw [hden] at hres + rw [hden, hnum, hextra] + unfold twoPow99I at hres ⊢ + omega + +theorem errBudgetL_fold {m k : Nat} (hm : Sc - 45 ≤ m) (hk : k ≤ 159) : + (m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) ≤ + m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * + (10 ^ 31 + lnErrorCoarsePosBudgetCap) * (10 ^ 31 - 10) * 10 ^ 18) := by + have hb := errBudgetL_le (k := k) hk + have hcross : (m + 1) * (Sc - 45) ≤ m * ((Sc - 45) + 1) := by + have e1 : (m + 1) * (Sc - 45) = m * (Sc - 45) + (Sc - 45) := by + rw [Nat.add_mul, Nat.one_mul] + have e2 : m * ((Sc - 45) + 1) = m * (Sc - 45) + m := by + rw [Nat.mul_add, Nat.mul_one] + omega + refine Nat.le_of_mul_le_mul_left ?_ (show 0 < Sc - 45 by decide) + calc (Sc - 45) * ((m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) + = ((m + 1) * (Sc - 45)) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by + simp only [Nat.mul_assoc, Nat.mul_left_comm] + _ ≤ (m * ((Sc - 45) + 1)) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := + Nat.mul_le_mul_right _ hcross + _ = m * (((Sc - 45) + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) := by + simp only [Nat.mul_assoc] + _ = m * (((Sc - 45) + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by + simp only [Nat.mul_assoc] + _ ≤ m * ((Sc - 45) * (10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18) * Sc := by - have h := Nat.mul_le_mul_left Sc hb - have e1 : Sc * ((m + 1) * (2 ^ (160 - c) * - (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) = - (m + 1) * 2 ^ (160 - c) * - (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e2 : Sc * (m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ (160 - c) * + (10 ^ 31 - 10) * 10 ^ 18) := + Nat.mul_le_mul_left _ hb + _ = (Sc - 45) * (m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18)) = - m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ (160 - c) * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18) * Sc := by + (10 ^ 31 - 10) * 10 ^ 18)) := by simp only [Nat.mul_comm, Nat.mul_left_comm] - rw [e1] at h - rw [e2] at h - exact h - have eL : x * 10 ^ 31 * - (((560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 40 : Nat) ^ (160 - c)) * (10 ^ 18 * 10 ^ 31)) * 10 ^ 31) ≤ - (x + 1) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have eAC : x * 10 ^ 31 * - (((Sc * 10 ^ 31 * (10 ^ 40 : Nat) ^ (160 - c)) * - (10 ^ 18 * 10 ^ 31)) * 10 ^ 31) = - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * - ((10 : Nat) ^ 31 * (10 ^ 31 * (10 ^ 18 * 10 ^ 31 * 10 ^ 31))))) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - rw [eAC, show ((10 : Nat) ^ 31 * (10 ^ 31 * (10 ^ 18 * 10 ^ 31 * 10 ^ 31))) = - 10 ^ 142 from by decide] - exact Nat.mul_le_mul_right _ (by omega : x ≤ x + 1) - have eR : (((m * 9999999999999999999999999996615) * - ((2 * (10 ^ 40 - 1)) ^ (160 - c))) * - (Sc * (10 ^ 31 - 3384)) * (10 ^ 31 + lnErrorCoarsePosBudgetCap)) * - (10 ^ 18 * (10 ^ 31 - 10)) = - m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ (160 - c) * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18) * Sc := by - rw [show (9999999999999999999999999996615 : Nat) = 10 ^ 31 - 3385 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - unfold wadRayNum wadRayStrictDen - generalize hT1 : x * 10 ^ 31 * - (((560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 40 : Nat) ^ (160 - c)) * (10 ^ 18 * 10 ^ 31)) * 10 ^ 31) = T1 - at eL ⊢ - generalize hT2 : (x + 1) * - (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) = T2 at eL hxw - generalize hT3 : (m + 1) * 2 ^ (160 - c) * - (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 142)) = T3 at hxw hfold - generalize hT4 : m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ (160 - c) * - (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarsePosBudgetCap) * - (10 ^ 31 - 10) * 10 ^ 18) * Sc = T4 at hfold eR - generalize hT5 : (((m * 9999999999999999999999999996615) * - ((2 * (10 ^ 40 - 1)) ^ (160 - c))) * - (Sc * (10 ^ 31 - 3384)) * (10 ^ 31 + lnErrorCoarsePosBudgetCap)) * - (10 ^ 18 * (10 ^ 31 - 10)) = T5 at eR ⊢ + +theorem errBudgetL_ge_fold {m k : Nat} (hm : Sc ≤ m) (hk : k ≤ 159) : + (m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) ≤ + m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * + (10 ^ 31 + lnErrorCoarseGePosBudgetCap) * (10 ^ 31 - 10) * 10 ^ 18) := by + have hb := errBudgetLGe_le (k := k) hk + have hcross : (m + 1) * Sc ≤ m * (Sc + 1) := by + have e1 : (m + 1) * Sc = m * Sc + Sc := by + rw [Nat.add_mul, Nat.one_mul] + have e2 : m * (Sc + 1) = m * Sc + m := by + rw [Nat.mul_add, Nat.mul_one] omega + refine Nat.le_of_mul_le_mul_left ?_ (show 0 < Sc by decide) + calc Sc * ((m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) + = ((m + 1) * Sc) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by + simp only [Nat.mul_assoc, Nat.mul_left_comm] + _ ≤ (m * (Sc + 1)) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := + Nat.mul_le_mul_right _ hcross + _ = m * ((Sc + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142)) := by + simp only [Nat.mul_assoc] + _ = m * ((Sc + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) := by + simp only [Nat.mul_assoc] + _ ≤ m * (Sc * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * + (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarseGePosBudgetCap) * + (10 ^ 31 - 10) * 10 ^ 18)) := + Nat.mul_le_mul_left _ (by + simpa only [Nat.mul_assoc] using hb) + _ = Sc * (m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * + (10 ^ 31 - 3384) * (10 ^ 31 + lnErrorCoarseGePosBudgetCap) * + (10 ^ 31 - 10) * 10 ^ 18)) := by + simp only [Nat.mul_comm, Nat.mul_left_comm] + theorem lo_ge_pos_exact_ge_residue {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc1 : 1 ≤ c) (hc : c < 160) @@ -382,7 +357,7 @@ theorem lo_ge_pos_exact_ge_residue {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : theorem lo_lt_pos_exact {m c x : Nat} {r : Int} (h1 : Sc - 45 ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c < 160) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516294209054209107914) + ln2kInt c + 116873961749927929127912020551560854268589826112230) (hr0 : 0 ≤ r) (hres : PosShiftResidueOk m c r) (hxm : x < (m + 1) * 2 ^ (160 - c)) : @@ -398,12 +373,12 @@ theorem lo_lt_pos_exact {m c x : Nat} {r : Int} (h1 : Sc - 45 ≤ m) (h2 : m < S have hX1 := x1_nonpos_ltF hmlo h2 have hVs := v_scale_pos (int256 (x1W (zWord m))) c (by omega : c ≤ 160) have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 := by have h0 : 0 ≤ r * 2 ^ 72 := Int.mul_nonneg hr0 (by decide) have hg : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ + 116873961749927929127912020551560854268589826112230 = V at hrlo ⊢ generalize hgR : r * 2 ^ 72 = R at hrlo h0 omega exact Int.mul_nonneg hg (by decide) diff --git a/formal/ln/LnProof/LnProof/Error/Core/Budget.lean b/formal/ln/LnProof/LnProof/Error/Core/Budget.lean index 4df1bdd7a..1d359f190 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/Budget.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/Budget.lean @@ -5,7 +5,7 @@ import LnProof.Error.Core.CutDefs /-! # Error bound — Budget -Per-branch budget definitions (`posPhaseNatGe/Lt`, `posAvail*`, `PosShift*BudgetOk`, phase-direct predicates). +The natural-number phase split and the minimum available closing margin. -/ open FormalYul @@ -20,33 +20,6 @@ open LnYul LnFloor Common.Exp Common.Poly attribute [local irreducible] lnWadToRayBody -def posPhaseNatGe (m c : Nat) : Nat := - (int256 (x1W (zWord m))).toNat * lnPhaseScaleN * lnErrorBoundDen + - (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) + - BIASc * twoPow27N * lnErrorBoundDen - -def posAvailGe (m c : Nat) (r : Int) : Nat := - lnErrArg r - posPhaseNatGe m c - -def posBaseYGe (m c : Nat) : Nat := - ((m * 9999999999999999999999999996615) * - ((2 * (10 ^ 40 - 1)) ^ (160 - c))) * - (Sc * (10 ^ 31 - 3384)) - -def posBaseWGe (c : Nat) : Nat := - (560227709747861399187319382270000000000000000000000000000000 * - ((10 ^ 40 : Nat) ^ (160 - c))) * - (10 ^ 18 * 10 ^ 31) - -def PosShiftGeBudgetOk (m c x : Nat) (r : Int) : Prop := - posPhaseNatGe m c ≤ lnErrArg r ∧ - wadRayNum x * (posBaseWGe c * lnErrQ) ≤ - (posBaseYGe m c * (lnErrQ + posAvailGe m c r)) * wadRayStrictDen - -def PosShiftGeBudgetIneqOk (m c x : Nat) (r : Int) : Prop := - wadRayNum x * (posBaseWGe c * lnErrQ) ≤ - (posBaseYGe m c * (lnErrQ + posAvailGe m c r)) * wadRayStrictDen - def posConstNat (c : Nat) : Nat := (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) + BIASc * twoPow27N * lnErrorBoundDen @@ -60,54 +33,8 @@ def posPhaseNatLt (m c : Nat) : Nat := def posAvailLt (m c : Nat) (r : Int) : Nat := lnErrArg r - posPhaseNatLt m c -def posBaseYLt (m c : Nat) : Nat := - ((2 * (10 ^ 40 - 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3384))) * - (m * 9999999999999999999999999996615) - -def posBaseWLt (c : Nat) : Nat := - (((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31)) * - 560227709747861399187319382270000000000000000000000000000000) - -def PosShiftLtBudgetOk (m c x : Nat) (r : Int) : Prop := - posNegXNat m ≤ posConstNat c ∧ - posPhaseNatLt m c ≤ lnErrArg r ∧ - wadRayNum x * (posBaseWLt c * lnErrQ) ≤ - (posBaseYLt m c * (lnErrQ + posAvailLt m c r)) * wadRayStrictDen - -def PosShiftLtBudgetIneqOk (m c x : Nat) (r : Int) : Prop := - wadRayNum x * (posBaseWLt c * lnErrQ) ≤ - (posBaseYLt m c * (lnErrQ + posAvailLt m c r)) * wadRayStrictDen - -def PosShiftGeTopBudgetIneqOk (m c : Nat) : Prop := - PosShiftGeBudgetIneqOk m c (posTopX c m) (int256 (lnTail (evmSub 160 c) m)) - -def PosShiftLtTopBudgetIneqOk (m c : Nat) : Prop := - PosShiftLtBudgetIneqOk m c (posTopX c m) (int256 (lnTail (evmSub 160 c) m)) - def lnPhaseExtraArg : Nat := lnErrorExtraNum * twoPow99N -def PosShiftGePhaseDirectOk (n m c : Nat) : Prop := - sumGE n (posPhaseNatGe m c + lnPhaseExtraArg) lnErrQ (posTopX c m) (10 ^ 18) - -def PosShiftLtPhaseDirectOk (n m c : Nat) : Prop := - sumGE n (posPhaseNatLt m c + lnPhaseExtraArg) lnErrQ (posTopX c m) (10 ^ 18) - def minPosAvail : Nat := lnPhaseExtraArg + twoPow27N * lnErrorBoundDen -def PosShiftGeMinPhaseDirectOk (n m c : Nat) : Prop := - sumGE n (posPhaseNatGe m c + minPosAvail) lnErrQ (posTopX c m) (10 ^ 18) - -def PosShiftLtMinPhaseDirectOk (n m c : Nat) : Prop := - sumGE n (posPhaseNatLt m c + minPosAvail) lnErrQ (posTopX c m) (10 ^ 18) - -def lnDirectGapArg : Nat := lnErrorDirectResidueGap * twoPow27N * lnErrorBoundDen - -def PosShiftGePhaseGapDirectOk (n m c : Nat) : Prop := - sumGE n (posPhaseNatGe m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ - (posTopX c m) (10 ^ 18) - -def PosShiftLtPhaseGapDirectOk (n m c : Nat) : Prop := - sumGE n (posPhaseNatLt m c + lnPhaseExtraArg + lnDirectGapArg) lnErrQ - (posTopX c m) (10 ^ 18) - end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/C160.lean b/formal/ln/LnProof/LnProof/Error/Core/C160.lean index 2716df6e6..385a15ff0 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/C160.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/C160.lean @@ -6,7 +6,7 @@ import LnProof.Error.Core.Args /-! # Error bound — C160 -Negative-argument lemmas, the `c160` constant block, and the `lo_*_c160_exact` brackets. +Negative-argument lemmas and the `lo_*_c160_exact` brackets. -/ open FormalYul @@ -20,7 +20,6 @@ open LnYul LnFloor Common.Exp Common.Poly attribute [local irreducible] lnWadToRayBody - theorem ln_err_arg_nonneg {r : Int} (hr0 : -1 ≤ r) : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by have h0 : 0 ≤ r + 1 := by omega @@ -74,21 +73,9 @@ theorem v_c160_nonneg {m : Nat} (h1 : MLO ≤ m) (h2 : m < MHI) : rw [hln2] omega -def ten31 : Nat := 10 ^ 31 - -def c160W0 : Nat := Sc * ten31 -def c160W : Nat := Sc * (10 : Nat) ^ 111 - -def c160R0 : Nat := ten31 - 3385 -def c160R1 : Nat := ten31 - 3384 -def c160R2 : Nat := ten31 + lnErrorExtraCap -def c160R3 : Nat := ten31 - 10 -def c160R4 : Nat := 10 ^ 18 -def c160R : Nat := Sc * (c160R0 * c160R1 * c160R2 * c160R3 * c160R4) - theorem lo_ge_c160_exact {m x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hr0 : -1 ≤ r) (hmx : m ≤ x) (hxm : x < m + 1) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by have hx : x = m := by omega @@ -169,7 +156,7 @@ theorem lo_ge_c160_exact {m x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem lo_lt_c160_exact {m x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hmx : m ≤ x) (hxm : x < m + 1) : capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by have hx : x = m := by omega @@ -179,7 +166,7 @@ theorem lo_lt_c160_exact {m x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) omega have hV0I := v_c160_nonneg h1 hmhi have hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt 160 + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by simpa [lnBiasI] using hV0I have hr0 : -1 ≤ r := by rcases Int.lt_or_le r (-1) with hlt | hle diff --git a/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean b/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean index a39d14c0c..9122aa143 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/CutDefs.lean @@ -4,7 +4,7 @@ import LnProof.Error.Cert /-! # Error bound — CutDefs -Cut predicates `CutLogWadRayLtRational(Strict)`, the scale constants, and the strict↔exact / `sumGE`-monotonicity plumbing. +Cut predicates, scale constants, and the strict-to-exact bridge. -/ open FormalYul @@ -64,15 +64,13 @@ def wadRayNum (x : Nat) : Nat := x * 10 ^ 31 def wadRayStrictDen : Nat := 10 ^ 18 * (10 ^ 31 - 10) def posTopX (c m : Nat) : Nat := (m + 1) * 2 ^ (160 - c) - 1 def twoPow27N : Nat := 2 ^ 27 -def twoPow72N : Nat := 2 ^ 72 def twoPow99N : Nat := 2 ^ 99 def twoPow27I : Int := 2 ^ 27 def twoPow72I : Int := 2 ^ 72 def twoPow99I : Int := 2 ^ 99 def lnPhaseScaleN : Nat := 1000000000000000000000000000 def lnPhaseScaleI : Int := 1000000000000000000000000000 -def lnBiasI : Int := 116873961749927929127912020551516294209054209107914 -def lnErrorHardMantissa : Nat := 39770979022059719714796403827 +def lnBiasI : Int := 116873961749927929127912020551560854268589826112230 /-- First-order exact-wad budget with the common `10^18` and `2^99` factors cancelled out. -/ @@ -122,57 +120,4 @@ theorem CutLogWadRayLtRational_of_strict {x : Nat} {r : Int} {num den : Nat} · rw [if_neg hpos] at h ⊢ exact capUB_strict_to_exact hx h -theorem capLB_exact_of_sumGE_mono {n p0 p y0 y : Nat} - (hp : p0 ≤ p) (hy : y ≤ y0) - (h : sumGE n p0 lnErrQ y0 (10 ^ 18)) : - capLB p lnErrQ y (10 ^ 18) := by - have hq : 0 < lnErrQ := by - unfold lnErrQ QS lnErrorBoundDen - decide - have cap0 : capLB p0 lnErrQ y0 (10 ^ 18) := ⟨n, h⟩ - have capP : capLB p lnErrQ y0 (10 ^ 18) := by - refine capLB_arg (p := p) (q := lnErrQ) (p' := p0) (q' := lnErrQ) - hq ?_ cap0 - exact Nat.mul_le_mul_right _ hp - refine capLB_weaken (p := p) (q := lnErrQ) (y := y0) (w := 10 ^ 18) - (y' := y) (w' := 10 ^ 18) (by decide) capP ?_ - exact Nat.mul_le_mul_right _ hy - -theorem sumGE_exact_mono {n p0 p y0 y : Nat} - (hp : p0 ≤ p) (hy : y ≤ y0) - (h : sumGE n p0 lnErrQ y0 (10 ^ 18)) : - sumGE n p lnErrQ y (10 ^ 18) := by - unfold sumGE at h ⊢ - have hleft : y * (fact n * lnErrQ ^ n) ≤ y0 * (fact n * lnErrQ ^ n) := - Nat.mul_le_mul_right _ hy - have harg : expNum n p0 lnErrQ * lnErrQ ^ n ≤ expNum n p lnErrQ * lnErrQ ^ n := by - simpa using expNum_arg_mono - (p := p0) (q := lnErrQ) (p' := p) (q' := lnErrQ) - (Nat.mul_le_mul_right lnErrQ hp) n - have hqpow : 0 < lnErrQ ^ n := Nat.pow_pos (by unfold lnErrQ QS lnErrorBoundDen; decide) - have hexp : expNum n p0 lnErrQ ≤ expNum n p lnErrQ := - Nat.le_of_mul_le_mul_right harg hqpow - exact Nat.le_trans hleft (Nat.le_trans h (Nat.mul_le_mul_right _ hexp)) - -theorem sumGE_arg_mono {n p q p' q' y w : Nat} - (hq' : 0 < q') (harg : p' * q ≤ p * q') - (h : sumGE n p' q' y w) : - sumGE n p q y w := by - unfold sumGE at h ⊢ - have hmono := expNum_arg_mono harg n - have hqpow : 0 < q' ^ n := Nat.pow_pos hq' - refine Nat.le_of_mul_le_mul_right ?_ hqpow - calc - (y * (fact n * q ^ n)) * q' ^ n = - (y * (fact n * q' ^ n)) * q ^ n := by - simp only [Nat.mul_comm, Nat.mul_left_comm] - _ ≤ (expNum n p' q' * w) * q ^ n := - Nat.mul_le_mul_right _ h - _ = (expNum n p' q' * q ^ n) * w := by - simp only [Nat.mul_comm, Nat.mul_left_comm] - _ ≤ (expNum n p q * q' ^ n) * w := - Nat.mul_le_mul_right _ hmono - _ = (expNum n p q * w) * q' ^ n := by - simp only [Nat.mul_comm, Nat.mul_left_comm] - end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/Direct.lean b/formal/ln/LnProof/LnProof/Error/Core/Direct.lean deleted file mode 100644 index 75f5538b5..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/Direct.lean +++ /dev/null @@ -1,264 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.ExpMargin -import LnProof.Error.Core.ResidueCover -import LnProof.Error.Core.Budget - -/-! -# Error bound — Direct - -Direct-cover machinery: `expSum*`, `sumGEB`, and `PosShiftDirectCell` covers. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def PosShiftTopDirectOk (n m c : Nat) : Prop := - sumGE n (lnErrArg (int256 (lnTail (evmSub 160 c) m))) lnErrQ - (posTopX c m) (10 ^ 18) - -def expSumState (p q : Nat) : Nat → Nat × Nat × Nat - | 0 => (1, 1, 1) - | n + 1 => - let s := expSumState p q n - let pp := s.2.2 * p - ((n + 1) * q * s.1 + pp, (n + 1) * q * s.2.1, pp) - -theorem expSumState_spec (p q : Nat) : - ∀ n, expSumState p q n = (expNum n p q, fact n * q ^ n, p ^ n) - | 0 => by - simp [expSumState, expNum, fact] - | n + 1 => by - simp [expSumState, expSumState_spec p q n, expNum, fact, Nat.pow_succ, - Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - -def expSumStateGo (p q : Nat) : Nat → Nat → Nat → Nat → Nat → Nat × Nat × Nat - | 0, _i, e, d, pp => (e, d, pp) - | k + 1, i, e, d, pp => - let pp' := pp * p - expSumStateGo p q k (i + 1) ((i + 1) * q * e + pp') ((i + 1) * q * d) pp' - -theorem expSumStateGo_spec (p q : Nat) : - ∀ k i e d pp, - expSumState p q i = (e, d, pp) → - expSumStateGo p q k i e d pp = expSumState p q (i + k) - | 0, i, e, d, pp, h => by - simp [expSumStateGo, h] - | k + 1, i, e, d, pp, h => by - simp only [expSumStateGo] - let pp' := pp * p - have hnext : expSumState p q (i + 1) = - ((i + 1) * q * e + pp', (i + 1) * q * d, pp') := by - rw [show i + 1 = Nat.succ i by omega] - simp [expSumState, h, pp'] - have ih := expSumStateGo_spec p q k (i + 1) - ((i + 1) * q * e + pp') ((i + 1) * q * d) pp' hnext - simpa [Nat.add_assoc, Nat.add_comm, Nat.add_left_comm] using ih - -def expSumStateFast (p q n : Nat) : Nat × Nat × Nat := - expSumStateGo p q n 0 1 1 1 - -theorem expSumStateFast_eq (p q n : Nat) : - expSumStateFast p q n = expSumState p q n := by - unfold expSumStateFast - have h := expSumStateGo_spec p q n 0 1 1 1 (by simp [expSumState]) - simpa using h - -def sumGEB (n p q y w : Nat) : Bool := - let s := expSumState p q n - decide (y * s.2.1 ≤ s.1 * w) - -theorem sumGE_of_sumGEB {n p q y w : Nat} (h : sumGEB n p q y w = true) : - sumGE n p q y w := by - unfold sumGEB at h - simpa [sumGE, expSumState_spec p q n] using (of_decide_eq_true h) - -structure PosShiftDirectCell where - c : Nat - lo : Nat - hi : Nat - n : Nat - -def PosShiftDirectCell.Ok (cell : PosShiftDirectCell) : Prop := - MLO ≤ cell.lo ∧ cell.lo ≤ cell.hi ∧ cell.hi < MHI ∧ cell.c < 160 ∧ - sumGE cell.n (lnErrArg (int256 (lnTail (evmSub 160 cell.c) cell.lo))) lnErrQ - (posTopX cell.c cell.hi) (10 ^ 18) - -def PosShiftDirectCell.okB (cell : PosShiftDirectCell) : Bool := - decide (MLO ≤ cell.lo) && - decide (cell.lo ≤ cell.hi) && - decide (cell.hi < MHI) && - decide (cell.c < 160) && - decide (sumGE cell.n - (lnErrArg (int256 (lnTail (evmSub 160 cell.c) cell.lo))) lnErrQ - (posTopX cell.c cell.hi) (10 ^ 18)) - -def PosShiftDirectCell.Covers (cell : PosShiftDirectCell) (m c : Nat) : Prop := - c = cell.c ∧ cell.lo ≤ m ∧ m ≤ cell.hi - -def PosShiftDirectCell.coversB (cell : PosShiftDirectCell) (m c : Nat) : Bool := - decide (c = cell.c) && decide (cell.lo ≤ m) && decide (m ≤ cell.hi) - -theorem PosShiftDirectCell.ok_of_okB {cell : PosShiftDirectCell} - (h : cell.okB = true) : cell.Ok := by - unfold PosShiftDirectCell.okB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, hlohi⟩, hhi⟩, hc⟩, hsum⟩ := h - exact ⟨hlo, hlohi, hhi, hc, hsum⟩ - -theorem PosShiftDirectCell.covers_of_coversB {cell : PosShiftDirectCell} {m c : Nat} - (h : cell.coversB m c = true) : cell.Covers m c := by - unfold PosShiftDirectCell.coversB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨hc, hlo⟩, hhi⟩ := h - exact ⟨hc, hlo, hhi⟩ - -def directCellsCoverB (cells : List PosShiftDirectCell) (m c : Nat) : Bool := - cells.any (fun cell => cell.okB && cell.coversB m c) - -def directCellsCover320B (cells : List PosShiftDirectCell) (m c : Nat) : Bool := - cells.any (fun cell => decide (cell.n = 320) && cell.okB && cell.coversB m c) - -def localDirectCell (m c : Nat) : PosShiftDirectCell := - { c := c, lo := max MLO (m - 16), hi := m, n := 320 } - -def localDirectCertB (m c : Nat) : Bool := - (localDirectCell m c).okB - -def residueOrDirectCertB (cells : List PosShiftDirectCell) (m c : Nat) (r : Int) : Bool := - residueGapOkB m c r || directCellsCover320B cells m c - -def residueOrLocalDirectCertB (m c : Nat) (r : Int) : Bool := - residueGapOkB m c r || localDirectCertB m c - -def posShiftDirectCells : List PosShiftDirectCell := [] - -theorem posTopX_mono_m {c m hi : Nat} (hm : m ≤ hi) : - posTopX c m ≤ posTopX c hi := by - unfold posTopX - have hmul : (m + 1) * 2 ^ (160 - c) ≤ (hi + 1) * 2 ^ (160 - c) := - Nat.mul_le_mul_right _ (by omega) - have hpos : 0 < (m + 1) * 2 ^ (160 - c) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - omega - -theorem lnTail_mono_m {c lo m hi : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m ≤ hi) (hhi : hi < MHI) - (hc : c < 256) : - int256 (lnTail (evmSub 160 c) lo) ≤ int256 (lnTail (evmSub 160 c) m) := by - have hmhi' : m < MHI := by omega - have hw := ln2k_bound (c := c) hc - exact tail_mono hlo hlom hmhi' hw.1 hw.2 - -theorem PosShiftDirectCell.sound {cell : PosShiftDirectCell} {m c : Nat} - (hok : cell.Ok) (hcov : cell.Covers m c) : - PosShiftTopDirectOk cell.n m c := by - obtain ⟨hlo, hlohi, hhi, _hc, hsum⟩ := hok - obtain ⟨hc_eq, hmlo, hmhi⟩ := hcov - subst c - unfold PosShiftTopDirectOk - refine sumGE_exact_mono (n := cell.n) - (p0 := lnErrArg (int256 (lnTail (evmSub 160 cell.c) cell.lo))) - (p := lnErrArg (int256 (lnTail (evmSub 160 cell.c) m))) - (y0 := posTopX cell.c cell.hi) (y := posTopX cell.c m) ?_ ?_ hsum - · exact lnErrArg_mono (lnTail_mono_m hlo hmlo hmhi hhi (by omega)) - · exact posTopX_mono_m hmhi - -theorem direct_of_cells_cover {cells : List PosShiftDirectCell} {m c : Nat} - (h : directCellsCoverB cells m c = true) : - ∃ n, PosShiftTopDirectOk n m c := by - unfold directCellsCoverB at h - rw [List.any_eq_true] at h - obtain ⟨cell, _hmem, hokcov⟩ := h - simp only [Bool.and_eq_true] at hokcov - obtain ⟨hok, hcov⟩ := hokcov - exact ⟨cell.n, PosShiftDirectCell.sound - (PosShiftDirectCell.ok_of_okB hok) - (PosShiftDirectCell.covers_of_coversB hcov)⟩ - -theorem direct320_of_cells_cover {cells : List PosShiftDirectCell} {m c : Nat} - (h : directCellsCover320B cells m c = true) : - PosShiftTopDirectOk 320 m c := by - unfold directCellsCover320B at h - rw [List.any_eq_true] at h - obtain ⟨cell, _hmem, hcert⟩ := h - simp only [Bool.and_eq_true, decide_eq_true_eq] at hcert - obtain ⟨⟨hn, hok⟩, hcov⟩ := hcert - have hs := PosShiftDirectCell.sound - (PosShiftDirectCell.ok_of_okB hok) - (PosShiftDirectCell.covers_of_coversB hcov) - simpa [hn] using hs - -theorem residue_or_direct_of_certB {cells : List PosShiftDirectCell} {m c : Nat} {r : Int} - (hc : c ≤ 160) (h : residueOrDirectCertB cells m c r = true) : - PosShiftResidueOk m c r ∨ PosShiftTopDirectOk 320 m c := by - unfold residueOrDirectCertB at h - simp only [Bool.or_eq_true] at h - rcases h with hres | hdir - · exact Or.inl (PosShiftResidueOk_of_gapB hc hres) - · exact Or.inr (direct320_of_cells_cover hdir) - -theorem residue_or_direct_of_local_certB {m c : Nat} {r : Int} - (hc : c ≤ 160) (h : residueOrLocalDirectCertB m c r = true) : - PosShiftResidueOk m c r ∨ PosShiftTopDirectOk 320 m c := by - unfold residueOrLocalDirectCertB localDirectCertB at h - simp only [Bool.or_eq_true] at h - rcases h with hres | hdir - · exact Or.inl (PosShiftResidueOk_of_gapB hc hres) - · have hokCell := PosShiftDirectCell.ok_of_okB hdir - have hlohi := hokCell.2.1 - have hcell : (localDirectCell m c).Covers m c := by - simpa [localDirectCell, PosShiftDirectCell.Covers] using - (⟨rfl, hlohi, Nat.le_refl m⟩ : - c = c ∧ (localDirectCell m c).lo ≤ m ∧ m ≤ (localDirectCell m c).hi) - have hs := PosShiftDirectCell.sound hokCell hcell - have hs320 : PosShiftTopDirectOk 320 m c := by - simpa [localDirectCell] using hs - exact Or.inr hs320 - -theorem posPhaseNatGe_mono_m {lo m c : Nat} - (hlo : Sc ≤ lo) (hlom : lo ≤ m) (hmhi : m < MHI) : - posPhaseNatGe lo c ≤ posPhaseNatGe m c := by - unfold posPhaseNatGe - have hmlo : MLO ≤ lo := by - simp only [Sc, MLO] at hlo ⊢ - omega - have hx := LnYul.r1_mono hmlo hlom hmhi - have hxNat : (int256 (x1W (zWord lo))).toNat ≤ - (int256 (x1W (zWord m))).toNat := - Int.toNat_le_toNat hx - have hmul : (int256 (x1W (zWord lo))).toNat * lnPhaseScaleN * lnErrorBoundDen ≤ - (int256 (x1W (zWord m))).toNat * lnPhaseScaleN * lnErrorBoundDen := by - exact Nat.mul_le_mul_right _ (Nat.mul_le_mul_right _ hxNat) - omega - -theorem posNegXNat_antitone_m {lo m : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m < MHI) : - posNegXNat m ≤ posNegXNat lo := by - unfold posNegXNat - have hx := LnYul.r1_mono hlo hlom hmhi - have hneg : -int256 (x1W (zWord m)) ≤ -int256 (x1W (zWord lo)) := by - omega - have hn : (-int256 (x1W (zWord m))).toNat ≤ - (-int256 (x1W (zWord lo))).toNat := - Int.toNat_le_toNat hneg - exact Nat.mul_le_mul_right _ (Nat.mul_le_mul_right _ hn) - -theorem posPhaseNatLt_mono_m {lo m c : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m < MHI) : - posPhaseNatLt lo c ≤ posPhaseNatLt m c := by - unfold posPhaseNatLt - have hn := posNegXNat_antitone_m (lo := lo) (m := m) hlo hlom hmhi - exact Nat.sub_le_sub_left hn (posConstNat c) - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/ExpMargin.lean b/formal/ln/LnProof/LnProof/Error/Core/ExpMargin.lean deleted file mode 100644 index d2510e210..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/ExpMargin.lean +++ /dev/null @@ -1,516 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs - -/-! -# Error bound — ExpMargin - -The `sumGE`→certificate toolkit: exp-margin polynomials (poly / L1 / value forms), nonnegative-interval evaluation, and the `sumGE_of_expMargin*` bridges. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def expMarginPoly (n : Nat) (pn qd y : List Int) (w : Nat) : List Int := - polySub (polyScale (w : Int) (expPolyNum pn qd n)) - (polyScale (fact n : Int) (polyMul y (polyPow qd n))) - -def expMarginFastState (pn qd y : List Int) (w : Nat) : Nat → List Int × List Int - | 0 => (polySub [((w : Nat) : Int)] y, [1]) - | n + 1 => - let st := expMarginFastState pn qd y w n - let pp := polyMul pn st.2 - (polyAdd (polyScale (((n + 1 : Nat) : Int)) (polyMul qd st.1)) - (polyScale (((w : Nat) : Int)) pp), pp) - -def expMarginPolyFast (n : Nat) (pn qd y : List Int) (w : Nat) : List Int := - (expMarginFastState pn qd y w n).1 - -theorem evalPoly_expMarginFastState_pow (pn qd y : List Int) (w n : Nat) (x : Int) : - evalPoly (expMarginFastState pn qd y w n).2 x = evalPoly pn x ^ n := by - induction n with - | zero => - simp [expMarginFastState, evalPoly] - | succ n ih => - simp [expMarginFastState, evalPoly_polyMul, ih, Int.pow_succ] - rw [Int.mul_comm] - -theorem evalPoly_expMarginPolyFast (pn qd y : List Int) (w n : Nat) (x : Int) : - evalPoly (expMarginPolyFast n pn qd y w) x = - (w : Int) * expNumI n (evalPoly pn x) (evalPoly qd x) - - (fact n : Int) * evalPoly y x * evalPoly qd x ^ n := by - induction n with - | zero => - simp [expMarginPolyFast, expMarginFastState, evalPoly_polySub, - expNumI, fact, evalPoly] - | succ n ih => - unfold expMarginPolyFast - simp only [expMarginFastState, evalPoly_polyAdd, evalPoly_polyScale, - evalPoly_polyMul, evalPoly_expMarginFastState_pow, expNumI, fact] - rw [show evalPoly (expMarginFastState pn qd y w n).fst x = - evalPoly (expMarginPolyFast n pn qd y w) x by rfl] - rw [ih] - simp only [Int.pow_succ] - simp only [Int.natCast_add, Int.natCast_one, Int.natCast_mul] - generalize ((n : Int) + 1) = N - generalize (w : Int) = W - generalize expNumI n (evalPoly pn x) (evalPoly qd x) = E - generalize evalPoly pn x = P - generalize evalPoly pn x ^ n = Pn - generalize (fact n : Int) = F - generalize evalPoly y x = Y - generalize evalPoly qd x = Q - simp only [Int.mul_add, Int.mul_sub] - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - omega - -theorem sumGE_of_expMarginPoly {n m p q y w : Nat} {pn qd yp : List Int} - (hcert : 0 ≤ evalPoly (expMarginPoly n pn qd yp w) (m : Int)) - (hpn : evalPoly pn (m : Int) = (p : Int)) - (hqd : evalPoly qd (m : Int) = (q : Int)) - (hy : evalPoly yp (m : Int) = (y : Int)) : - sumGE n p q y w := by - unfold expMarginPoly at hcert - rw [evalPoly_polySub, evalPoly_polyScale, evalPoly_expPolyNum, - evalPoly_polyScale, evalPoly_polyMul, evalPoly_polyPow, hpn, hqd, hy] at hcert - rw [expNumI_eq_expNum] at hcert - unfold sumGE - refine Int.ofNat_le.mp ?_ - simp only [Int.natCast_mul, Int.natCast_pow] - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] at hcert ⊢ - omega - -theorem sumGE_of_expMarginPolyFast {n m p q y w : Nat} {pn qd yp : List Int} - (hcert : 0 ≤ evalPoly (expMarginPolyFast n pn qd yp w) (m : Int)) - (hpn : evalPoly pn (m : Int) = (p : Int)) - (hqd : evalPoly qd (m : Int) = (q : Int)) - (hy : evalPoly yp (m : Int) = (y : Int)) : - sumGE n p q y w := by - rw [evalPoly_expMarginPolyFast, hpn, hqd, hy] at hcert - rw [expNumI_eq_expNum] at hcert - unfold sumGE - refine Int.ofNat_le.mp ?_ - simp only [Int.natCast_mul, Int.natCast_pow] - simp only [Int.mul_comm, Int.mul_left_comm] at hcert ⊢ - omega - -def expMarginL1BoundState (pb qb yb w : Nat) : Nat → Nat × Nat - | 0 => (w + yb, 1) - | n + 1 => - let st := expMarginL1BoundState pb qb yb w n - let pp := pb * st.2 - ((n + 1) * qb * st.1 + w * pp, pp) - -def expMarginL1Bound (n pb qb yb w : Nat) : Nat := - (expMarginL1BoundState pb qb yb w n).1 - -theorem polyL1_singleton_nat (w : Nat) : - polyL1 [((w : Nat) : Int)] = w := by - simp [polyL1] - -theorem polyL1_expMarginFastState (pn qd y : List Int) (w n : Nat) : - polyL1 (expMarginFastState pn qd y w n).1 ≤ - (expMarginL1BoundState (polyL1 pn) (polyL1 qd) (polyL1 y) w n).1 ∧ - polyL1 (expMarginFastState pn qd y w n).2 ≤ - (expMarginL1BoundState (polyL1 pn) (polyL1 qd) (polyL1 y) w n).2 := by - induction n with - | zero => - unfold expMarginFastState expMarginL1BoundState - constructor - · unfold polySub - have hadd := polyL1_polyAdd [((w : Nat) : Int)] (polyNeg y) - rw [polyL1_singleton_nat, polyL1_polyNeg] at hadd - exact hadd - · simp [polyL1] - | succ n ih => - unfold expMarginFastState expMarginL1BoundState - let st := expMarginFastState pn qd y w n - let bt := expMarginL1BoundState (polyL1 pn) (polyL1 qd) (polyL1 y) w n - have hpw : polyL1 (polyMul pn st.2) ≤ polyL1 pn * bt.2 := by - have hmul := polyL1_polyMul pn st.2 - exact Nat.le_trans hmul (Nat.mul_le_mul_left _ ih.2) - constructor - · have hsum := polyL1_polyAdd - (polyScale (((n + 1 : Nat) : Int)) (polyMul qd st.1)) - (polyScale (((w : Nat) : Int)) (polyMul pn st.2)) - have hscale1 := polyL1_polyScale (((n + 1 : Nat) : Int)) (polyMul qd st.1) - have hmul1 := polyL1_polyMul qd st.1 - have hscale2 := polyL1_polyScale (((w : Nat) : Int)) (polyMul pn st.2) - have h1 : polyL1 (polyScale (((n + 1 : Nat) : Int)) (polyMul qd st.1)) ≤ - (n + 1) * polyL1 qd * bt.1 := by - have hm : polyL1 (polyMul qd st.1) ≤ polyL1 qd * bt.1 := - Nat.le_trans hmul1 (Nat.mul_le_mul_left _ ih.1) - have hs := Nat.mul_le_mul_left (n + 1) hm - simpa [Int.natAbs_natCast, Nat.mul_assoc] using Nat.le_trans hscale1 hs - have h2 : polyL1 (polyScale (((w : Nat) : Int)) (polyMul pn st.2)) ≤ - w * (polyL1 pn * bt.2) := by - have hs := Nat.mul_le_mul_left w hpw - simpa [Int.natAbs_natCast] using Nat.le_trans hscale2 hs - exact Nat.le_trans hsum (Nat.add_le_add h1 h2) - · exact hpw - -theorem polyL1_expMarginPolyFast (pn qd y : List Int) (w n : Nat) : - polyL1 (expMarginPolyFast n pn qd y w) ≤ - expMarginL1Bound n (polyL1 pn) (polyL1 qd) (polyL1 y) w := by - exact (polyL1_expMarginFastState pn qd y w n).1 - -def expMarginValState (p q y w : Int) : Nat → Int × Int - | 0 => (w - y, 1) - | n + 1 => - let st := expMarginValState p q y w n - let pp := p * st.2 - (((n + 1 : Nat) : Int) * q * st.1 + w * pp, pp) - -def expMarginVal (n : Nat) (p q y w : Int) : Int := - (expMarginValState p q y w n).1 - -theorem expMarginValState_pow (p q y w : Int) (n : Nat) : - (expMarginValState p q y w n).2 = p ^ n := by - induction n with - | zero => - simp [expMarginValState] - | succ n ih => - simp [expMarginValState, ih, Int.pow_succ] - rw [Int.mul_comm] - -theorem expMarginVal_eq (p q y w : Int) (n : Nat) : - expMarginVal n p q y w = - w * expNumI n p q - (fact n : Int) * y * q ^ n := by - induction n with - | zero => - simp [expMarginVal, expMarginValState, expNumI, fact] - | succ n ih => - unfold expMarginVal - simp only [expMarginValState, expMarginValState_pow, expNumI, fact] - rw [show (expMarginValState p q y w n).fst = expMarginVal n p q y w by rfl] - rw [ih] - simp only [Int.pow_succ, Int.natCast_add, Int.natCast_one, Int.natCast_mul] - generalize ((n : Int) + 1) = N - generalize expNumI n p q = E - generalize p = P - generalize p ^ n = Pn - generalize (fact n : Int) = F - generalize q = Q - generalize y = Y - generalize w = W - simp only [Int.mul_add, Int.mul_sub] - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - omega - -theorem sumGE_of_expMarginVal {n p q y w : Nat} - (hcert : 0 ≤ expMarginVal n (p : Int) (q : Int) (y : Int) (w : Int)) : - sumGE n p q y w := by - rw [expMarginVal_eq, expNumI_eq_expNum] at hcert - unfold sumGE - refine Int.ofNat_le.mp ?_ - simp only [Int.natCast_mul, Int.natCast_pow] - simp only [Int.mul_comm, Int.mul_left_comm] at hcert ⊢ - omega - -def shiftedExpMarginCellOkB (B n : Nat) (pn qd y : List Int) - (lo hi outW : Nat) (S : List Int) : Bool := - decide (lo ≤ hi) && - let pS := polyShift pn (lo : Int) - let qS := polyShift qd (lo : Int) - let yS := polyShift y (lo : Int) - let K := ((2 ^ B : Nat) : Int) - decide (polyL1 S * 2 < 2 ^ B) && - decide (expMarginL1Bound n (polyL1 pS) (polyL1 qS) (polyL1 yS) outW * 2 < 2 ^ B) && - decide (evalPoly S K = - expMarginVal n (evalPoly pS K) (evalPoly qS K) (evalPoly yS K) (outW : Int)) && - decide (0 ≤ (hornerIv S 0 (((hi - lo : Nat) : Int))).1) - -theorem shiftedExpMarginCellOkB_sound {B n lo hi outW m : Nat} - {pn qd y S : List Int} - (h : shiftedExpMarginCellOkB B n pn qd y lo hi outW S = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - 0 ≤ expMarginVal n (evalPoly pn (m : Int)) (evalPoly qd (m : Int)) - (evalPoly y (m : Int)) (outW : Int) := by - unfold shiftedExpMarginCellOkB at h - let pS := polyShift pn (lo : Int) - let qS := polyShift qd (lo : Int) - let yS := polyShift y (lo : Int) - let K := ((2 ^ B : Nat) : Int) - rw [Bool.and_eq_true] at h - rcases h with ⟨hlohiB, h⟩ - rw [Bool.and_eq_true] at h - rcases h with ⟨h, hIvB⟩ - rw [Bool.and_eq_true] at h - rcases h with ⟨h, hEvalB⟩ - rw [Bool.and_eq_true] at h - rcases h with ⟨hSB, hBoundB⟩ - have hlohi : lo ≤ hi := of_decide_eq_true hlohiB - have hS : polyL1 S * 2 < 2 ^ B := of_decide_eq_true hSB - have hBound : - expMarginL1Bound n (polyL1 pS) (polyL1 qS) (polyL1 yS) outW * 2 < 2 ^ B := - of_decide_eq_true hBoundB - have hEval : evalPoly S K = - expMarginVal n (evalPoly pS K) (evalPoly qS K) (evalPoly yS K) (outW : Int) := - of_decide_eq_true hEvalB - have hIv : 0 ≤ (hornerIv S 0 (((hi - lo : Nat) : Int))).1 := - of_decide_eq_true hIvB - let d : Int := (m : Int) - (lo : Int) - have hd0 : 0 ≤ d := by - simp [d] - omega - have hdhi : d ≤ ((hi - lo : Nat) : Int) := by - simp [d] - omega - have hshiftBound : - polyL1 (expMarginPolyFast n pS qS yS outW) * 2 < 2 ^ B := by - have hle := polyL1_expMarginPolyFast pS qS yS outW n - omega - have hEvalPoly : - evalPoly S ((2 : Int) ^ B) = - evalPoly (expMarginPolyFast n pS qS yS outW) ((2 : Int) ^ B) := by - rw [int_two_pow, ← show K = ((2 ^ B : Nat) : Int) by rfl] - rw [evalPoly_expMarginPolyFast, ← expMarginVal_eq] - exact hEval - have hext := evalPoly_ext (B := B) S (expMarginPolyFast n pS qS yS outW) - hS hshiftBound hEvalPoly - have hhorner := (hornerIv_sound S (lo := 0) (hi := ((hi - lo : Nat) : Int)) - (x := d) (Int.le_refl 0) hd0 hdhi).1 - have hSnon : 0 ≤ evalPoly S d := by - omega - have hEq := hext d - rw [hEq] at hSnon - rw [evalPoly_expMarginPolyFast, ← expMarginVal_eq] at hSnon - have hm_decomp : (lo : Int) + d = (m : Int) := by - simp [d] - have hp := polyShift_eval pn (lo : Int) d - have hq := polyShift_eval qd (lo : Int) d - have hy := polyShift_eval y (lo : Int) d - rw [hm_decomp] at hp hq hy - simpa [pS, qS, yS, hp, hq, hy] using hSnon - -def ivAdd (a b : Int × Int) : Int × Int := - (a.1 + b.1, a.2 + b.2) - -def ivScaleNat (k : Nat) (a : Int × Int) : Int × Int := - (((k : Nat) : Int) * a.1, ((k : Nat) : Int) * a.2) - -def ivMulNonneg (a b : Int × Int) : Int × Int := - (a.1 * b.1, a.2 * b.2) - -def ivMulNonnegLeft (q a : Int × Int) : Int × Int := - ((if 0 ≤ a.1 then q.1 * a.1 else q.2 * a.1), - (if a.2 ≤ 0 then q.1 * a.2 else q.2 * a.2)) - -theorem ivAdd_sound {a b : Int × Int} {x y : Int} - (ha : a.1 ≤ x ∧ x ≤ a.2) (hb : b.1 ≤ y ∧ y ≤ b.2) : - (ivAdd a b).1 ≤ x + y ∧ x + y ≤ (ivAdd a b).2 := by - unfold ivAdd - omega - -theorem ivScaleNat_sound {k : Nat} {a : Int × Int} {x : Int} - (ha : a.1 ≤ x ∧ x ≤ a.2) : - (ivScaleNat k a).1 ≤ (k : Int) * x ∧ (k : Int) * x ≤ (ivScaleNat k a).2 := by - unfold ivScaleNat - have hk : 0 ≤ (k : Int) := Int.natCast_nonneg _ - constructor - · exact mul_le_mul_left_nonneg ha.1 hk - · exact mul_le_mul_left_nonneg ha.2 hk - -theorem ivMulNonneg_sound {a b : Int × Int} {x y : Int} - (ha0 : 0 ≤ a.1) (hb0 : 0 ≤ b.1) - (ha : a.1 ≤ x ∧ x ≤ a.2) (hb : b.1 ≤ y ∧ y ≤ b.2) : - (ivMulNonneg a b).1 ≤ x * y ∧ x * y ≤ (ivMulNonneg a b).2 := by - unfold ivMulNonneg - have hx0 : 0 ≤ x := by omega - have hy0 : 0 ≤ y := by omega - constructor - · calc - a.1 * b.1 ≤ x * b.1 := mul_le_mul_right_nonneg ha.1 hb0 - _ ≤ x * y := mul_le_mul_left_nonneg hb.1 hx0 - · calc - x * y ≤ a.2 * y := mul_le_mul_right_nonneg ha.2 hy0 - _ ≤ a.2 * b.2 := mul_le_mul_left_nonneg hb.2 (by omega : 0 ≤ a.2) - -theorem ivMulNonnegLeft_sound {q a : Int × Int} {x y : Int} - (hq0 : 0 ≤ q.1) (hq : q.1 ≤ x ∧ x ≤ q.2) (ha : a.1 ≤ y ∧ y ≤ a.2) : - (ivMulNonnegLeft q a).1 ≤ x * y ∧ x * y ≤ (ivMulNonnegLeft q a).2 := by - unfold ivMulNonnegLeft - have hx0 : 0 ≤ x := by omega - have hq20 : 0 ≤ q.2 := by omega - constructor - · by_cases ha10 : 0 ≤ a.1 - · rw [if_pos ha10] - have hy0 : 0 ≤ y := by omega - calc - q.1 * a.1 ≤ x * a.1 := mul_le_mul_right_nonneg hq.1 ha10 - _ ≤ x * y := mul_le_mul_left_nonneg ha.1 hx0 - · rw [if_neg ha10] - by_cases hypos : 0 ≤ y - · have hle0 : q.2 * a.1 ≤ 0 := Int.mul_nonpos_of_nonneg_of_nonpos hq20 (by omega) - have hxy0 : 0 ≤ x * y := Int.mul_nonneg hx0 hypos - omega - · have hy_nonpos : y ≤ 0 := by omega - calc - q.2 * a.1 ≤ q.2 * y := mul_le_mul_left_nonneg ha.1 hq20 - _ ≤ x * y := by - have h := mul_le_mul_left_nonpos hq.2 hy_nonpos - simpa only [Int.mul_comm] using h - · by_cases ha20 : a.2 ≤ 0 - · rw [if_pos ha20] - have hy_nonpos : y ≤ 0 := by omega - calc - x * y ≤ q.1 * y := by - have h := mul_le_mul_left_nonpos hq.1 hy_nonpos - simpa only [Int.mul_comm] using h - _ ≤ q.1 * a.2 := mul_le_mul_left_nonneg ha.2 hq0 - · rw [if_neg ha20] - by_cases hy_nonpos : y ≤ 0 - · have hxy0 : x * y ≤ 0 := Int.mul_nonpos_of_nonneg_of_nonpos hx0 hy_nonpos - have h0hi : 0 ≤ q.2 * a.2 := Int.mul_nonneg hq20 (by omega) - omega - · have hy0 : 0 ≤ y := by omega - calc - x * y ≤ q.2 * y := mul_le_mul_right_nonneg hq.2 hy0 - _ ≤ q.2 * a.2 := mul_le_mul_left_nonneg ha.2 hq20 - -def expMarginIvState (p q y : Int × Int) (w : Nat) : Nat → (Int × Int) × (Int × Int) - | 0 => (((w : Int) - y.2, (w : Int) - y.1), (1, 1)) - | n + 1 => - let st := expMarginIvState p q y w n - let pp := ivMulNonneg p st.2 - (ivAdd (ivScaleNat (n + 1) (ivMulNonnegLeft q st.1)) - (ivScaleNat w pp), pp) - -def expMarginIvLower (n : Nat) (p q y : Int × Int) (w : Nat) : Int := - (expMarginIvState p q y w n).1.1 - -theorem expMarginIvState_sound {p q y : Int × Int} {P Q Y : Int} {w n : Nat} - (hp0 : 0 ≤ p.1) (hq0 : 0 ≤ q.1) - (hp : p.1 ≤ P ∧ P ≤ p.2) - (hq : q.1 ≤ Q ∧ Q ≤ q.2) - (hy : y.1 ≤ Y ∧ Y ≤ y.2) : - 0 ≤ (expMarginIvState p q y w n).2.1 ∧ - ((expMarginIvState p q y w n).1.1 ≤ - expMarginVal n P Q Y (w : Int) ∧ - expMarginVal n P Q Y (w : Int) ≤ - (expMarginIvState p q y w n).1.2) ∧ - ((expMarginIvState p q y w n).2.1 ≤ P ^ n ∧ - P ^ n ≤ (expMarginIvState p q y w n).2.2) := by - induction n with - | zero => - simp [expMarginIvState, expMarginVal, expMarginValState] - omega - | succ n ih => - simp only [expMarginIvState] - let st := expMarginIvState p q y w n - have hst := ih - have hpp := ivMulNonneg_sound hp0 hst.1 hp hst.2.2 - have hpp0 : 0 ≤ (ivMulNonneg p st.2).1 := by - unfold ivMulNonneg - exact Int.mul_nonneg hp0 hst.1 - have hqm := ivMulNonnegLeft_sound hq0 hq hst.2.1 - have hterm1 := ivScaleNat_sound (k := n + 1) hqm - have hterm2 := ivScaleNat_sound (k := w) hpp - have hsum := ivAdd_sound hterm1 hterm2 - constructor - · exact hpp0 - constructor - · simpa [expMarginVal, expMarginValState, expMarginValState_pow, Int.mul_assoc] using hsum - · rw [Int.pow_succ] - simpa only [Int.mul_comm, Int.mul_left_comm] using hpp - -theorem expMarginIvLower_sound {n p q y w : Nat} {pIv qIv yIv : Int × Int} - (hp0 : 0 ≤ pIv.1) (hq0 : 0 ≤ qIv.1) - (hp : pIv.1 ≤ (p : Int) ∧ (p : Int) ≤ pIv.2) - (hq : qIv.1 ≤ (q : Int) ∧ (q : Int) ≤ qIv.2) - (hy : yIv.1 ≤ (y : Int) ∧ (y : Int) ≤ yIv.2) - (hlo : 0 ≤ expMarginIvLower n pIv qIv yIv w) : - sumGE n p q y w := by - have h := expMarginIvState_sound (p := pIv) (q := qIv) (y := yIv) - (P := (p : Int)) (Q := (q : Int)) (Y := (y : Int)) (w := w) (n := n) - hp0 hq0 hp hq hy - exact sumGE_of_expMarginVal (n := n) (p := p) (q := q) (y := y) (w := w) - (Int.le_trans hlo h.2.1.1) - - -theorem ge_phase_lower_algebra {tn td x k c e : Int} - (hk : 0 ≤ k) (hbr : tn * 2 ^ 99 ≤ x * td) : - (2 ^ 99 * k) * tn + (c + e) * td ≤ - (x * k + c + e) * td := by - have hs := mul_le_mul_right_nonneg hbr hk - have hs' : (2 ^ 99 * k) * tn ≤ (x * k) * td := by - calc - (2 ^ 99 * k) * tn = (tn * 2 ^ 99) * k := by - simp only [Int.mul_comm, Int.mul_left_comm] - _ ≤ (x * td) * k := hs - _ = (x * k) * td := by - simp only [Int.mul_comm, Int.mul_left_comm] - have hadd := Int.add_le_add_right hs' ((c + e) * td) - rw [← Int.add_mul] at hadd - simpa only [Int.add_assoc] using hadd - -theorem sumGE_mono_N {n m p q y w : Nat} (hq : 0 < q) (hnm : n ≤ m) - (h : sumGE n p q y w) : sumGE m p q y w := by - unfold sumGE at h ⊢ - let Dn := fact n * q ^ n - let Dm := fact m * q ^ m - have hDn : 0 < Dn := Nat.mul_pos (fact_pos n) (Nat.pow_pos hq) - have hmono := expNum_mono_N (p := p) (q := q) hnm - change expNum n p q * Dm ≤ expNum m p q * Dn at hmono - refine Nat.le_of_mul_le_mul_right ?_ hDn - calc - y * Dm * Dn = (y * Dn) * Dm := by - rw [Nat.mul_assoc, Nat.mul_comm Dm Dn, ← Nat.mul_assoc] - _ ≤ (expNum n p q * w) * Dm := Nat.mul_le_mul_right _ h - _ = (expNum n p q * Dm) * w := by - rw [Nat.mul_assoc, Nat.mul_comm w Dm, ← Nat.mul_assoc] - _ ≤ (expNum m p q * Dn) * w := Nat.mul_le_mul_right _ hmono - _ = expNum m p q * w * Dn := by - rw [Nat.mul_assoc, Nat.mul_comm Dn w, ← Nat.mul_assoc] - -theorem pos_shift_direct_exact_of_sumGE {x n : Nat} - (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hclt : evmClz x < 160) - (hleaf : sumGE n - (lnErrArg (int256 (lnTail (evmSub 160 (evmClz x)) (mant x)))) lnErrQ - (posTopX (evmClz x) (mant x)) (10 ^ 18)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - have hx256 : x < 2 ^ 256 := by omega - have hbody : - lnWadToRayBody x = lnTail (evmSub 160 (evmClz x)) (mant x) := by - rw [lnWadToRayBody_eq_tail hx256] - rfl - have htop : x ≤ posTopX (evmClz x) (mant x) := by - have hw := mant_window_le h1 h2 (by omega : evmClz x ≤ 160) - have hpos : 0 < (mant x + 1) * 2 ^ (160 - evmClz x) := - Nat.mul_pos (Nat.succ_pos _) (Nat.pow_pos (by decide)) - unfold posTopX - omega - refine capLB_exact_of_sumGE_mono (n := n) (p0 := - lnErrArg (int256 (lnTail (evmSub 160 (evmClz x)) (mant x)))) - (p := lnErrArg (int256 (lnWadToRayBody x))) - (y0 := posTopX (evmClz x) (mant x)) (y := x) ?_ htop hleaf - rw [hbody] - -theorem lnErrArg_mono {r0 r : Int} (hle : r0 ≤ r) : lnErrArg r0 ≤ lnErrArg r := by - unfold lnErrArg lnErrorBoundDen lnErrorBoundNum - exact Nat.mul_le_mul_right (2 ^ 99) - (Int.toNat_le_toNat (by omega : - r0 * (1000000000 : Int) + (1698600000 : Int) ≤ - r * (1000000000 : Int) + (1698600000 : Int))) - -theorem capLB_exact_of_body_interval_sumGE {n x lo hi : Nat} - (hlo : 1 ≤ lo) (hxlo : lo ≤ x) (hxhi : x ≤ hi) (hhi : hi < 2 ^ 255) - (h : sumGE n (lnErrArg (int256 (lnWadToRayBody lo))) lnErrQ hi (10 ^ 18)) : - capLB (lnErrArg (int256 (lnWadToRayBody x))) lnErrQ x (10 ^ 18) := by - have hmono := lnWadToRayBody_mono (x := lo) (y := x) (by omega) hxlo (by omega) - have hrle : int256 (lnWadToRayBody lo) ≤ int256 (lnWadToRayBody x) := - toInt_of_sle (lnWadToRayBody_lt (by omega : lo < 2 ^ 256)) - (lnWadToRayBody_lt (by omega : x < 2 ^ 256)) hmono - exact capLB_exact_of_sumGE_mono (p0 := lnErrArg (int256 (lnWadToRayBody lo))) - (y0 := hi) (lnErrArg_mono hrle) hxhi h - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean b/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean deleted file mode 100644 index 9ffdec361..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/PhaseCover.lean +++ /dev/null @@ -1,492 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.Args -import LnProof.Error.Core.Residue -import LnProof.Error.Core.Budget -import LnProof.Error.Core.Direct - -/-! -# Error bound — PhaseCover - -Phase cell deciders / covers and the `posPhaseNat*` casts into `lnErrArg`. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def gePhaseCellOkB (lo hi c : Nat) : Bool := - decide (Sc ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - sumGEB 320 (posPhaseNatGe lo c + lnPhaseExtraArg) lnErrQ - (posTopX c hi) (10 ^ 18) - -def ltPhaseCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < Sc) && - decide (c < 160) && - sumGEB 320 (posPhaseNatLt lo c + lnPhaseExtraArg) lnErrQ - (posTopX c hi) (10 ^ 18) - -def gePhaseGapCellOkB (lo hi c : Nat) : Bool := - decide (Sc ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - sumGEB 320 (posPhaseNatGe lo c + lnPhaseExtraArg + lnDirectGapArg) - lnErrQ (posTopX c hi) (10 ^ 18) - -def ltPhaseGapCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < Sc) && - decide (c < 160) && - sumGEB 320 (posPhaseNatLt lo c + lnPhaseExtraArg + lnDirectGapArg) - lnErrQ (posTopX c hi) (10 ^ 18) - -def geTopBudgetCoarseCellOkB (lo hi c : Nat) : Bool := - decide (Sc ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - decide (wadRayNum (posTopX c hi) * (posBaseWGe c * lnErrQ) ≤ - (posBaseYGe lo c * (lnErrQ + minPosAvail)) * wadRayStrictDen) - -def ltTopBudgetCoarseCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < Sc) && - decide (c < 160) && - decide (wadRayNum (posTopX c hi) * (posBaseWLt c * lnErrQ) ≤ - (posBaseYLt lo c * (lnErrQ + minPosAvail)) * wadRayStrictDen) - -def geTopBudgetRunCellOkB (lo hi c : Nat) : Bool := - decide (Sc ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - let rlo := int256 (lnTail (evmSub 160 c) lo) - decide (posAccI hi c < (rlo + 1) * twoPow72I) && - decide (wadRayNum (posTopX c hi) * (posBaseWGe c * lnErrQ) ≤ - (posBaseYGe lo c * (lnErrQ + posAvailGe hi c rlo)) * wadRayStrictDen) - -def ltTopBudgetRunCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < Sc) && - decide (c < 160) && - let rlo := int256 (lnTail (evmSub 160 c) lo) - decide (posAccI hi c < (rlo + 1) * twoPow72I) && - decide (wadRayNum (posTopX c hi) * (posBaseWLt c * lnErrQ) ≤ - (posBaseYLt lo c * (lnErrQ + posAvailLt hi c rlo)) * wadRayStrictDen) - -theorem gePhaseCell_sound {lo hi m c : Nat} (h : gePhaseCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGePhaseDirectOk 320 m c := by - unfold gePhaseCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, _hc⟩, hsum⟩ := h - unfold PosShiftGePhaseDirectOk - refine sumGE_exact_mono (n := 320) - (p0 := posPhaseNatGe lo c + lnPhaseExtraArg) - (p := posPhaseNatGe m c + lnPhaseExtraArg) - (y0 := posTopX c hi) (y := posTopX c m) ?_ ?_ (sumGE_of_sumGEB hsum) - · exact Nat.add_le_add_right - (posPhaseNatGe_mono_m hlo hlom (by omega)) lnPhaseExtraArg - · exact posTopX_mono_m hmhi - -theorem ltPhaseCell_sound {lo hi m c : Nat} (h : ltPhaseCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtPhaseDirectOk 320 m c := by - unfold ltPhaseCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, _hc⟩, hsum⟩ := h - unfold PosShiftLtPhaseDirectOk - refine sumGE_exact_mono (n := 320) - (p0 := posPhaseNatLt lo c + lnPhaseExtraArg) - (p := posPhaseNatLt m c + lnPhaseExtraArg) - (y0 := posTopX c hi) (y := posTopX c m) ?_ ?_ (sumGE_of_sumGEB hsum) - · exact Nat.add_le_add_right - (posPhaseNatLt_mono_m hlo hlom (by simp only [Sc, MHI] at hhi ⊢; omega)) - lnPhaseExtraArg - · exact posTopX_mono_m hmhi - -theorem gePhaseGapCell_sound {lo hi m c : Nat} - (h : gePhaseGapCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGePhaseGapDirectOk 320 m c := by - unfold gePhaseGapCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, _hc⟩, hsum⟩ := h - unfold PosShiftGePhaseGapDirectOk - refine sumGE_exact_mono (n := 320) - (p0 := posPhaseNatGe lo c + lnPhaseExtraArg + lnDirectGapArg) - (p := posPhaseNatGe m c + lnPhaseExtraArg + lnDirectGapArg) - (y0 := posTopX c hi) (y := posTopX c m) ?_ ?_ (sumGE_of_sumGEB hsum) - · exact Nat.add_le_add_right - (Nat.add_le_add_right (posPhaseNatGe_mono_m hlo hlom (by omega)) - lnPhaseExtraArg) lnDirectGapArg - · exact posTopX_mono_m hmhi - -theorem ltPhaseGapCell_sound {lo hi m c : Nat} - (h : ltPhaseGapCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtPhaseGapDirectOk 320 m c := by - unfold ltPhaseGapCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, _hc⟩, hsum⟩ := h - unfold PosShiftLtPhaseGapDirectOk - refine sumGE_exact_mono (n := 320) - (p0 := posPhaseNatLt lo c + lnPhaseExtraArg + lnDirectGapArg) - (p := posPhaseNatLt m c + lnPhaseExtraArg + lnDirectGapArg) - (y0 := posTopX c hi) (y := posTopX c m) ?_ ?_ (sumGE_of_sumGEB hsum) - · exact Nat.add_le_add_right - (Nat.add_le_add_right - (posPhaseNatLt_mono_m hlo hlom (by simp only [Sc, MHI] at hhi ⊢; omega)) - lnPhaseExtraArg) lnDirectGapArg - · exact posTopX_mono_m hmhi - -def phaseSearchFuel : Nat := 128 -def phaseCoverFuel : Nat := 20000 - -def phaseSearchMax (fuel : Nat) (ok : Nat → Bool) (lo hi best : Nat) : Nat := - match fuel with - | 0 => best - | fuel + 1 => - if lo ≤ hi then - let mid := (lo + hi) / 2 - if ok mid then - phaseSearchMax fuel ok (mid + 1) hi mid - else - phaseSearchMax fuel ok lo (mid - 1) best - else - best - -def gePhaseCoverB : Nat → Nat → Nat → Nat → Bool - | 0, _c, lo, hi => decide (hi < lo) - | fuel + 1, c, lo, hi => - if hi < lo then - true - else - let mx := phaseSearchMax phaseSearchFuel (fun h => gePhaseCellOkB lo h c) - lo hi (lo - 1) - decide (lo ≤ mx) && - decide (mx ≤ hi) && - gePhaseCellOkB lo mx c && - gePhaseCoverB fuel c (mx + 1) hi - -def ltPhaseCoverB : Nat → Nat → Nat → Nat → Bool - | 0, _c, lo, hi => decide (hi < lo) - | fuel + 1, c, lo, hi => - if hi < lo then - true - else if lo = lnErrorHardMantissa then - ltPhaseCoverB fuel c (lo + 1) hi - else - let mx := phaseSearchMax phaseSearchFuel (fun h => ltPhaseCellOkB lo h c) - lo hi (lo - 1) - decide (lo ≤ mx) && - decide (mx ≤ hi) && - ltPhaseCellOkB lo mx c && - ltPhaseCoverB fuel c (mx + 1) hi - -theorem gePhaseCoverB_sound {fuel c lo hi m : Nat} - (h : gePhaseCoverB fuel c lo hi = true) (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGePhaseDirectOk 320 m c := by - revert lo - induction fuel with - | zero => - intro lo h hlom - unfold gePhaseCoverB at h - simp only [decide_eq_true_eq] at h - omega - | succ fuel ih => - intro lo h hlom - unfold gePhaseCoverB at h - by_cases hdone : hi < lo - · rw [if_pos hdone] at h - omega - · rw [if_neg hdone] at h - let mx := phaseSearchMax phaseSearchFuel (fun h => gePhaseCellOkB lo h c) - lo hi (lo - 1) - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨hlmx, hmxhi⟩, hcell⟩, hrest⟩ := h - by_cases hleft : m ≤ mx - · exact gePhaseCell_sound hcell hlom hleft - · exact ih (lo := mx + 1) hrest (by omega) - -theorem ltPhaseCoverB_sound {fuel c lo hi m : Nat} - (h : ltPhaseCoverB fuel c lo hi = true) (hlom : lo ≤ m) (hmhi : m ≤ hi) : - m = lnErrorHardMantissa ∨ PosShiftLtPhaseDirectOk 320 m c := by - revert lo - induction fuel with - | zero => - intro lo h hlom - unfold ltPhaseCoverB at h - simp only [decide_eq_true_eq] at h - omega - | succ fuel ih => - intro lo h hlom - unfold ltPhaseCoverB at h - by_cases hdone : hi < lo - · rw [if_pos hdone] at h - omega - · rw [if_neg hdone] at h - by_cases hhard : lo = lnErrorHardMantissa - · rw [if_pos hhard] at h - by_cases hm : m = lo - · exact Or.inl (by omega) - · exact ih (lo := lo + 1) h (by omega) - · rw [if_neg hhard] at h - let mx := phaseSearchMax phaseSearchFuel (fun h => ltPhaseCellOkB lo h c) - lo hi (lo - 1) - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨hlmx, hmxhi⟩, hcell⟩, hrest⟩ := h - by_cases hleft : m ≤ mx - · exact Or.inr (ltPhaseCell_sound hcell hlom hleft) - · exact ih (lo := mx + 1) hrest (by omega) - -structure PhaseCell where - lo : Nat - hi : Nat - -def gePhaseCellListCoverB (c : Nat) : Nat → Nat → List PhaseCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - gePhaseCellOkB cell.lo cell.hi c && - gePhaseCellListCoverB c (cell.hi + 1) hi cells - -def ltPhaseCellListCoverB (c : Nat) : Nat → Nat → List PhaseCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - ltPhaseCellOkB cell.lo cell.hi c && - ltPhaseCellListCoverB c (cell.hi + 1) hi cells - -theorem gePhaseCellListCoverB_sound {cells : List PhaseCell} {c lo hi m : Nat} - (h : gePhaseCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGePhaseDirectOk 320 m c := by - induction cells generalizing lo with - | nil => - unfold gePhaseCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold gePhaseCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact gePhaseCell_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -theorem ltPhaseCellListCoverB_sound {cells : List PhaseCell} {c lo hi m : Nat} - (h : ltPhaseCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtPhaseDirectOk 320 m c := by - induction cells generalizing lo with - | nil => - unfold ltPhaseCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold ltPhaseCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact ltPhaseCell_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -theorem posPhaseI_le_of_floor {m c : Nat} {r : Int} (hc : c ≤ 160) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI < (r + 1) * 2 ^ 72) : - posPhaseI m c ≤ (r + 1) * twoPow99I - twoPow27I := by - have h := phase_lt_scaled_le hr - change (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI) * twoPow27I ≤ ((r + 1) * twoPow72I - 1) * twoPow27I at h - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - have hVs' : - (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI) * twoPow27I = - int256 (x1W (zWord m)) * lnPhaseScaleI + - ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + - lnBiasI * twoPow27I := by - simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs - rw [hVs'] at h - have er : ((r + 1) * twoPow72I - 1) * twoPow27I = - (r + 1) * twoPow99I - twoPow27I := by - unfold twoPow72I twoPow27I twoPow99I - rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from - by decide] - omega - rw [er] at h - simpa [posPhaseI, lnPhaseScaleI, twoPow27I, lnBiasI] using h - -theorem posPhaseNatGe_cast {m c : Nat} - (hX : 0 ≤ int256 (x1W (zWord m))) : - ((posPhaseNatGe m c : Nat) : Int) = - posPhaseI m c * (lnErrorBoundDen : Int) := by - have hXn : (((int256 (x1W (zWord m))).toNat : Nat) : Int) = - int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX - have hBc : ((BIASc * twoPow27N : Nat) : Int) = lnBiasI * twoPow27I := by - simp only [Int.natCast_mul] - rfl - have hLc : (((160 - c) * (LN2c * twoPow27N) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) := by - simp only [Int.natCast_mul] - unfold twoPow27N twoPow27I - rfl - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - have hscale : ((lnPhaseScaleN : Nat) : Int) = lnPhaseScaleI := rfl - have hN : (((160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) : Nat) : Int) = - (((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I)) * - (1000000000 : Int) := by - rw [show (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) = - ((160 - c) * (LN2c * twoPow27N)) * lnErrorBoundDen by - simp only [Nat.mul_assoc]] - simp only [Int.natCast_mul, hLc, hden] - unfold posPhaseNatGe posPhaseI - simp only [Int.natCast_add, Int.natCast_mul, hXn, hBc, hN, hden, hscale] - rw [Int.add_mul, Int.add_mul] - -theorem posConstNat_cast (c : Nat) : - ((posConstNat c : Nat) : Int) = - (((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + - lnBiasI * twoPow27I) * (lnErrorBoundDen : Int) := by - have hBc : ((BIASc * twoPow27N : Nat) : Int) = lnBiasI * twoPow27I := by - unfold twoPow27N twoPow27I lnBiasI - decide +kernel - have hLc : (((160 - c) * (LN2c * twoPow27N) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) := by - simp only [Int.natCast_mul] - unfold twoPow27N twoPow27I - rfl - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - have hN : (((160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) : Nat) : Int) = - (((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I)) * - (1000000000 : Int) := by - rw [show (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) = - ((160 - c) * (LN2c * twoPow27N)) * lnErrorBoundDen by - simp only [Nat.mul_assoc]] - simp only [Int.natCast_mul, hLc, hden] - unfold posConstNat - simp only [Int.natCast_add, Int.natCast_mul, hBc, hN, hden] - rw [Int.add_mul] - -theorem posNegXNat_cast {m : Nat} - (hX : int256 (x1W (zWord m)) ≤ 0) : - ((posNegXNat m : Nat) : Int) = - (-int256 (x1W (zWord m)) * lnPhaseScaleI) * (lnErrorBoundDen : Int) := by - have hXn : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = - -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hscale : ((lnPhaseScaleN : Nat) : Int) = lnPhaseScaleI := rfl - unfold posNegXNat - simp only [Int.natCast_mul, hXn, hscale] - -theorem posPhaseNatLt_cast {m c : Nat} - (hX : int256 (x1W (zWord m)) ≤ 0) - (hneg : posNegXNat m ≤ posConstNat c) : - ((posPhaseNatLt m c : Nat) : Int) = - posPhaseI m c * (lnErrorBoundDen : Int) := by - have hconst := posConstNat_cast c - have hnegc := posNegXNat_cast (m := m) hX - have hsub : ((posConstNat c - posNegXNat m : Nat) : Int) = - ((posConstNat c : Nat) : Int) - ((posNegXNat m : Nat) : Int) := by - omega - unfold posPhaseNatLt - rw [hsub, hconst, hnegc] - unfold posPhaseI - rw [Int.add_mul, Int.add_mul, Int.add_mul] - rw [show (-int256 (x1W (zWord m)) * lnPhaseScaleI) * - (lnErrorBoundDen : Int) = - -(int256 (x1W (zWord m)) * lnPhaseScaleI * (lnErrorBoundDen : Int)) by - rw [Int.neg_mul, Int.neg_mul]] - omega - -theorem posPhaseNatGe_le_lnErrArg {m c : Nat} {r : Int} - (hge : Sc ≤ m) (hmhi : m < MHI) (hc : c ≤ 160) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI < (r + 1) * 2 ^ 72) - (hr0 : -1 ≤ r) : - posPhaseNatGe m c ≤ lnErrArg r := by - have hX := x1_nonneg_geF hge hmhi - have hphase := posPhaseI_le_of_floor hc hr - have hcore := c160_arg_le_int (A := posPhaseI m c) (r := r) hphase - have harg : 0 ≤ r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - have h0 : 0 ≤ r + 1 := by omega - have hp : 0 ≤ (r + 1) * (1000000000 : Int) := - Int.mul_nonneg h0 (by decide) - have e : (r + 1) * (1000000000 : Int) + 698600000 = - r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int) := by - unfold lnErrorBoundDen lnErrorBoundNum - rw [Int.add_mul, Int.one_mul] - omega - rw [← e] - exact Int.add_nonneg hp (by decide) - apply Int.ofNat_le.mp - rw [posPhaseNatGe_cast hX] - unfold lnErrArg - rw [Int.natCast_mul, Int.toNat_of_nonneg harg] - have hnon : 0 ≤ 698600000 * twoPow99I := by - unfold twoPow99I - decide - have hle := Int.le_trans (Int.le_add_of_nonneg_right hnon) hcore - simpa [lnErrorBoundDen, lnErrorBoundNum, twoPow99I] using hle - -theorem posNegXNat_le_posConstNat {m c : Nat} - (hX : int256 (x1W (zWord m)) ≤ 0) (hc : c ≤ 160) - (hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI) : - posNegXNat m ≤ posConstNat c := by - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - have hV0s : 0 ≤ posPhaseI m c := by - have hmul := Int.mul_nonneg hV0 - (by unfold twoPow27I; decide : 0 ≤ twoPow27I) - change 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI) * twoPow27I at hmul - have hVs' : - (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - lnBiasI) * twoPow27I = - int256 (x1W (zWord m)) * lnPhaseScaleI + - ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + - lnBiasI * twoPow27I := by - simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs - rw [hVs'] at hmul - simpa [posPhaseI, lnPhaseScaleI, twoPow27I, lnBiasI] using hmul - apply Int.ofNat_le.mp - rw [posNegXNat_cast hX, posConstNat_cast c] - unfold posPhaseI at hV0s - have hmain : - -int256 (x1W (zWord m)) * lnPhaseScaleI ≤ - ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + - lnBiasI * twoPow27I := by - rw [show -int256 (x1W (zWord m)) * lnPhaseScaleI = - -(int256 (x1W (zWord m)) * lnPhaseScaleI) by rw [Int.neg_mul]] - generalize int256 (x1W (zWord m)) * lnPhaseScaleI = A at hV0s ⊢ - omega - exact Int.mul_le_mul_of_nonneg_right hmain (Int.natCast_nonneg _) - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/PhaseGe.lean b/formal/ln/LnProof/LnProof/Error/Core/PhaseGe.lean deleted file mode 100644 index 322068b29..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/PhaseGe.lean +++ /dev/null @@ -1,324 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.ExpMargin -import LnProof.Error.Core.Budget - -/-! -# Error bound — PhaseGe - -Ge-branch phase-lower margin polynomials and their soundness. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def posTopXPoly (c : Nat) : List Int := - [((2 ^ (160 - c) : Nat) : Int) - 1, ((2 ^ (160 - c) : Nat) : Int)] - -theorem eval_posTopXPoly (m c : Nat) : - evalPoly (posTopXPoly c) (m : Int) = (posTopX c m : Int) := by - unfold posTopXPoly posTopX - simp only [evalPoly] - have hpow : 0 < 2 ^ (160 - c) := Nat.pow_pos (by decide) - have hprod : 1 ≤ (m + 1) * 2 ^ (160 - c) := Nat.succ_le_of_lt - (Nat.mul_pos (Nat.succ_pos m) hpow) - rw [Int.natCast_sub (n := 1) (m := (m + 1) * 2 ^ (160 - c)) hprod] - simp only [Int.natCast_mul, Int.natCast_add, Int.natCast_one, Int.mul_zero, Int.add_zero] - rw [Int.add_mul, Int.one_mul] - omega - -def gePhaseLowerPN (c : Nat) : List Int := - polyAdd - (polyScale (((2 ^ 99 * lnPhaseScaleN * lnErrorBoundDen : Nat) : Int)) geTN2b) - (polyScale (((posConstNat c + lnPhaseExtraArg : Nat) : Int)) geTD2b) - -def gePhaseLowerQD : List Int := - polyScale ((lnErrQ : Nat) : Int) geTD2b - -def gePhaseLowerMarginPoly (c : Nat) : List Int := - expMarginPolyFast 320 (gePhaseLowerPN c) gePhaseLowerQD (posTopXPoly c) (10 ^ 18) - -theorem geTD2b_pos_of_outer {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - 0 < evalPoly geTD2b (m : Int) := by - have hw1 : (56022770974786139918731938273 : Int) ≤ (m : Int) := by - simp only [Sc] at h1 - omega - have hw2 : (m : Int) ≤ 79228162514264337593543950335 := by - simp only [MHI] at h2 - omega - have h := geTD2_nonneg hw1 hw2 - rw [evalCertGeTD2] at h - omega - -theorem geTN2b_nonneg_of_outer {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - 0 ≤ evalPoly geTN2b (m : Int) := by - have hw1 : (56022770974786139918731938273 : Int) ≤ (m : Int) := by - simp only [Sc] at h1 - omega - have hw2 : (m : Int) ≤ 79228162514264337593543950335 := by - simp only [MHI] at h2 - omega - exact geTN2_nonneg hw1 hw2 - -theorem gePhaseLowerPN_nonneg {m c : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - 0 ≤ evalPoly (gePhaseLowerPN c) (m : Int) := by - have htn := geTN2b_nonneg_of_outer h1 h2 - have htd : 0 ≤ evalPoly geTD2b (m : Int) := by - exact Int.le_of_lt (geTD2b_pos_of_outer h1 h2) - unfold gePhaseLowerPN - rw [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyScale] - exact Int.add_nonneg - (Int.mul_nonneg (Int.natCast_nonneg _) htn) - (Int.mul_nonneg (Int.natCast_nonneg _) htd) - -theorem gePhaseLowerQD_pos {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - 0 < evalPoly gePhaseLowerQD (m : Int) := by - unfold gePhaseLowerQD - rw [evalPoly_polyScale] - exact Int.mul_pos (by unfold lnErrQ QS lnErrorBoundDen; decide) - (geTD2b_pos_of_outer h1 h2) - -theorem posPhaseNatGe_cast_decomp {m c : Nat} - (hX : 0 ≤ int256 (x1W (zWord m))) : - ((posPhaseNatGe m c : Nat) : Int) = - int256 (x1W (zWord m)) * - ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) + - (posConstNat c : Int) := by - have hXn : (((int256 (x1W (zWord m))).toNat : Nat) : Int) = - int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX - unfold posPhaseNatGe posConstNat - simp only [Int.natCast_add, Int.natCast_mul, hXn] - simp only [Int.mul_assoc] - rw [Int.add_assoc] - -theorem gePhaseLowerPN_le_phase_mul_TD {m c : Nat} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - evalPoly (gePhaseLowerPN c) (m : Int) ≤ - ((posPhaseNatGe m c + lnPhaseExtraArg : Nat) : Int) * - evalPoly geTD2b (m : Int) := by - have hbr := bracket_ge_lo h1 h2 - generalize hTN : evalPoly geTN2b (m : Int) = TN at hbr ⊢ - generalize hTD : evalPoly geTD2b (m : Int) = TD at hbr ⊢ - have hX := x1_nonneg_ge h1 h2 - have hphase0 := posPhaseNatGe_cast_decomp (m := m) (c := c) hX - generalize hXV : int256 (x1W (zWord m)) = X at hbr hphase0 ⊢ - let K : Int := ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) - let C : Int := (posConstNat c : Int) - let E : Int := (lnPhaseExtraArg : Int) - have hphase : - ((posPhaseNatGe m c + lnPhaseExtraArg : Nat) : Int) = X * K + C + E := by - rw [Int.natCast_add, hphase0] - have hpn : - evalPoly (gePhaseLowerPN c) (m : Int) = (2 ^ 99 * K) * TN + (C + E) * TD := by - unfold gePhaseLowerPN - rw [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyScale, hTN, hTD] - simp only [K, C, E, Int.natCast_add, Int.natCast_mul, Int.natCast_pow, - Int.mul_assoc] - rfl - have hAlg := ge_phase_lower_algebra - (tn := TN) (td := TD) (x := X) (k := K) (c := C) (e := E) - (by unfold K; exact Int.natCast_nonneg _) hbr - rw [hpn, hphase] - exact hAlg - -theorem gePhaseLowerMargin_sound {m c : Nat} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) - (hcert : 0 ≤ evalPoly (gePhaseLowerMarginPoly c) (m : Int)) : - PosShiftGePhaseDirectOk 320 m c := by - let PN := evalPoly (gePhaseLowerPN c) (m : Int) - let QD := evalPoly gePhaseLowerQD (m : Int) - let P := posPhaseNatGe m c + lnPhaseExtraArg - have hPNnon : 0 ≤ PN := by - simpa [PN] using gePhaseLowerPN_nonneg (m := m) (c := c) h1 h2 - have hQDpos : 0 < QD := by - simpa [QD] using gePhaseLowerQD_pos (m := m) h1 h2 - have hPNcast : (((PN.toNat : Nat) : Int)) = PN := - Int.toNat_of_nonneg hPNnon - have hQDcast : (((QD.toNat : Nat) : Int)) = QD := - Int.toNat_of_nonneg (Int.le_of_lt hQDpos) - have hY := eval_posTopXPoly m c - have hsum : sumGE 320 PN.toNat QD.toNat (posTopX c m) (10 ^ 18) := by - refine sumGE_of_expMarginPolyFast - (n := 320) (m := m) (p := PN.toNat) (q := QD.toNat) - (y := posTopX c m) (w := 10 ^ 18) - (pn := gePhaseLowerPN c) (qd := gePhaseLowerQD) (yp := posTopXPoly c) - ?_ ?_ ?_ ?_ - · simpa [gePhaseLowerMarginPoly, PN, QD] using hcert - · exact hPNcast.symm - · exact hQDcast.symm - · exact hY - have hqpos : 0 < QD.toNat := by - apply Int.ofNat_lt.mp - rw [hQDcast] - exact hQDpos - have harg : PN.toNat * lnErrQ ≤ P * QD.toNat := by - apply Int.ofNat_le.mp - simp only [Int.natCast_mul, hPNcast, hQDcast] - have hPNle : PN ≤ (P : Int) * evalPoly geTD2b (m : Int) := by - simpa [PN, P] using gePhaseLowerPN_le_phase_mul_TD (m := m) (c := c) h1 h2 - have hlnNon : 0 ≤ (lnErrQ : Int) := by - unfold lnErrQ QS lnErrorBoundDen - decide - have hmul := Int.mul_le_mul_of_nonneg_right hPNle hlnNon - have hQD : - QD = (lnErrQ : Int) * evalPoly geTD2b (m : Int) := by - unfold QD gePhaseLowerQD - rw [evalPoly_polyScale] - rw [hQD] - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - unfold PosShiftGePhaseDirectOk - exact sumGE_arg_mono (q' := QD.toNat) hqpos harg hsum - -theorem gePhaseLowerMarginVal_sound {m c : Nat} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) - (hcert : 0 ≤ expMarginVal 320 (evalPoly (gePhaseLowerPN c) (m : Int)) - (evalPoly gePhaseLowerQD (m : Int)) (evalPoly (posTopXPoly c) (m : Int)) - (((10 ^ 18 : Nat) : Int))) : - PosShiftGePhaseDirectOk 320 m c := by - let PN := evalPoly (gePhaseLowerPN c) (m : Int) - let QD := evalPoly gePhaseLowerQD (m : Int) - let P := posPhaseNatGe m c + lnPhaseExtraArg - have hPNnon : 0 ≤ PN := by - simpa [PN] using gePhaseLowerPN_nonneg (m := m) (c := c) h1 h2 - have hQDpos : 0 < QD := by - simpa [QD] using gePhaseLowerQD_pos (m := m) h1 h2 - have hPNcast : (((PN.toNat : Nat) : Int)) = PN := - Int.toNat_of_nonneg hPNnon - have hQDcast : (((QD.toNat : Nat) : Int)) = QD := - Int.toNat_of_nonneg (Int.le_of_lt hQDpos) - have hY := eval_posTopXPoly m c - have hsum : sumGE 320 PN.toNat QD.toNat (posTopX c m) (10 ^ 18) := by - refine sumGE_of_expMarginVal - (n := 320) (p := PN.toNat) (q := QD.toNat) - (y := posTopX c m) (w := 10 ^ 18) ?_ - rw [hPNcast, hQDcast, ← hY] - exact hcert - have hqpos : 0 < QD.toNat := by - apply Int.ofNat_lt.mp - rw [hQDcast] - exact hQDpos - have harg : PN.toNat * lnErrQ ≤ P * QD.toNat := by - apply Int.ofNat_le.mp - simp only [Int.natCast_mul, hPNcast, hQDcast] - have hPNle : PN ≤ (P : Int) * evalPoly geTD2b (m : Int) := by - simpa [PN, P] using gePhaseLowerPN_le_phase_mul_TD (m := m) (c := c) h1 h2 - have hlnNon : 0 ≤ (lnErrQ : Int) := by - unfold lnErrQ QS lnErrorBoundDen - decide - have hmul := Int.mul_le_mul_of_nonneg_right hPNle hlnNon - have hQD : - QD = (lnErrQ : Int) * evalPoly geTD2b (m : Int) := by - unfold QD gePhaseLowerQD - rw [evalPoly_polyScale] - rw [hQD] - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - unfold PosShiftGePhaseDirectOk - exact sumGE_arg_mono (q' := QD.toNat) hqpos harg hsum - -def gePhaseLowerPNMin (c : Nat) : List Int := - polyAdd - (polyScale (((2 ^ 99 * lnPhaseScaleN * lnErrorBoundDen : Nat) : Int)) geTN2b) - (polyScale (((posConstNat c + minPosAvail : Nat) : Int)) geTD2b) - -def gePhaseLowerMarginPolyMin (c : Nat) : List Int := - expMarginPolyFast 320 (gePhaseLowerPNMin c) gePhaseLowerQD (posTopXPoly c) (10 ^ 18) - -theorem gePhaseLowerPNMin_nonneg {m c : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - 0 ≤ evalPoly (gePhaseLowerPNMin c) (m : Int) := by - have htn := geTN2b_nonneg_of_outer h1 h2 - have htd : 0 ≤ evalPoly geTD2b (m : Int) := by - exact Int.le_of_lt (geTD2b_pos_of_outer h1 h2) - unfold gePhaseLowerPNMin - rw [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyScale] - exact Int.add_nonneg - (Int.mul_nonneg (Int.natCast_nonneg _) htn) - (Int.mul_nonneg (Int.natCast_nonneg _) htd) - -theorem gePhaseLowerPNMin_le_phase_mul_TD {m c : Nat} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - evalPoly (gePhaseLowerPNMin c) (m : Int) ≤ - ((posPhaseNatGe m c + minPosAvail : Nat) : Int) * - evalPoly geTD2b (m : Int) := by - have hbr := bracket_ge_lo h1 h2 - generalize hTN : evalPoly geTN2b (m : Int) = TN at hbr ⊢ - generalize hTD : evalPoly geTD2b (m : Int) = TD at hbr ⊢ - have hX := x1_nonneg_ge h1 h2 - have hphase0 := posPhaseNatGe_cast_decomp (m := m) (c := c) hX - generalize hXV : int256 (x1W (zWord m)) = X at hbr hphase0 ⊢ - let K : Int := ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) - let C : Int := (posConstNat c : Int) - let E : Int := (minPosAvail : Int) - have hphase : - ((posPhaseNatGe m c + minPosAvail : Nat) : Int) = X * K + C + E := by - rw [Int.natCast_add, hphase0] - have hpn : - evalPoly (gePhaseLowerPNMin c) (m : Int) = (2 ^ 99 * K) * TN + (C + E) * TD := by - unfold gePhaseLowerPNMin - rw [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyScale, hTN, hTD] - simp only [K, C, E, Int.natCast_add, Int.natCast_mul, Int.natCast_pow, - Int.mul_assoc] - rfl - have hAlg := ge_phase_lower_algebra - (tn := TN) (td := TD) (x := X) (k := K) (c := C) (e := E) - (by unfold K; exact Int.natCast_nonneg _) hbr - rw [hpn, hphase] - exact hAlg - -theorem gePhaseLowerMarginValMin_sound {m c : Nat} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) - (hcert : 0 ≤ expMarginVal 320 (evalPoly (gePhaseLowerPNMin c) (m : Int)) - (evalPoly gePhaseLowerQD (m : Int)) (evalPoly (posTopXPoly c) (m : Int)) - (((10 ^ 18 : Nat) : Int))) : - PosShiftGeMinPhaseDirectOk 320 m c := by - let PN := evalPoly (gePhaseLowerPNMin c) (m : Int) - let QD := evalPoly gePhaseLowerQD (m : Int) - let P := posPhaseNatGe m c + minPosAvail - have hPNnon : 0 ≤ PN := by - simpa [PN] using gePhaseLowerPNMin_nonneg (m := m) (c := c) h1 h2 - have hQDpos : 0 < QD := by - simpa [QD] using gePhaseLowerQD_pos (m := m) h1 h2 - have hPNcast : (((PN.toNat : Nat) : Int)) = PN := - Int.toNat_of_nonneg hPNnon - have hQDcast : (((QD.toNat : Nat) : Int)) = QD := - Int.toNat_of_nonneg (Int.le_of_lt hQDpos) - have hY := eval_posTopXPoly m c - have hsum : sumGE 320 PN.toNat QD.toNat (posTopX c m) (10 ^ 18) := by - refine sumGE_of_expMarginVal - (n := 320) (p := PN.toNat) (q := QD.toNat) - (y := posTopX c m) (w := 10 ^ 18) ?_ - rw [hPNcast, hQDcast, ← hY] - exact hcert - have hqpos : 0 < QD.toNat := by - apply Int.ofNat_lt.mp - rw [hQDcast] - exact hQDpos - have harg : PN.toNat * lnErrQ ≤ P * QD.toNat := by - apply Int.ofNat_le.mp - simp only [Int.natCast_mul, hPNcast, hQDcast] - have hPNle : PN ≤ (P : Int) * evalPoly geTD2b (m : Int) := by - simpa [PN, P] using gePhaseLowerPNMin_le_phase_mul_TD (m := m) (c := c) h1 h2 - have hlnNon : 0 ≤ (lnErrQ : Int) := by - unfold lnErrQ QS lnErrorBoundDen - decide - have hmul := Int.mul_le_mul_of_nonneg_right hPNle hlnNon - have hQD : - QD = (lnErrQ : Int) * evalPoly geTD2b (m : Int) := by - unfold QD gePhaseLowerQD - rw [evalPoly_polyScale] - rw [hQD] - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - unfold PosShiftGeMinPhaseDirectOk - exact sumGE_arg_mono (q' := QD.toNat) hqpos harg hsum - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/PhaseLt.lean b/formal/ln/LnProof/LnProof/Error/Core/PhaseLt.lean deleted file mode 100644 index 5573c2689..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/PhaseLt.lean +++ /dev/null @@ -1,461 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.ExpMargin -import LnProof.Error.Core.Residue -import LnProof.Error.Core.Budget -import LnProof.Error.Core.PhaseGe -import LnProof.Error.Core.PhaseCover - -/-! -# Error bound — PhaseLt - -Lt-branch phase-lower margin polynomials, cells, and covers. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def ltPhaseLowerPN (c : Nat) : List Int := - polySub - (polyScale (((posConstNat c + lnPhaseExtraArg : Nat) : Int)) ltTD) - (polyScale (((2 ^ 99 * lnPhaseScaleN * lnErrorBoundDen : Nat) : Int)) ltTN) - -def ltPhaseLowerQD : List Int := - polyScale ((lnErrQ : Nat) : Int) ltTD - -def ltPhaseLowerMarginPoly (c : Nat) : List Int := - expMarginPolyFast 320 (ltPhaseLowerPN c) ltPhaseLowerQD (posTopXPoly c) (10 ^ 18) - -def polyIvOnCell (p : List Int) (lo hi : Nat) : Int × Int := - hornerIv (polyShift p (lo : Int)) 0 (((hi - lo : Nat) : Int)) - -def gePhaseLowerIvCellOkB (lo hi c : Nat) : Bool := - decide (Sc + 46 ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - let pIv := polyIvOnCell (gePhaseLowerPN c) lo hi - let qIv := polyIvOnCell gePhaseLowerQD lo hi - let yIv := polyIvOnCell (posTopXPoly c) lo hi - decide (0 ≤ pIv.1) && - decide (0 ≤ qIv.1) && - decide (0 ≤ expMarginIvLower 320 pIv qIv yIv (10 ^ 18)) - -def ltPhaseLowerIvCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi + 46 ≤ Sc) && - decide (c < 160) && - let pIv := polyIvOnCell (ltPhaseLowerPN c) lo hi - let qIv := polyIvOnCell ltPhaseLowerQD lo hi - let yIv := polyIvOnCell (posTopXPoly c) lo hi - decide (0 ≤ pIv.1) && - decide (0 ≤ qIv.1) && - decide (0 ≤ expMarginIvLower 320 pIv qIv yIv (10 ^ 18)) - -theorem ltTD_pos_of_outer {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : - 0 < evalPoly ltTD (m : Int) := by - have hw1 : (39614081257132168796771975168 : Int) ≤ (m : Int) := by - simp only [MLO] at h1 - omega - have hw2 : (m : Int) ≤ 56022770974786139918731938181 := by - simp only [Sc] at h2 - omega - have h := ltTD_nonneg hw1 hw2 - rw [evalCertLtTD] at h - omega - -theorem ltPhaseLowerQD_pos {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : - 0 < evalPoly ltPhaseLowerQD (m : Int) := by - unfold ltPhaseLowerQD - rw [evalPoly_polyScale] - exact Int.mul_pos (by unfold lnErrQ QS lnErrorBoundDen; decide) - (ltTD_pos_of_outer h1 h2) - -theorem posPhaseNatLt_cast_decomp {m c : Nat} - (hX : int256 (x1W (zWord m)) ≤ 0) - (hneg : posNegXNat m ≤ posConstNat c) : - ((posPhaseNatLt m c : Nat) : Int) = - (posConstNat c : Int) - - (-int256 (x1W (zWord m))) * - ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) := by - have hnegc : ((posNegXNat m : Nat) : Int) = - (-int256 (x1W (zWord m))) * - ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) := by - rw [posNegXNat_cast (m := m) hX] - change ((-int256 (x1W (zWord m))) * ((lnPhaseScaleN : Nat) : Int)) * - ((lnErrorBoundDen : Nat) : Int) = - (-int256 (x1W (zWord m))) * ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) - rw [Int.natCast_mul] - rw [Int.mul_assoc] - have hsub : ((posConstNat c - posNegXNat m : Nat) : Int) = - ((posConstNat c : Nat) : Int) - ((posNegXNat m : Nat) : Int) := by - omega - unfold posPhaseNatLt - rw [hsub, hnegc] - -theorem lt_phase_lower_algebra {tn td neg k c e : Int} - (hk : 0 ≤ k) (hbr : neg * td ≤ tn * 2 ^ 99) : - (c + e) * td - (2 ^ 99 * k) * tn ≤ - (c - neg * k + e) * td := by - have hmul := Int.mul_le_mul_of_nonneg_right hbr hk - have hmul' : neg * td * k ≤ (2 ^ 99 * k) * tn := by - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - have hrewrite : (c + e) * td - neg * td * k = (c - neg * k + e) * td := by - rw [Int.add_mul, Int.add_mul, Int.sub_mul] - have hterm : neg * td * k = neg * k * td := by - rw [Int.mul_assoc, Int.mul_comm td k, ← Int.mul_assoc] - rw [hterm] - omega - calc - (c + e) * td - (2 ^ 99 * k) * tn ≤ - (c + e) * td - neg * td * k := by - exact Int.sub_le_sub_left hmul' ((c + e) * td) - _ = (c - neg * k + e) * td := hrewrite - -theorem ltPhaseLowerPN_le_phase_mul_TD {m c : Nat} - (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hc : c < 160) : - evalPoly (ltPhaseLowerPN c) (m : Int) ≤ - ((posPhaseNatLt m c + lnPhaseExtraArg : Nat) : Int) * - evalPoly ltTD (m : Int) := by - have hbr := bracket_lt_up h1 h2 - generalize hTN : evalPoly ltTN (m : Int) = TN at hbr ⊢ - generalize hTD : evalPoly ltTD (m : Int) = TD at hbr ⊢ - have hX := x1_nonpos_lt h1 h2 - have hmhi : m < MHI := by - simp only [Sc, MHI] at h2 ⊢ - omega - have hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + lnBiasI := by - simpa [posAccI] using posAccI_nonneg h1 hmhi hc - have hneg := posNegXNat_le_posConstNat hX (Nat.le_of_lt hc) hV0 - have hphase0 := posPhaseNatLt_cast_decomp (m := m) (c := c) hX hneg - generalize hNegV : -int256 (x1W (zWord m)) = X at hbr hphase0 ⊢ - let K : Int := ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) - let C : Int := (posConstNat c : Int) - let E : Int := (lnPhaseExtraArg : Int) - have hphase : - ((posPhaseNatLt m c + lnPhaseExtraArg : Nat) : Int) = C - X * K + E := by - rw [Int.natCast_add, hphase0] - have hpn : - evalPoly (ltPhaseLowerPN c) (m : Int) = (C + E) * TD - (2 ^ 99 * K) * TN := by - unfold ltPhaseLowerPN polySub - rw [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyNeg, evalPoly_polyScale, - hTN, hTD] - simp only [K, C, E, Int.natCast_add, Int.natCast_mul, Int.natCast_pow, - Int.mul_assoc] - rfl - have hAlg := lt_phase_lower_algebra - (tn := TN) (td := TD) (neg := X) (k := K) (c := C) (e := E) - (by unfold K; exact Int.natCast_nonneg _) hbr - rw [hpn, hphase] - exact hAlg - -theorem ltPhaseLowerMargin_sound {m c : Nat} - (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hc : c < 160) - (hpn_nonneg : 0 ≤ evalPoly (ltPhaseLowerPN c) (m : Int)) - (hcert : 0 ≤ evalPoly (ltPhaseLowerMarginPoly c) (m : Int)) : - PosShiftLtPhaseDirectOk 320 m c := by - let PN := evalPoly (ltPhaseLowerPN c) (m : Int) - let QD := evalPoly ltPhaseLowerQD (m : Int) - let P := posPhaseNatLt m c + lnPhaseExtraArg - have hPNnon : 0 ≤ PN := by - simpa [PN] using hpn_nonneg - have hQDpos : 0 < QD := by - simpa [QD] using ltPhaseLowerQD_pos (m := m) h1 h2 - have hPNcast : (((PN.toNat : Nat) : Int)) = PN := - Int.toNat_of_nonneg hPNnon - have hQDcast : (((QD.toNat : Nat) : Int)) = QD := - Int.toNat_of_nonneg (Int.le_of_lt hQDpos) - have hY := eval_posTopXPoly m c - have hsum : sumGE 320 PN.toNat QD.toNat (posTopX c m) (10 ^ 18) := by - refine sumGE_of_expMarginPolyFast - (n := 320) (m := m) (p := PN.toNat) (q := QD.toNat) - (y := posTopX c m) (w := 10 ^ 18) - (pn := ltPhaseLowerPN c) (qd := ltPhaseLowerQD) (yp := posTopXPoly c) - ?_ ?_ ?_ ?_ - · change 0 ≤ evalPoly (ltPhaseLowerMarginPoly c) (m : Int) - exact hcert - · exact hPNcast.symm - · exact hQDcast.symm - · exact hY - have hqpos : 0 < QD.toNat := by - apply Int.ofNat_lt.mp - rw [hQDcast] - exact hQDpos - have harg : PN.toNat * lnErrQ ≤ P * QD.toNat := by - apply Int.ofNat_le.mp - simp only [Int.natCast_mul, hPNcast, hQDcast] - have hPNle : PN ≤ (P : Int) * evalPoly ltTD (m : Int) := by - change evalPoly (ltPhaseLowerPN c) (m : Int) ≤ - ((posPhaseNatLt m c + lnPhaseExtraArg : Nat) : Int) * evalPoly ltTD (m : Int) - exact ltPhaseLowerPN_le_phase_mul_TD (m := m) (c := c) h1 h2 hc - have hlnNon : 0 ≤ (lnErrQ : Int) := by - unfold lnErrQ QS lnErrorBoundDen - decide - have hmul := Int.mul_le_mul_of_nonneg_right hPNle hlnNon - have hQD : - QD = (lnErrQ : Int) * evalPoly ltTD (m : Int) := by - unfold QD ltPhaseLowerQD - rw [evalPoly_polyScale] - rw [hQD] - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - unfold PosShiftLtPhaseDirectOk - exact sumGE_arg_mono (q' := QD.toNat) hqpos harg hsum - -theorem ltPhaseLowerMarginVal_sound {m c : Nat} - (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hc : c < 160) - (hpn_nonneg : 0 ≤ evalPoly (ltPhaseLowerPN c) (m : Int)) - (hcert : 0 ≤ expMarginVal 320 (evalPoly (ltPhaseLowerPN c) (m : Int)) - (evalPoly ltPhaseLowerQD (m : Int)) (evalPoly (posTopXPoly c) (m : Int)) - (((10 ^ 18 : Nat) : Int))) : - PosShiftLtPhaseDirectOk 320 m c := by - let PN := evalPoly (ltPhaseLowerPN c) (m : Int) - let QD := evalPoly ltPhaseLowerQD (m : Int) - let P := posPhaseNatLt m c + lnPhaseExtraArg - have hPNnon : 0 ≤ PN := by - simpa [PN] using hpn_nonneg - have hQDpos : 0 < QD := by - simpa [QD] using ltPhaseLowerQD_pos (m := m) h1 h2 - have hPNcast : (((PN.toNat : Nat) : Int)) = PN := - Int.toNat_of_nonneg hPNnon - have hQDcast : (((QD.toNat : Nat) : Int)) = QD := - Int.toNat_of_nonneg (Int.le_of_lt hQDpos) - have hY := eval_posTopXPoly m c - have hsum : sumGE 320 PN.toNat QD.toNat (posTopX c m) (10 ^ 18) := by - refine sumGE_of_expMarginVal - (n := 320) (p := PN.toNat) (q := QD.toNat) - (y := posTopX c m) (w := 10 ^ 18) ?_ - rw [hPNcast, hQDcast, ← hY] - exact hcert - have hqpos : 0 < QD.toNat := by - apply Int.ofNat_lt.mp - rw [hQDcast] - exact hQDpos - have harg : PN.toNat * lnErrQ ≤ P * QD.toNat := by - apply Int.ofNat_le.mp - simp only [Int.natCast_mul, hPNcast, hQDcast] - have hPNle : PN ≤ (P : Int) * evalPoly ltTD (m : Int) := by - change evalPoly (ltPhaseLowerPN c) (m : Int) ≤ - ((posPhaseNatLt m c + lnPhaseExtraArg : Nat) : Int) * evalPoly ltTD (m : Int) - exact ltPhaseLowerPN_le_phase_mul_TD (m := m) (c := c) h1 h2 hc - have hlnNon : 0 ≤ (lnErrQ : Int) := by - unfold lnErrQ QS lnErrorBoundDen - decide - have hmul := Int.mul_le_mul_of_nonneg_right hPNle hlnNon - have hQD : - QD = (lnErrQ : Int) * evalPoly ltTD (m : Int) := by - unfold QD ltPhaseLowerQD - rw [evalPoly_polyScale] - rw [hQD] - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - unfold PosShiftLtPhaseDirectOk - exact sumGE_arg_mono (q' := QD.toNat) hqpos harg hsum - -def ltPhaseLowerPNMin (c : Nat) : List Int := - polySub - (polyScale (((posConstNat c + minPosAvail : Nat) : Int)) ltTD) - (polyScale (((2 ^ 99 * lnPhaseScaleN * lnErrorBoundDen : Nat) : Int)) ltTN) - -def ltPhaseLowerMarginPolyMin (c : Nat) : List Int := - expMarginPolyFast 320 (ltPhaseLowerPNMin c) ltPhaseLowerQD (posTopXPoly c) (10 ^ 18) - -theorem ltPhaseLowerPNMin_le_phase_mul_TD {m c : Nat} - (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hc : c < 160) : - evalPoly (ltPhaseLowerPNMin c) (m : Int) ≤ - ((posPhaseNatLt m c + minPosAvail : Nat) : Int) * - evalPoly ltTD (m : Int) := by - have hbr := bracket_lt_up h1 h2 - generalize hTN : evalPoly ltTN (m : Int) = TN at hbr ⊢ - generalize hTD : evalPoly ltTD (m : Int) = TD at hbr ⊢ - have hX := x1_nonpos_lt h1 h2 - have hmhi : m < MHI := by - simp only [Sc, MHI] at h2 ⊢ - omega - have hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + lnBiasI := by - simpa [posAccI] using posAccI_nonneg h1 hmhi hc - have hneg := posNegXNat_le_posConstNat hX (Nat.le_of_lt hc) hV0 - have hphase0 := posPhaseNatLt_cast_decomp (m := m) (c := c) hX hneg - generalize hNegV : -int256 (x1W (zWord m)) = X at hbr hphase0 ⊢ - let K : Int := ((lnPhaseScaleN * lnErrorBoundDen : Nat) : Int) - let C : Int := (posConstNat c : Int) - let E : Int := (minPosAvail : Int) - have hphase : - ((posPhaseNatLt m c + minPosAvail : Nat) : Int) = C - X * K + E := by - rw [Int.natCast_add, hphase0] - have hpn : - evalPoly (ltPhaseLowerPNMin c) (m : Int) = (C + E) * TD - (2 ^ 99 * K) * TN := by - unfold ltPhaseLowerPNMin polySub - rw [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyNeg, evalPoly_polyScale, - hTN, hTD] - simp only [K, C, E, Int.natCast_add, Int.natCast_mul, Int.natCast_pow, - Int.mul_assoc] - rfl - have hAlg := lt_phase_lower_algebra - (tn := TN) (td := TD) (neg := X) (k := K) (c := C) (e := E) - (by unfold K; exact Int.natCast_nonneg _) hbr - rw [hpn, hphase] - exact hAlg - -theorem ltPhaseLowerMarginValMin_sound {m c : Nat} - (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hc : c < 160) - (hpn_nonneg : 0 ≤ evalPoly (ltPhaseLowerPNMin c) (m : Int)) - (hcert : 0 ≤ expMarginVal 320 (evalPoly (ltPhaseLowerPNMin c) (m : Int)) - (evalPoly ltPhaseLowerQD (m : Int)) (evalPoly (posTopXPoly c) (m : Int)) - (((10 ^ 18 : Nat) : Int))) : - PosShiftLtMinPhaseDirectOk 320 m c := by - let PN := evalPoly (ltPhaseLowerPNMin c) (m : Int) - let QD := evalPoly ltPhaseLowerQD (m : Int) - let P := posPhaseNatLt m c + minPosAvail - have hPNnon : 0 ≤ PN := by - simpa [PN] using hpn_nonneg - have hQDpos : 0 < QD := by - simpa [QD] using ltPhaseLowerQD_pos (m := m) h1 h2 - have hPNcast : (((PN.toNat : Nat) : Int)) = PN := - Int.toNat_of_nonneg hPNnon - have hQDcast : (((QD.toNat : Nat) : Int)) = QD := - Int.toNat_of_nonneg (Int.le_of_lt hQDpos) - have hY := eval_posTopXPoly m c - have hsum : sumGE 320 PN.toNat QD.toNat (posTopX c m) (10 ^ 18) := by - refine sumGE_of_expMarginVal - (n := 320) (p := PN.toNat) (q := QD.toNat) - (y := posTopX c m) (w := 10 ^ 18) ?_ - rw [hPNcast, hQDcast, ← hY] - exact hcert - have hqpos : 0 < QD.toNat := by - apply Int.ofNat_lt.mp - rw [hQDcast] - exact hQDpos - have harg : PN.toNat * lnErrQ ≤ P * QD.toNat := by - apply Int.ofNat_le.mp - simp only [Int.natCast_mul, hPNcast, hQDcast] - have hPNle : PN ≤ (P : Int) * evalPoly ltTD (m : Int) := by - change evalPoly (ltPhaseLowerPNMin c) (m : Int) ≤ - ((posPhaseNatLt m c + minPosAvail : Nat) : Int) * evalPoly ltTD (m : Int) - exact ltPhaseLowerPNMin_le_phase_mul_TD (m := m) (c := c) h1 h2 hc - have hlnNon : 0 ≤ (lnErrQ : Int) := by - unfold lnErrQ QS lnErrorBoundDen - decide - have hmul := Int.mul_le_mul_of_nonneg_right hPNle hlnNon - have hQD : - QD = (lnErrQ : Int) * evalPoly ltTD (m : Int) := by - unfold QD ltPhaseLowerQD - rw [evalPoly_polyScale] - rw [hQD] - simpa only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] using hmul - unfold PosShiftLtMinPhaseDirectOk - exact sumGE_arg_mono (q' := QD.toNat) hqpos harg hsum - -structure GePhaseLowerCell where - lo : Nat - hi : Nat - marginWs : List Int - -structure LtPhaseLowerCell where - lo : Nat - hi : Nat - pnWs : List Int - marginWs : List Int - -def gePhaseLowerCellOkB (cell : GePhaseLowerCell) (c : Nat) : Bool := - decide (Sc + 46 ≤ cell.lo) && - decide (cell.lo ≤ cell.hi) && - decide (cell.hi < MHI) && - decide (c < 160) && - shiftedExpMarginCellOkB kB 320 (gePhaseLowerPN c) gePhaseLowerQD - (posTopXPoly c) cell.lo cell.hi (10 ^ 18) cell.marginWs - -def ltPhaseLowerCellOkB (cell : LtPhaseLowerCell) (c : Nat) : Bool := - decide (MLO ≤ cell.lo) && - decide (cell.lo ≤ cell.hi) && - decide (cell.hi + 46 ≤ Sc) && - decide (c < 160) && - checkCoverK kB (ltPhaseLowerPN c) (cell.lo : Int) (cell.hi : Int) cell.pnWs && - shiftedExpMarginCellOkB kB 320 (ltPhaseLowerPN c) ltPhaseLowerQD - (posTopXPoly c) cell.lo cell.hi (10 ^ 18) cell.marginWs - -theorem gePhaseLowerCell_sound {cell : GePhaseLowerCell} {m c : Nat} - (h : gePhaseLowerCellOkB cell c = true) - (hlom : cell.lo ≤ m) (hmhi : m ≤ cell.hi) : - PosShiftGePhaseDirectOk 320 m c := by - unfold gePhaseLowerCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, _hc⟩, hmargin⟩ := h - exact gePhaseLowerMarginVal_sound (by omega : Sc + 46 ≤ m) (by omega : m < MHI) - (shiftedExpMarginCellOkB_sound hmargin hlom hmhi) - -theorem ltPhaseLowerCell_sound {cell : LtPhaseLowerCell} {m c : Nat} - (h : ltPhaseLowerCellOkB cell c = true) - (hlom : cell.lo ≤ m) (hmhi : m ≤ cell.hi) : - PosShiftLtPhaseDirectOk 320 m c := by - unfold ltPhaseLowerCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, hc⟩, hpn⟩, hmargin⟩ := h - exact ltPhaseLowerMarginVal_sound (by omega : MLO ≤ m) (by omega : m + 46 ≤ Sc) hc - (checkCoverK_sound _ _ _ _ _ hpn (m : Int) (by omega) (by omega)) - (shiftedExpMarginCellOkB_sound hmargin hlom hmhi) - -def gePhaseLowerCellListCoverB (c : Nat) : Nat → Nat → List GePhaseLowerCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - gePhaseLowerCellOkB cell c && - gePhaseLowerCellListCoverB c (cell.hi + 1) hi cells - -def ltPhaseLowerCellListCoverB (c : Nat) : Nat → Nat → List LtPhaseLowerCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - ltPhaseLowerCellOkB cell c && - ltPhaseLowerCellListCoverB c (cell.hi + 1) hi cells - -theorem gePhaseLowerCellListCoverB_sound {cells : List GePhaseLowerCell} {c lo hi m : Nat} - (h : gePhaseLowerCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGePhaseDirectOk 320 m c := by - induction cells generalizing lo with - | nil => - unfold gePhaseLowerCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold gePhaseLowerCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact gePhaseLowerCell_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -theorem ltPhaseLowerCellListCoverB_sound {cells : List LtPhaseLowerCell} {c lo hi m : Nat} - (h : ltPhaseLowerCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftLtPhaseDirectOk 320 m c := by - induction cells generalizing lo with - | nil => - unfold ltPhaseLowerCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold ltPhaseLowerCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact ltPhaseLowerCell_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/Core/Residue.lean b/formal/ln/LnProof/LnProof/Error/Core/Residue.lean index 3249c2c00..dbdc3d9bd 100644 --- a/formal/ln/LnProof/LnProof/Error/Core/Residue.lean +++ b/formal/ln/LnProof/LnProof/Error/Core/Residue.lean @@ -5,7 +5,7 @@ import LnProof.Error.Core.CutDefs /-! # Error bound — Residue -`posAccI` / `posResidueGap` / `lnTail` residue algebra and the modular bucket-index helpers. +`posAccI` / `posResidueGap` and the positive-tail floor decomposition. -/ open FormalYul @@ -31,74 +31,6 @@ def posAccI (m c : Nat) : Int := def posResidueGap (m c : Nat) (r : Int) : Int := (r + 1) * twoPow72I - posAccI m c -def posResidueGapThreshold : Int := 86144214621787901969 - -def firstCongruentGE (q r lo : Nat) : Nat := - if lo ≤ r then - r - else - r + ((lo - r + q - 1) / q) * q - -theorem firstCongruentGE_le_of_mod {q r lo h : Nat} - (hq : 0 < q) (hmod : h % q = r) (hlo : lo ≤ h) : - firstCongruentGE q r lo ≤ h := by - unfold firstCongruentGE - let k := h / q - have hdecomp : h = k * q + r := by - have hdm := Nat.div_add_mod h q - rw [hmod] at hdm - simpa [k, Nat.add_comm, Nat.mul_comm] using hdm.symm - by_cases hlr : lo ≤ r - · simp [hlr] - rw [hdecomp] - omega - · simp [hlr] - have hlo' : lo ≤ k * q + r := by - rw [← hdecomp] - exact hlo - have hsub : lo - r ≤ k * q := by omega - have hceil : (lo - r + q - 1) / q ≤ k := by - rw [Nat.div_le_iff_le_mul_add_pred hq] - calc - lo - r + q - 1 = (lo - r) + (q - 1) := by omega - _ ≤ k * q + (q - 1) := Nat.add_le_add_right hsub _ - _ = q * k + (q - 1) := by rw [Nat.mul_comm] - have hmul : ((lo - r + q - 1) / q) * q ≤ k * q := - Nat.mul_le_mul_right q hceil - rw [hdecomp] - omega - -theorem no_congruent_of_first_gt {q r lo hi h : Nat} - (hq : 0 < q) (hfirst : hi < firstCongruentGE q r lo) - (hlo : lo ≤ h) (hhi : h ≤ hi) : - h % q ≠ r := by - intro hmod - have hle := firstCongruentGE_le_of_mod hq hmod hlo - omega - -theorem bucket_index_eq_of_mod_bracket {r : Int} {d rem q : Nat} - (hq : 0 < q) (hrem : rem < q) - (hlo : r * (q : Int) ≤ (d : Int) * (q : Int) + (rem : Int)) - (hhi : (d : Int) * (q : Int) + (rem : Int) < (r + 1) * (q : Int)) : - r = (d : Int) := by - have hq_nonneg : (0 : Int) ≤ (q : Int) := by omega - have hd_le_r : (d : Int) ≤ r := by - by_cases hle : (d : Int) ≤ r - · exact hle - · have hsucc : r + 1 ≤ (d : Int) := by omega - have hmul : (r + 1) * (q : Int) ≤ (d : Int) * (q : Int) := - Int.mul_le_mul_of_nonneg_right hsucc hq_nonneg - omega - have hr_le_d : r ≤ (d : Int) := by - by_cases hle : r ≤ (d : Int) - · exact hle - · have hsucc : (d : Int) + 1 ≤ r := by omega - have hmul : ((d : Int) + 1) * (q : Int) ≤ r * (q : Int) := - Int.mul_le_mul_of_nonneg_right hsucc hq_nonneg - rw [Int.add_mul, Int.one_mul] at hmul - omega - omega - theorem posAccI_nonneg {m c : Nat} (hmlo : MLO ≤ m) (hmhi : m < MHI) (hc : c < 160) : 0 ≤ posAccI m c := by @@ -189,231 +121,6 @@ theorem posResidueGap_bounds {m c : Nat} rw [hpow] at hbr ⊢ omega -theorem posResidueGap_eq_twoPow72_sub_mod {m c : Nat} - (hmlo : MLO ≤ m) (hmhi : m < MHI) (hc : c < 160) : - let r := int256 (lnTail (evmSub 160 c) m) - posResidueGap m c r = - ((twoPow72N - (posAccI m c).toNat % twoPow72N : Nat) : Int) := by - intro r - let q : Nat := twoPow72N - let A : Nat := (posAccI m c).toNat - let d : Nat := A / q - let rem : Nat := A % q - change posResidueGap m c r = ((q - rem : Nat) : Int) - have hq : 0 < q := by - unfold q twoPow72N - decide - have hqI : ((q : Nat) : Int) = twoPow72I := by - unfold q twoPow72N twoPow72I - decide - have hnon : 0 ≤ posAccI m c := posAccI_nonneg hmlo hmhi hc - have hAcast : ((A : Nat) : Int) = posAccI m c := by - unfold A - exact Int.toNat_of_nonneg hnon - have hdm := Nat.div_add_mod A q - have hdm' : A / q * q + A % q = A := by - simpa [Nat.mul_comm] using hdm - have hAeq : (d : Int) * (q : Int) + (rem : Int) = posAccI m c := by - unfold d rem - rw [← Int.natCast_mul, ← Int.natCast_add, hdm', hAcast] - have hrem_lt : rem < q := by - unfold rem - exact Nat.mod_lt A hq - have hbr := lnTail_floor_bracket_pos (m := m) (c := c) hmlo hmhi hc - change r * twoPow72I ≤ posAccI m c ∧ - posAccI m c < (r + 1) * twoPow72I at hbr - have hlo : r * (q : Int) ≤ (d : Int) * (q : Int) + (rem : Int) := by - rw [hAeq, hqI] - exact hbr.1 - have hhi : (d : Int) * (q : Int) + (rem : Int) < (r + 1) * (q : Int) := by - rw [hAeq, hqI] - exact hbr.2 - have hr : r = (d : Int) := - bucket_index_eq_of_mod_bracket (r := r) (d := d) (rem := rem) (q := q) - hq hrem_lt hlo hhi - unfold posResidueGap - rw [hr, ← hqI, ← hAeq] - have hremle : rem ≤ q := Nat.le_of_lt hrem_lt - have hsubcast : ((q - rem : Nat) : Int) = (q : Int) - (rem : Int) := by - omega - rw [hsubcast] - rw [Int.add_mul, Int.one_mul] - omega - -theorem lnTail_eq_of_posAcc_window {lo m c : Nat} - (hlo1 : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m < MHI) (hc : c < 160) - (hdiff : - posAccI m c - posAccI lo c + - posResidueGap m c (int256 (lnTail (evmSub 160 c) m)) ≤ twoPow72I) : - int256 (lnTail (evmSub 160 c) lo) = - int256 (lnTail (evmSub 160 c) m) := by - have hlohi : lo < MHI := by omega - have hbrLo := lnTail_floor_bracket_pos hlo1 hlohi hc - have hbrM := lnTail_floor_bracket_pos (by omega : MLO ≤ m) hmhi hc - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - have hrloLo := hbrLo.1 - have hrloHi := hbrLo.2 - have hrmLo := hbrM.1 - have hrmHi := hbrM.2 - have hx := LnYul.r1_mono hlo1 hlom hmhi - have hacc_mono : posAccI lo c ≤ posAccI m c := by - have hmul := Int.mul_le_mul_of_nonneg_right hx - (by change (0 : Int) ≤ 7450580596923828125; decide) - have h1 := Int.add_le_add_right hmul (ln2kInt c) - have h2 := Int.add_le_add_right h1 lnBiasI - simpa [posAccI, Int.add_assoc] using h2 - have hpow : twoPow72I = (4722366482869645213696 : Int) := by - unfold twoPow72I - decide - rw [hpow] at hdiff hrloLo hrloHi hrmLo hrmHi - unfold posResidueGap at hdiff - change posAccI m c - posAccI lo c + - ((rm + 1) * 4722366482869645213696 - posAccI m c) ≤ - 4722366482869645213696 at hdiff - change rlo * 4722366482869645213696 ≤ posAccI lo c at hrloLo - change posAccI lo c < (rlo + 1) * 4722366482869645213696 at hrloHi - change rm * 4722366482869645213696 ≤ posAccI m c at hrmLo - change posAccI m c < (rm + 1) * 4722366482869645213696 at hrmHi - generalize hQ : (4722366482869645213696 : Int) = Q at hdiff hrloLo hrloHi hrmLo hrmHi - change posAccI m c - posAccI lo c + ((rm + 1) * Q - posAccI m c) ≤ Q at hdiff - change rlo * Q ≤ posAccI lo c at hrloLo - change posAccI lo c < (rlo + 1) * Q at hrloHi - change rm * Q ≤ posAccI m c at hrmLo - change posAccI m c < (rm + 1) * Q at hrmHi - have hdiffQ : - posAccI m c - posAccI lo c + ((rm + 1) * Q - posAccI m c) ≤ Q := by - simpa [hQ] using hdiff - have hQpos : (0 : Int) < Q := by - rw [← hQ] - decide - have hQnonneg : (0 : Int) ≤ Q := by omega - have sub_swap (A B C : Int) : C - B = A - B + (C - A) := by omega - have cancel_bucket {A B Q' : Int} (h : A + Q' - B ≤ Q') : A ≤ B := by omega - have lt_of_le_lt {A B C : Int} (hAB : A ≤ B) (hBC : B < C) : A < C := by omega - have le_lt_false {A B : Int} (hBA : B ≤ A) (hAB : A < B) : False := by omega - have succ_le_of_not_le {A B : Int} (h : ¬ A ≤ B) : B + 1 ≤ A := by omega - have hmlo_for_rm : rm * Q ≤ posAccI lo c := by - have hcollapse : - (rm + 1) * Q - posAccI lo c ≤ Q := by - calc - (rm + 1) * Q - posAccI lo c = - posAccI m c - posAccI lo c + ((rm + 1) * Q - posAccI m c) := by - exact sub_swap (posAccI m c) (posAccI lo c) ((rm + 1) * Q) - _ ≤ Q := hdiffQ - have hsplit : (rm + 1) * Q = rm * Q + Q := by - rw [Int.add_mul, Int.one_mul] - rw [hsplit] at hcollapse - exact cancel_bucket hcollapse - have hmhi_for_rm : posAccI lo c < (rm + 1) * Q := - lt_of_le_lt hacc_mono hrmHi - have hle1 : rlo ≤ rm := by - by_cases hle : rlo ≤ rm - · exact hle - · have hge : rm + 1 ≤ rlo := succ_le_of_not_le hle - have hmul := Int.mul_le_mul_of_nonneg_right hge hQnonneg - have hcontr : (rm + 1) * Q ≤ posAccI lo c := - Int.le_trans hmul hrloLo - exact False.elim (le_lt_false hcontr hmhi_for_rm) - have hle2 : rm ≤ rlo := by - by_cases hle : rm ≤ rlo - · exact hle - · have hge : rlo + 1 ≤ rm := succ_le_of_not_le hle - have hmul := Int.mul_le_mul_of_nonneg_right hge hQnonneg - have hcontr : (rlo + 1) * Q ≤ posAccI lo c := - Int.le_trans hmul hmlo_for_rm - exact False.elim (le_lt_false hcontr hrloHi) - change rlo = rm - exact Int.le_antisymm hle1 hle2 - -theorem posAccI_mono_m {lo m c : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m < MHI) : - posAccI lo c ≤ posAccI m c := by - have hx := LnYul.r1_mono hlo hlom hmhi - have hmul := Int.mul_le_mul_of_nonneg_right hx - (by change (0 : Int) ≤ 7450580596923828125; decide) - unfold posAccI - omega - -theorem lnTail_eq_of_same_posAcc_endpoints {lo hi m c : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m ≤ hi) (hhi : hi < MHI) - (hc : c < 160) - (heq : int256 (lnTail (evmSub 160 c) lo) = - int256 (lnTail (evmSub 160 c) hi)) : - int256 (lnTail (evmSub 160 c) m) = - int256 (lnTail (evmSub 160 c) hi) := by - have hmlo : MLO ≤ m := by omega - have hmhi' : m < MHI := by omega - have hlohi : lo < MHI := by omega - have hbrLo := lnTail_floor_bracket_pos hlo hlohi hc - have hbrM := lnTail_floor_bracket_pos hmlo hmhi' hc - have hbrHi := lnTail_floor_bracket_pos (by omega : MLO ≤ hi) hhi hc - have haccLoM : posAccI lo c ≤ posAccI m c := - posAccI_mono_m hlo hlom hmhi' - have haccMHi : posAccI m c ≤ posAccI hi c := - posAccI_mono_m hmlo hmhi hhi - have hpow : twoPow72I = (4722366482869645213696 : Int) := by - unfold twoPow72I - decide - rw [hpow] at hbrLo hbrM hbrHi - generalize hQ : (4722366482869645213696 : Int) = Q at hbrLo hbrM hbrHi - change int256 (lnTail (evmSub 160 c) lo) * Q ≤ posAccI lo c ∧ - posAccI lo c < (int256 (lnTail (evmSub 160 c) lo) + 1) * Q at hbrLo - change int256 (lnTail (evmSub 160 c) m) * Q ≤ posAccI m c ∧ - posAccI m c < (int256 (lnTail (evmSub 160 c) m) + 1) * Q at hbrM - change int256 (lnTail (evmSub 160 c) hi) * Q ≤ posAccI hi c ∧ - posAccI hi c < (int256 (lnTail (evmSub 160 c) hi) + 1) * Q at hbrHi - rw [← heq] at hbrHi - have hQnonneg : (0 : Int) ≤ Q := by rw [← hQ]; decide - have succ_le_of_not_le {A B : Int} (h : ¬ A ≤ B) : B + 1 ≤ A := by omega - have le_lt_false {A B : Int} (hBA : B ≤ A) (hAB : A < B) : False := by omega - have hm_eq_lo : - int256 (lnTail (evmSub 160 c) m) = - int256 (lnTail (evmSub 160 c) lo) := by - have hm_le_lo : int256 (lnTail (evmSub 160 c) m) ≤ - int256 (lnTail (evmSub 160 c) lo) := by - by_cases hle : int256 (lnTail (evmSub 160 c) m) ≤ - int256 (lnTail (evmSub 160 c) lo) - · exact hle - · have hsucc : int256 (lnTail (evmSub 160 c) lo) + 1 ≤ - int256 (lnTail (evmSub 160 c) m) := succ_le_of_not_le hle - have hmul := Int.mul_le_mul_of_nonneg_right hsucc hQnonneg - have hcontr : (int256 (lnTail (evmSub 160 c) lo) + 1) * Q ≤ - posAccI hi c := - Int.le_trans (Int.le_trans hmul hbrM.1) haccMHi - exact False.elim (le_lt_false hcontr hbrHi.2) - have hlo_le_m : int256 (lnTail (evmSub 160 c) lo) ≤ - int256 (lnTail (evmSub 160 c) m) := by - by_cases hle : int256 (lnTail (evmSub 160 c) lo) ≤ - int256 (lnTail (evmSub 160 c) m) - · exact hle - · have hsucc : int256 (lnTail (evmSub 160 c) m) + 1 ≤ - int256 (lnTail (evmSub 160 c) lo) := succ_le_of_not_le hle - have hmul := Int.mul_le_mul_of_nonneg_right hsucc hQnonneg - have hcontr : (int256 (lnTail (evmSub 160 c) m) + 1) * Q ≤ - posAccI m c := - Int.le_trans (Int.le_trans hmul hbrLo.1) haccLoM - exact False.elim (le_lt_false hcontr hbrM.2) - exact Int.le_antisymm hm_le_lo hlo_le_m - exact Eq.trans hm_eq_lo heq - -theorem posResidueGap_ge_of_same_posAcc_endpoints {lo hi m c : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m ≤ hi) (hhi : hi < MHI) - (hc : c < 160) - (heq : int256 (lnTail (evmSub 160 c) lo) = - int256 (lnTail (evmSub 160 c) hi)) : - posResidueGap hi c (int256 (lnTail (evmSub 160 c) hi)) ≤ - posResidueGap m c (int256 (lnTail (evmSub 160 c) m)) := by - have hmlo : MLO ≤ m := by omega - have htail := - lnTail_eq_of_same_posAcc_endpoints hlo hlom hmhi hhi hc heq - have hacc : posAccI m c ≤ posAccI hi c := - posAccI_mono_m hmlo hmhi hhi - unfold posResidueGap - rw [htail] - have sub_left_antitone {A B C : Int} (h : A ≤ B) : C - B ≤ C - A := by omega - exact sub_left_antitone hacc - theorem lnErrArg_eq_posPhase_gap {m c : Nat} (hmlo : MLO ≤ m) (hmhi : m < MHI) (hc : c < 160) : let r := int256 (lnTail (evmSub 160 c) m) diff --git a/formal/ln/LnProof/LnProof/Error/Core/ResidueCover.lean b/formal/ln/LnProof/LnProof/Error/Core/ResidueCover.lean deleted file mode 100644 index 4db2dbbf1..000000000 --- a/formal/ln/LnProof/LnProof/Error/Core/ResidueCover.lean +++ /dev/null @@ -1,487 +0,0 @@ -import LnProof.Floor.CutEquiv -import LnProof.Error.Cert -import LnProof.Error.Core.CutDefs -import LnProof.Error.Core.Residue - -/-! -# Error bound — ResidueCover - -`PosShift*ResidueOk` predicates, `ResidueCell`, and the decidable residue cell-cover machinery. --/ - -open FormalYul -open FormalYul.Preservation - -set_option maxRecDepth 100000 - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -attribute [local irreducible] lnWadToRayBody - - -def PosShiftResidueOk (m c : Nat) (r : Int) : Prop := - posPhaseI m c * (lnErrorBoundDen : Int) + (lnErrorCoarsePosResidue : Int) ≤ - (r + 1) * twoPow99I * (lnErrorBoundDen : Int) - -def PosShiftGeResidueOk (m c : Nat) (r : Int) : Prop := - posPhaseI m c * (lnErrorBoundDen : Int) + (lnErrorCoarseGePosResidue : Int) ≤ - (r + 1) * twoPow99I * (lnErrorBoundDen : Int) - -def PosShiftResidueGapOk (m c : Nat) (r : Int) : Prop := - (lnErrorCoarsePosResidue : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) - -def PosShiftGeResidueGapOk (m c : Nat) (r : Int) : Prop := - (lnErrorCoarseGePosResidue : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int) - -def PosShiftDirectResidueGapOk (m c : Nat) (r : Int) : Prop := - (lnErrorDirectResidueGap : Int) ≤ posResidueGap m c r - -def residueGapOkB (m c : Nat) (r : Int) : Bool := - decide ((lnErrorCoarsePosResidue : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int)) - -def geResidueGapOkB (m c : Nat) (r : Int) : Bool := - decide ((lnErrorCoarseGePosResidue : Int) ≤ - posResidueGap m c r * twoPow27I * (lnErrorBoundDen : Int)) - -def directResidueGapOkB (m c : Nat) (r : Int) : Bool := - decide ((lnErrorDirectResidueGap : Int) ≤ posResidueGap m c r) - -def directResidueGapModOkB (m c : Nat) : Bool := - decide ((posAccI m c).toNat % twoPow72N ≤ twoPow72N - lnErrorDirectResidueGap) - -theorem PosShiftResidueGapOk.of_bool {m c : Nat} {r : Int} - (h : residueGapOkB m c r = true) : PosShiftResidueGapOk m c r := by - unfold residueGapOkB PosShiftResidueGapOk at * - exact of_decide_eq_true h - -theorem PosShiftGeResidueGapOk.of_bool {m c : Nat} {r : Int} - (h : geResidueGapOkB m c r = true) : PosShiftGeResidueGapOk m c r := by - unfold geResidueGapOkB PosShiftGeResidueGapOk at * - exact of_decide_eq_true h - -theorem PosShiftDirectResidueGapOk.of_bool {m c : Nat} {r : Int} - (h : directResidueGapOkB m c r = true) : PosShiftDirectResidueGapOk m c r := by - unfold directResidueGapOkB PosShiftDirectResidueGapOk at * - exact of_decide_eq_true h - -theorem PosShiftDirectResidueGapOk.of_modB {m c : Nat} - (hmlo : MLO ≤ m) (hmhi : m < MHI) (hc : c < 160) - (h : directResidueGapModOkB m c = true) : - PosShiftDirectResidueGapOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold directResidueGapModOkB at h - have hmod : - (posAccI m c).toNat % twoPow72N ≤ twoPow72N - lnErrorDirectResidueGap := - of_decide_eq_true h - have heq := posResidueGap_eq_twoPow72_sub_mod (m := m) (c := c) hmlo hmhi hc - change posResidueGap m c (int256 (lnTail (evmSub 160 c) m)) = - ((twoPow72N - (posAccI m c).toNat % twoPow72N : Nat) : Int) at heq - unfold PosShiftDirectResidueGapOk - rw [heq] - apply Int.ofNat_le.mpr - have hgap_le_q : lnErrorDirectResidueGap ≤ twoPow72N := by - unfold lnErrorDirectResidueGap twoPow72N - decide - omega - -theorem PosShiftResidueGapOk_of_gap_threshold {m c : Nat} {r : Int} - (hgap : posResidueGapThreshold ≤ posResidueGap m c r) : - PosShiftResidueGapOk m c r := by - have hconst : - (lnErrorCoarsePosResidue : Int) ≤ - posResidueGapThreshold * twoPow27I * (lnErrorBoundDen : Int) := by - unfold lnErrorCoarsePosResidue posResidueGapThreshold twoPow27I lnErrorBoundDen - decide +kernel - have h27 : 0 ≤ twoPow27I := by - change (0 : Int) ≤ 134217728 - decide - have hden : 0 ≤ (lnErrorBoundDen : Int) := by - change (0 : Int) ≤ 1000000000 - decide - have hmul := Int.mul_le_mul_of_nonneg_right hgap h27 - have hmul2 := Int.mul_le_mul_of_nonneg_right hmul hden - unfold PosShiftResidueGapOk - exact Int.le_trans hconst hmul2 - -theorem posResidueGap_lt_threshold_of_not_ok {m c : Nat} {r : Int} - (_hgap_pos : 1 ≤ posResidueGap m c r) - (h : residueGapOkB m c r = false) : - posResidueGap m c r < posResidueGapThreshold := by - unfold residueGapOkB at h - rw [decide_eq_false_iff_not] at h - by_cases hle : posResidueGapThreshold ≤ posResidueGap m c r - · exact False.elim (h (PosShiftResidueGapOk_of_gap_threshold hle)) - · omega - -theorem PosShiftResidueOk_of_gap {m c : Nat} {r : Int} - (hc : c ≤ 160) (hgap : PosShiftResidueGapOk m c r) : - PosShiftResidueOk m c r := by - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - have hVs' : posAccI m c * twoPow27I = posPhaseI m c := by - unfold posAccI posPhaseI - simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs - unfold PosShiftResidueGapOk posResidueGap at hgap - unfold PosShiftResidueOk - rw [← hVs'] - unfold twoPow72I twoPow27I at hgap - unfold twoPow27I twoPow99I - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - rw [hden] at hgap ⊢ - omega - -theorem PosShiftResidueOk_of_gapB {m c : Nat} {r : Int} - (hc : c ≤ 160) (h : residueGapOkB m c r = true) : - PosShiftResidueOk m c r := - PosShiftResidueOk_of_gap hc (PosShiftResidueGapOk.of_bool h) - -theorem PosShiftGeResidueOk_of_gap {m c : Nat} {r : Int} - (hc : c ≤ 160) (hgap : PosShiftGeResidueGapOk m c r) : - PosShiftGeResidueOk m c r := by - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - have hVs' : posAccI m c * twoPow27I = posPhaseI m c := by - unfold posAccI posPhaseI - simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs - unfold PosShiftGeResidueGapOk posResidueGap at hgap - unfold PosShiftGeResidueOk - rw [← hVs'] - unfold twoPow72I twoPow27I at hgap - unfold twoPow27I twoPow99I - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - rw [hden] at hgap ⊢ - omega - -theorem PosShiftGeResidueOk_of_gapB {m c : Nat} {r : Int} - (hc : c ≤ 160) (h : geResidueGapOkB m c r = true) : - PosShiftGeResidueOk m c r := - PosShiftGeResidueOk_of_gap hc (PosShiftGeResidueGapOk.of_bool h) - -structure ResidueCell where - lo : Nat - hi : Nat - -def geResidueCellOkB (lo hi c : Nat) : Bool := - decide (Sc ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - decide (int256 (lnTail (evmSub 160 c) lo) = - int256 (lnTail (evmSub 160 c) hi)) && - geResidueGapOkB hi c (int256 (lnTail (evmSub 160 c) hi)) - -def directResidueCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - decide (int256 (lnTail (evmSub 160 c) lo) = - int256 (lnTail (evmSub 160 c) hi)) && - directResidueGapOkB hi c (int256 (lnTail (evmSub 160 c) hi)) - -def geResidueRunCellOkB (lo hi c : Nat) : Bool := - decide (Sc ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - let rlo := int256 (lnTail (evmSub 160 c) lo) - decide (posAccI hi c < (rlo + 1) * twoPow72I) && - decide ((lnErrorCoarseGePosResidue : Int) ≤ - ((rlo + 1) * twoPow72I - posAccI hi c) * twoPow27I * - (lnErrorBoundDen : Int)) - -def residueRunCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - let rlo := int256 (lnTail (evmSub 160 c) lo) - decide (posAccI hi c < (rlo + 1) * twoPow72I) && - decide ((lnErrorCoarsePosResidue : Int) ≤ - ((rlo + 1) * twoPow72I - posAccI hi c) * twoPow27I * - (lnErrorBoundDen : Int)) - -def directResidueRunCellOkB (lo hi c : Nat) : Bool := - decide (MLO ≤ lo) && - decide (lo ≤ hi) && - decide (hi < MHI) && - decide (c < 160) && - let rlo := int256 (lnTail (evmSub 160 c) lo) - decide (posAccI hi c < (rlo + 1) * twoPow72I) && - decide ((lnErrorDirectResidueGap : Int) ≤ - (rlo + 1) * twoPow72I - posAccI hi c) - -theorem geResidueCellOkB_sound {lo hi m c : Nat} - (h : geResidueCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeResidueOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold geResidueCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨⟨hloSc, _hlohi⟩, hhi⟩, hc⟩, htailEq⟩, hgapHiB⟩ := h - have hloMLO : MLO ≤ lo := by - simp only [Sc, MLO] at hloSc ⊢ - omega - have hgapLe := - posResidueGap_ge_of_same_posAcc_endpoints hloMLO hlom hmhi hhi hc htailEq - have hgapHi := PosShiftGeResidueGapOk.of_bool hgapHiB - have hgapM : - PosShiftGeResidueGapOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold PosShiftGeResidueGapOk at hgapHi ⊢ - have h27 : 0 ≤ twoPow27I := by - change (0 : Int) ≤ 134217728 - decide - have hden : 0 ≤ (lnErrorBoundDen : Int) := by - change (0 : Int) ≤ 1000000000 - decide - have hmul := Int.mul_le_mul_of_nonneg_right hgapLe h27 - have hmul2 := Int.mul_le_mul_of_nonneg_right hmul hden - exact Int.le_trans hgapHi hmul2 - exact PosShiftGeResidueOk_of_gap (by omega : c ≤ 160) hgapM - -theorem directResidueCellOkB_sound {lo hi m c : Nat} - (h : directResidueCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftDirectResidueGapOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold directResidueCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, hc⟩, htailEq⟩, hgapHiB⟩ := h - have hgapLe := - posResidueGap_ge_of_same_posAcc_endpoints hlo hlom hmhi hhi hc htailEq - have hgapHi := PosShiftDirectResidueGapOk.of_bool hgapHiB - unfold PosShiftDirectResidueGapOk at hgapHi ⊢ - exact Int.le_trans hgapHi hgapLe - -theorem lnTail_eq_of_residue_run {lo hi m c : Nat} - (hlo : MLO ≤ lo) (hlom : lo ≤ m) (hmhi : m ≤ hi) (hhi : hi < MHI) - (hc : c < 160) - (hboundary : posAccI hi c < - (int256 (lnTail (evmSub 160 c) lo) + 1) * twoPow72I) : - int256 (lnTail (evmSub 160 c) m) = - int256 (lnTail (evmSub 160 c) lo) := by - have hlohi : lo < MHI := by omega - have hmhi' : m < MHI := by omega - have hbrLo := lnTail_floor_bracket_pos hlo hlohi hc - have hbrM := lnTail_floor_bracket_pos (by omega : MLO ≤ m) hmhi' hc - have haccLoM := posAccI_mono_m (c := c) hlo hlom hmhi' - have haccMHi := posAccI_mono_m (c := c) (by omega : MLO ≤ m) hmhi hhi - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - have hboundaryM : posAccI m c < (rlo + 1) * twoPow72I := by - exact Int.lt_of_le_of_lt haccMHi (by simpa [rlo] using hboundary) - have hrm_le : rm ≤ rlo := by - have hmul : rm * twoPow72I < (rlo + 1) * twoPow72I := - Int.lt_of_le_of_lt hbrM.1 hboundaryM - have hlt : rm < rlo + 1 := - (Int.mul_lt_mul_right (a := twoPow72I) (b := rm) (c := rlo + 1) - (by unfold twoPow72I; decide)).mp hmul - exact Int.le_of_lt_add_one hlt - have hrlo_le : rlo ≤ rm := by - have hmul : rlo * twoPow72I < (rm + 1) * twoPow72I := by - exact Int.lt_of_le_of_lt (Int.le_trans hbrLo.1 haccLoM) hbrM.2 - have hlt : rlo < rm + 1 := - (Int.mul_lt_mul_right (a := twoPow72I) (b := rlo) (c := rm + 1) - (by unfold twoPow72I; decide)).mp hmul - exact Int.le_of_lt_add_one hlt - exact Int.le_antisymm hrm_le hrlo_le - -theorem geResidueRunCellOkB_sound {lo hi m c : Nat} - (h : geResidueRunCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeResidueOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold geResidueRunCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hloSc, _hlohi⟩, hhi⟩, hc⟩, hrun⟩ := h - obtain ⟨hboundary, hgapHi⟩ := hrun - have hlo : MLO ≤ lo := by - simp only [Sc, MLO] at hloSc ⊢ - omega - have htail := lnTail_eq_of_residue_run hlo hlom hmhi hhi hc hboundary - have hmhi' : m < MHI := by omega - have haccMHi := posAccI_mono_m (c := c) (by omega : MLO ≤ m) hmhi hhi - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - have hgapLe : - (rlo + 1) * twoPow72I - posAccI hi c ≤ - (rm + 1) * twoPow72I - posAccI m c := by - rw [show rm = rlo by simpa [rm, rlo] using htail] - exact Int.sub_le_sub_left haccMHi ((rlo + 1) * twoPow72I) - have h27 : 0 ≤ twoPow27I := by - unfold twoPow27I - decide - have hden : 0 ≤ (lnErrorBoundDen : Int) := by - change (0 : Int) ≤ 1000000000 - decide - have hscaled1 : - ((rlo + 1) * twoPow72I - posAccI hi c) * twoPow27I ≤ - ((rm + 1) * twoPow72I - posAccI m c) * twoPow27I := - Int.mul_le_mul_of_nonneg_right hgapLe h27 - have hscaled2 : - ((rlo + 1) * twoPow72I - posAccI hi c) * twoPow27I * - (lnErrorBoundDen : Int) ≤ - ((rm + 1) * twoPow72I - posAccI m c) * twoPow27I * - (lnErrorBoundDen : Int) := - Int.mul_le_mul_of_nonneg_right hscaled1 hden - have hgapM : PosShiftGeResidueGapOk m c rm := by - unfold PosShiftGeResidueGapOk posResidueGap - exact Int.le_trans hgapHi hscaled2 - simpa [rm] using PosShiftGeResidueOk_of_gap (by omega : c ≤ 160) hgapM - -theorem residueRunCellOkB_sound {lo hi m c : Nat} - (h : residueRunCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftResidueOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold residueRunCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, hc⟩, hrun⟩ := h - obtain ⟨hboundary, hgapHi⟩ := hrun - have htail := lnTail_eq_of_residue_run hlo hlom hmhi hhi hc hboundary - have haccMHi := posAccI_mono_m (c := c) (by omega : MLO ≤ m) hmhi hhi - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - have hgapLe : - (rlo + 1) * twoPow72I - posAccI hi c ≤ - (rm + 1) * twoPow72I - posAccI m c := by - rw [show rm = rlo by simpa [rm, rlo] using htail] - exact Int.sub_le_sub_left haccMHi ((rlo + 1) * twoPow72I) - have h27 : 0 ≤ twoPow27I := by - unfold twoPow27I - decide - have hden : 0 ≤ (lnErrorBoundDen : Int) := by - change (0 : Int) ≤ 1000000000 - decide - have hscaled1 : - ((rlo + 1) * twoPow72I - posAccI hi c) * twoPow27I ≤ - ((rm + 1) * twoPow72I - posAccI m c) * twoPow27I := - Int.mul_le_mul_of_nonneg_right hgapLe h27 - have hscaled2 : - ((rlo + 1) * twoPow72I - posAccI hi c) * twoPow27I * - (lnErrorBoundDen : Int) ≤ - ((rm + 1) * twoPow72I - posAccI m c) * twoPow27I * - (lnErrorBoundDen : Int) := - Int.mul_le_mul_of_nonneg_right hscaled1 hden - have hgapM : PosShiftResidueGapOk m c rm := by - unfold PosShiftResidueGapOk posResidueGap - exact Int.le_trans hgapHi hscaled2 - simpa [rm] using PosShiftResidueOk_of_gap (by omega : c ≤ 160) hgapM - -theorem directResidueRunCellOkB_sound {lo hi m c : Nat} - (h : directResidueRunCellOkB lo hi c = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftDirectResidueGapOk m c (int256 (lnTail (evmSub 160 c) m)) := by - unfold directResidueRunCellOkB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, hhi⟩, hc⟩, hrun⟩ := h - obtain ⟨hboundary, hgapHi⟩ := hrun - have htail := lnTail_eq_of_residue_run hlo hlom hmhi hhi hc hboundary - have haccMHi := posAccI_mono_m (c := c) (by omega : MLO ≤ m) hmhi hhi - let rlo := int256 (lnTail (evmSub 160 c) lo) - let rm := int256 (lnTail (evmSub 160 c) m) - have hgapLe : - (rlo + 1) * twoPow72I - posAccI hi c ≤ - (rm + 1) * twoPow72I - posAccI m c := by - rw [show rm = rlo by simpa [rm, rlo] using htail] - exact Int.sub_le_sub_left haccMHi ((rlo + 1) * twoPow72I) - have hgapM : PosShiftDirectResidueGapOk m c rm := by - unfold PosShiftDirectResidueGapOk posResidueGap - exact Int.le_trans hgapHi hgapLe - simpa [rm] using hgapM - -def geResidueCellListCoverB (c : Nat) : Nat → Nat → List ResidueCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - geResidueCellOkB cell.lo cell.hi c && - geResidueCellListCoverB c (cell.hi + 1) hi cells - -theorem geResidueCellListCoverB_sound {cells : List ResidueCell} {c lo hi m : Nat} - (h : geResidueCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftGeResidueOk m c (int256 (lnTail (evmSub 160 c) m)) := by - induction cells generalizing lo with - | nil => - unfold geResidueCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold geResidueCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact geResidueCellOkB_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -def directResidueCellListCoverB (c : Nat) : Nat → Nat → List ResidueCell → Bool - | lo, hi, [] => decide (hi < lo) - | lo, hi, cell :: cells => - decide (cell.lo = lo) && - decide (lo ≤ cell.hi) && - decide (cell.hi ≤ hi) && - directResidueCellOkB cell.lo cell.hi c && - directResidueCellListCoverB c (cell.hi + 1) hi cells - -theorem directResidueCellListCoverB_sound {cells : List ResidueCell} {c lo hi m : Nat} - (h : directResidueCellListCoverB c lo hi cells = true) - (hlom : lo ≤ m) (hmhi : m ≤ hi) : - PosShiftDirectResidueGapOk m c (int256 (lnTail (evmSub 160 c) m)) := by - induction cells generalizing lo with - | nil => - unfold directResidueCellListCoverB at h - have hlt : hi < lo := of_decide_eq_true h - omega - | cons cell cells ih => - unfold directResidueCellListCoverB at h - simp only [Bool.and_eq_true, decide_eq_true_eq] at h - obtain ⟨⟨⟨⟨hlo, _hlohi⟩, _hhihi⟩, hok⟩, hrest⟩ := h - by_cases hmcell : m ≤ cell.hi - · exact directResidueCellOkB_sound hok (by omega) hmcell - · exact ih hrest (by omega) - -theorem pos_direct_residue_arg_le_int {A r : Int} - (hres : A * (lnErrorBoundDen : Int) + - (lnErrorDirectResidueGap : Int) * twoPow27I * (lnErrorBoundDen : Int) ≤ - (r + 1) * twoPow99I * (lnErrorBoundDen : Int)) : - A * (lnErrorBoundDen : Int) + (lnErrorExtraNum : Int) * twoPow99I + - (lnErrorDirectResidueGap : Int) * twoPow27I * (lnErrorBoundDen : Int) ≤ - (r * (lnErrorBoundDen : Int) + (lnErrorBoundNum : Int)) * twoPow99I := by - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - have hnum : ((lnErrorBoundNum : Nat) : Int) = (1698600000 : Int) := by - unfold lnErrorBoundNum - rfl - have hextra : ((lnErrorExtraNum : Nat) : Int) = (698600000 : Int) := by - unfold lnErrorExtraNum lnErrorBoundNum lnErrorBoundDen - decide +kernel - rw [hden] at hres - rw [hden, hnum, hextra] - unfold twoPow99I twoPow27I at hres ⊢ - omega - -theorem direct_residue_phase_bound {m c : Nat} {r : Int} - (hc : c ≤ 160) (hgap : PosShiftDirectResidueGapOk m c r) : - posPhaseI m c * (lnErrorBoundDen : Int) + - (lnErrorDirectResidueGap : Int) * twoPow27I * (lnErrorBoundDen : Int) ≤ - (r + 1) * twoPow99I * (lnErrorBoundDen : Int) := by - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - have hVs' : posAccI m c * twoPow27I = posPhaseI m c := by - unfold posAccI posPhaseI - simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs - unfold PosShiftDirectResidueGapOk posResidueGap at hgap - rw [← hVs'] - unfold twoPow27I twoPow99I - unfold twoPow72I at hgap - have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by - unfold lnErrorBoundDen - rfl - rw [hden] - omega - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/FactoredCap.lean b/formal/ln/LnProof/LnProof/Error/FactoredCap.lean deleted file mode 100644 index bdb543dbe..000000000 --- a/formal/ln/LnProof/LnProof/Error/FactoredCap.lean +++ /dev/null @@ -1,245 +0,0 @@ -import LnProof.Error.Core -import LnProof.Cert.BiasCapNum - -open FormalYul -open FormalYul.Preservation - -/-! -# Factored-octave cap primitive - -The positive-shift phase-direct proof shows `e^(phase) ≥ posTopX` with a -single `sumGE 320` because it keeps the *full* log argument (~110). This file -factors that exponential into - - octave (`cap2L^(160-c)`) · bias (`capBL`) · x1/H part · first-order extra, - -so the only piece that still needs a per-`m` exponential bound is the small -`x1 = H·10^27` residual (argument in `[0, ln2/2]` on the ge branch). That -residual is captured tightly by a low-degree cap rather than the linear -`x1capGeLoF`, which lets the global certificate avoid the intractable -degree-320 Kronecker cells. - -`lo_ge_pos_factored` is the soundness bridge: it is exactly the -`lo_ge_pos_budget_exact` assembly with the x1 and bias caps taken as parameters, -so any sharper `capLB` for the x1 part drops straight in. --/ - -namespace LnFloorCert - -open LnYul LnFloor Common.Exp Common.Poly - -set_option maxRecDepth 100000 - -/-- Sharpened bias cap. `capBL` keeps only ~31 digits (slop `3404`, i.e. -`3.4e-28` relative), which is too loose for the tight cells the factored cap -needs. Since the bias argument is constant, a `130`-term lower sum pins it to -`~1e-39` relative with a `10^60` denominator. -/ -theorem capBLtight : - capLB (BIASc * 2 ^ 27) QS - biasCapNum - (10 ^ 18 * 10 ^ 42) := - ⟨130, by decide⟩ - -/-- Factored ge positive-shift cut. Given a cap for the x1/H part and the bias -(both over denominator `QS`), and the closing arithmetic inequality, produce the -upper-cut `capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen`. -/ -theorem lo_ge_pos_factored {m c x : Nat} {r : Int} - {x1num x1den biasnum biasden : Nat} - (hphase : posPhaseNatGe m c ≤ lnErrArg r) - (hx1den : 0 < x1den) (hbiasden : 0 < biasden) - (hx1 : capLB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS - x1num x1den) - (hbias : capLB (BIASc * 2 ^ 27) QS biasnum biasden) - (hclose : - wadRayNum x * (((x1den * (10 ^ 40) ^ (160 - c)) * biasden) * lnErrQ) ≤ - (((x1num * (2 * (10 ^ 40 - 1)) ^ (160 - c)) * biasnum) * - (lnErrQ + posAvailGe m c r)) * wadRayStrictDen) : - capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by - have cap1 := capLB_lift_right (den := lnErrorBoundDen) QS_pos hx1 - have cap2LQ := capLB_lift_right (den := lnErrorBoundDen) QS_pos cap2L - have cap2 := capLB_pow cap2LQ (160 - c) - have capB := capLB_lift_right (den := lnErrorBoundDen) QS_pos hbias - have cap12 := capLB_mul cap1 cap2 - have cap123 := capLB_mul cap12 capB - change capLB (posPhaseNatGe m c) lnErrQ - ((x1num * (2 * (10 ^ 40 - 1)) ^ (160 - c)) * biasnum) - ((x1den * (10 ^ 40) ^ (160 - c)) * biasden) at cap123 - have capE := capLB_first_order_self (posAvailGe m c r) lnErrQ - have capR0 := capLB_mul cap123 capE - have hsum : posPhaseNatGe m c + posAvailGe m c r = lnErrArg r := by - unfold posAvailGe - exact Nat.add_sub_of_le hphase - rw [hsum] at capR0 - refine capLB_weaken ?_ capR0 ?_ - · have hlnErrQ : 0 < lnErrQ := Nat.mul_pos QS_pos (by decide) - exact Nat.mul_pos (Nat.mul_pos (Nat.mul_pos hx1den - (Nat.pow_pos (by decide : (0 : Nat) < 10 ^ 40))) hbiasden) hlnErrQ - · exact hclose - -/-- The `n`-term lower partial sum is a valid lower cap for its own argument. -Stated abstractly so the kernel never reduces `expNum n`. -/ -theorem capLB_expNum_self (n p q : Nat) : - capLB p q (expNum n p q) (fact n * q ^ n) := - ⟨n, Nat.le_refl _⟩ - -/-- Degree-22 lower cap for the x1/H part of the ge phase, transported along the -floor bracket `geTN2b·2⁹⁹ ≤ H·geTD2b`. No Kronecker: a trivial degree-22 base -cap at argument `geTN2b/geTD2b` is moved up to the true argument `H·10²⁷/QS` by -`capLB_arg`. c-independent and bias-independent. -/ -theorem ge_x1_cap_d22 {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - capLB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS - (expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat) - (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) := by - have hTD : 0 < evalPoly geTD2b (m : Int) := geTD2b_pos_of_outer h1 h2 - have hTN : 0 ≤ evalPoly geTN2b (m : Int) := geTN2b_nonneg_of_outer h1 h2 - have hH : 0 ≤ int256 (x1W (zWord m)) := x1_nonneg_ge h1 h2 - have hbr := bracket_ge_lo h1 h2 - -- generalize the degree-12 Horner evaluations to opaque integers so no tactic - -- expands `evalPoly` (which overflows the kernel) - generalize hTNe : evalPoly geTN2b (m : Int) = TN at hbr hTN ⊢ - generalize hTDe : evalPoly geTD2b (m : Int) = TD at hbr hTD ⊢ - generalize hHe : int256 (x1W (zWord m)) = H at hbr hH ⊢ - have hTDnat : 0 < TD.toNat := by rw [Int.lt_toNat]; simpa using hTD - refine capLB_arg (q' := TD.toNat) hTDnat ?_ (capLB_expNum_self 22 _ _) - -- Nat bracket TN.toNat·2⁹⁹ ≤ H.toNat·TD.toNat from the Int bracket hbr - have hbrN : TN.toNat * 2 ^ 99 ≤ H.toNat * TD.toNat := by - refine Int.ofNat_le.mp ?_ - simp only [Int.natCast_mul, Int.natCast_pow, Int.toNat_of_nonneg hTN, - Int.toNat_of_nonneg hH, Int.toNat_of_nonneg (Int.le_of_lt hTD)] - simpa using hbr - -- goal (Nat): TN.toNat * QS ≤ (H.toNat * 10²⁷) * TD.toNat, with QS = 10²⁷·2⁹⁹ - have hQSe : QS = 1000000000000000000000000000 * 2 ^ 99 := by decide - calc TN.toNat * QS - = TN.toNat * 2 ^ 99 * 1000000000000000000000000000 := by - rw [hQSe]; simp only [Nat.mul_assoc, Nat.mul_comm] - _ ≤ H.toNat * TD.toNat * 1000000000000000000000000000 := Nat.mul_le_mul_right _ hbrN - _ = H.toNat * 1000000000000000000000000000 * TD.toNat := by - simp only [Nat.mul_assoc, Nat.mul_comm] - -/-- Composition: the ge positive-shift upper cut from the smooth-phase floor -bound and the closing budget inequality `hclose` with the degree-22 x1 cap and -the sharp bias. The octave power on each side cancels, leaving a per-`m` -inequality up to the per-`k` octave-looseness factor. -/ -theorem ge_pos_cut_factored {m c x : Nat} {r : Int} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) - (hphase : posPhaseNatGe m c ≤ lnErrArg r) - (hclose : - wadRayNum x * - ((((fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 40) ^ (160 - c)) * (10 ^ 18 * 10 ^ 42)) * lnErrQ) ≤ - (((expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - (2 * (10 ^ 40 - 1)) ^ (160 - c)) * - biasCapNum) * - (lnErrQ + posAvailGe m c r)) * wadRayStrictDen) : - capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by - have hTDnat : 0 < (evalPoly geTD2b (m : Int)).toNat := by - rw [Int.lt_toNat]; simpa using geTD2b_pos_of_outer h1 h2 - exact lo_ge_pos_factored hphase - (Nat.mul_pos (fact_pos 22) (Nat.pow_pos hTDnat)) - (by decide : 0 < 10 ^ 18 * 10 ^ 42) - (ge_x1_cap_d22 h1 h2) capBLtight hclose - -/-- Octave ratio bound, batched as one kernel `decide` over `k ∈ [0,159]`. -`(10^40/(10^40-1))^k` peaks at `k=159` below the tight rational `(10^40+160)/10^40` -(looseness `~10^-40`), so the cell polynomial keeps small coefficients instead of -carrying the `~2^21000` octave power. -/ -theorem octaveGeBound_all : - (List.range 160).all - (fun k => decide (10 ^ 40 * (10 ^ 40) ^ k ≤ (10 ^ 40 + 160) * (10 ^ 40 - 1) ^ k)) - = true := by decide +kernel - -theorem octaveGeBound {k : Nat} (hk : k ≤ 159) : - 10 ^ 40 * (10 ^ 40) ^ k ≤ (10 ^ 40 + 160) * (10 ^ 40 - 1) ^ k := by - have h := List.all_eq_true.mp octaveGeBound_all k (List.mem_range.mpr (by omega)) - simp only [decide_eq_true_eq] at h - exact h - -/-- C-independent reduction of `ge_pos_cut_factored`'s `hclose`. - -The closing inequality factors as `octave · (x1/H cell) · bias · first-order`. -Three monotone substitutions collapse all `c`/`r`/`x` dependence into a single -degree-221 polynomial inequality in `m`: - -* `minPosAvail ≤ posAvailGe m c r` (from - `posPhaseNatGe_minAvail_le_lnErrArg`) lowers `(lnErrQ + posAvailGe)` to the - constant `(lnErrQ + minPosAvail)`. -* `x ≤ posTopX c m ≤ (m+1)·2^(160-c)` pulls the only `x` factor into - `(m+1)·2^(160-c)`. -* `A·(10^40)^k ≤ B·(10^40-1)^k` follows from the small-coefficient inequality - `A·(10^40+160) ≤ B·10^40` via `octaveGeBound`, keeping the cell polynomial at - floor-proof coefficient scale. - -The remaining hypothesis is the c-independent inequality checked by the -degree-221 Kronecker cell cover. -/ -theorem ge_pos_cut_reduced {m c x : Nat} {r : Int} - (h1 : Sc + 46 ≤ m) (h2 : m < MHI) (hc1 : 1 ≤ c) (hc : c < 160) - (hmin : posPhaseNatGe m c + minPosAvail ≤ lnErrArg r) - (hxtop : x ≤ posTopX c m) - (hReduced : - ((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * (10 ^ 40 + 160) ≤ - (expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - biasCapNum * - (lnErrQ + minPosAvail) * wadRayStrictDen) * 10 ^ 40) : - capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen := by - have hphase : posPhaseNatGe m c ≤ lnErrArg r := Nat.le_trans (Nat.le_add_right _ _) hmin - have hmineq : minPosAvail ≤ posAvailGe m c r := by - unfold posAvailGe; omega - have hoct := octaveGeBound (k := 160 - c) (by omega) - -- Chain the octave bound with the reduced inequality, then cancel the common `10^40`. - have keyineq : - ((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * (10 ^ 40) ^ (160 - c) ≤ - (expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - biasCapNum * - (lnErrQ + minPosAvail) * wadRayStrictDen) * ((10 ^ 40 - 1) ^ (160 - c)) := by - refine Nat.le_of_mul_le_mul_right ?_ (show 0 < 10 ^ 40 by decide) - calc ((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * (10 ^ 40) ^ (160 - c) * 10 ^ 40 - = ((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * (10 ^ 40 * (10 ^ 40) ^ (160 - c)) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - _ ≤ ((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * - ((10 ^ 40 + 160) * (10 ^ 40 - 1) ^ (160 - c)) := Nat.mul_le_mul_left _ hoct - _ = ((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * (10 ^ 40 + 160) * (10 ^ 40 - 1) ^ (160 - c) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - _ ≤ (expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - biasCapNum * - (lnErrQ + minPosAvail) * wadRayStrictDen) * 10 ^ 40 * - (10 ^ 40 - 1) ^ (160 - c) := Nat.mul_le_mul_right _ hReduced - _ = (expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - biasCapNum * - (lnErrQ + minPosAvail) * wadRayStrictDen) * ((10 ^ 40 - 1) ^ (160 - c)) * - 10 ^ 40 := by simp only [Nat.mul_comm, Nat.mul_left_comm] - -- now assemble `hclose` - refine ge_pos_cut_factored h1 h2 hphase ?_ - -- lower the RHS phase-availability to the constant `minPosAvail` - refine Nat.le_trans ?_ - (Nat.mul_le_mul (Nat.mul_le_mul (Nat.le_refl _) (Nat.add_le_add_left hmineq lnErrQ)) - (Nat.le_refl wadRayStrictDen)) - -- bound `wadRayNum x` by the window top - have hxw : wadRayNum x ≤ (m + 1) * 2 ^ (160 - c) * 10 ^ 31 := by - unfold wadRayNum - exact Nat.mul_le_mul_right _ - (Nat.le_trans (by unfold posTopX at hxtop; exact hxtop) (Nat.sub_le _ _)) - refine Nat.le_trans (Nat.mul_le_mul hxw (Nat.le_refl _)) ?_ - -- pure AC + `(2·y)^k = 2^k·y^k`, closed by `keyineq` scaled by `2^(160-c)` - calc (m + 1) * 2 ^ (160 - c) * 10 ^ 31 * - ((((fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * (10 ^ 40) ^ (160 - c)) * - (10 ^ 18 * 10 ^ 42)) * lnErrQ) - = (((m + 1) * 10 ^ 31 * (fact 22 * (evalPoly geTD2b (m : Int)).toNat ^ 22) * - (10 ^ 18 * 10 ^ 42) * lnErrQ) * (10 ^ 40) ^ (160 - c)) * 2 ^ (160 - c) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - _ ≤ ((expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - biasCapNum * - (lnErrQ + minPosAvail) * wadRayStrictDen) * ((10 ^ 40 - 1) ^ (160 - c))) * - 2 ^ (160 - c) := Nat.mul_le_mul_right _ keyineq - _ = (((expNum 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat * - (2 * (10 ^ 40 - 1)) ^ (160 - c)) * - biasCapNum) * - (lnErrQ + minPosAvail)) * wadRayStrictDen := by - simp only [Nat.mul_pow, Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/GeBridge.lean b/formal/ln/LnProof/LnProof/Error/GeBridge.lean deleted file mode 100644 index a51291044..000000000 --- a/formal/ln/LnProof/LnProof/Error/GeBridge.lean +++ /dev/null @@ -1,118 +0,0 @@ -import LnProof.Cert.ErrCertGe -import LnProof.Floor.CertGeLo -import LnProof.Error.FactoredCap - -/-! -# Bridge from the ge error cell cover to the `sumGE` inequality - -`errGe_nonnegOn` proves `0 ≤ evalPoly certErrGeLit m` over the ge domain. Here we -identify the literal cert with the symbolic margin -`certErrGe = expMarginPoly 22 geTN2b geTD2b (errGeK·(m+1)) errGeW` -(an `evalPoly_ext` identity, exactly as `geLo_eval_eq`), and feed the existing -`sumGE_of_expMarginPoly` to obtain the `sumGE`-shaped budget inequality that -`ge_pos_cut_reduced` consumes. - -The constants are the octave-extracted cell parameters at -`lnErrorBoundNum = 1692115493`: -`errGeK = 10^31·(10^18·10^42)·lnErrQ·(10^40+160)`, -`errGeW = BIASCAPNUM·(lnErrQ+minPosAvail)·wadRayStrictDen·10^40`. --/ - -namespace LnFloorCert - -open LnYul Common.Poly Common.Exp - -set_option maxRecDepth 100000 - -def errGeK : Int := - 63382530011411470074835160268800000001014120480182583521197362564300800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - -/-- `errGeW = BIASCAPNUM · (lnErrQ + minPosAvailGe) · wadRayStrictDen · 10^40`, -where `minPosAvailGe = 692115493·2^99 + 2^27·10^9` is the GE-internal bound -(1.692115493 ulp) used by the ge cells, tighter than the -published bound, so the ge branch only tracks the bias here. -/ -def errGeW : Nat := - biasCapNum * - (lnErrQ + (692115493 * 2 ^ 99 + 2 ^ 27 * 10 ^ 9)) * wadRayStrictDen * 10 ^ 40 - -def certErrGe : List Int := - expMarginPoly 22 geTN2b geTD2b (polyScale errGeK [1, 1]) errGeW - -theorem errGe_eval_eq : ∀ x : Int, evalPoly certErrGe x = evalPoly certErrGeLit x := by - refine evalPoly_ext (B := kB) certErrGe certErrGeLit ?_ ?_ ?_ - · -- polyL1 bound on the symbolic margin, via the ℓ1 homomorphism lemmas on the - -- degree-12 literal bases; the full degree-221 poly is never reduced. - show polyL1 certErrGe * 2 < 2 ^ kB - have hadd := polyL1_polyAdd - (polyScale errGeW (expPolyNum geTN2bLit geTD2bLit 22)) - (polyNeg (polyScale (fact 22 : Int) - (polyMul (polyScale errGeK [1, 1]) (polyPow geTD2bLit 22)))) - have hneg := polyL1_polyNeg - (polyScale (fact 22 : Int) - (polyMul (polyScale errGeK [1, 1]) (polyPow geTD2bLit 22))) - have hA := polyL1_polyScale errGeW (expPolyNum geTN2bLit geTD2bLit 22) - have hAe := polyL1_expPolyNum geTN2bLit geTD2bLit 22 - have hA2 : (errGeW : Int).natAbs * polyL1 (expPolyNum geTN2bLit geTD2bLit 22) ≤ - (errGeW : Int).natAbs * expNum 22 (polyL1 geTN2bLit) (polyL1 geTD2bLit) := - Nat.mul_le_mul_left _ hAe - have hB := polyL1_polyScale (fact 22 : Int) - (polyMul (polyScale errGeK [1, 1]) (polyPow geTD2bLit 22)) - have hBm := polyL1_polyMul (polyScale errGeK [1, 1]) (polyPow geTD2bLit 22) - have hBs := polyL1_polyScale errGeK ([1, 1] : List Int) - have hBp := polyL1_polyPow geTD2bLit 22 - have hBm2 : polyL1 (polyScale errGeK [1, 1]) * polyL1 (polyPow geTD2bLit 22) ≤ - errGeK.natAbs * polyL1 ([1, 1] : List Int) * polyL1 geTD2bLit ^ 22 := - Nat.mul_le_mul hBs hBp - have hB2 : (fact 22 : Int).natAbs * - polyL1 (polyMul (polyScale errGeK [1, 1]) (polyPow geTD2bLit 22)) ≤ - (fact 22 : Int).natAbs * - (errGeK.natAbs * polyL1 ([1, 1] : List Int) * polyL1 geTD2bLit ^ 22) := - Nat.mul_le_mul_left _ (Nat.le_trans hBm hBm2) - have hfin : ((errGeW : Int).natAbs * - expNum 22 (polyL1 geTN2bLit) (polyL1 geTD2bLit) + - (fact 22 : Int).natAbs * - (errGeK.natAbs * polyL1 ([1, 1] : List Int) * polyL1 geTD2bLit ^ 22)) * 2 - < 2 ^ kB := by - decide +kernel - have hAfin := Nat.le_trans hA hA2 - have hBfin := Nat.le_trans hB hB2 - rw [hneg] at hadd - exact Nat.lt_of_le_of_lt - (Nat.mul_le_mul_right 2 (Nat.le_trans hadd (Nat.add_le_add hAfin hBfin))) hfin - · show polyL1 certErrGeLit * 2 < 2 ^ kB - decide +kernel - · show evalPoly certErrGe ((2 : Int) ^ kB) = evalPoly certErrGeLit ((2 : Int) ^ kB) - rw [int_two_pow kB] - unfold certErrGe expMarginPoly - rw [geTN2b_eq_lit, geTD2b_eq_lit] - simp only [evalPoly_polySub, evalPoly_polyScale, evalPoly_polyMul, - evalPoly_polyPow, evalPoly_expPolyNum, eval01] - decide +kernel - -theorem certErrGe_nonnegOn : - NonnegOn certErrGe 56022770974786139918731938273 79228162514264337593543950335 := by - intro x hlo hhi - rw [errGe_eval_eq] - exact errGe_nonnegOn x hlo hhi - -/-- The ge cell cover proves the `sumGE`-shaped budget inequality. -/ -theorem errGe_sumGE {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - sumGE 22 (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat - (evalPoly (polyScale errGeK [1, 1]) (m : Int)).toNat errGeW := by - have hge : (56022770974786139918731938273 : Int) ≤ (m : Int) := by - simp only [Sc] at h1; omega - have hle : (m : Int) ≤ 79228162514264337593543950335 := by - simp only [MHI] at h2; omega - have hnn : 0 ≤ evalPoly certErrGe (m : Int) := certErrGe_nonnegOn _ hge hle - have hyp : 0 ≤ evalPoly (polyScale errGeK [1, 1]) (m : Int) := by - rw [evalPoly_polyScale] - refine Int.mul_nonneg (by unfold errGeK; decide) ?_ - have hm : (0 : Int) ≤ (m : Int) := Int.ofNat_nonneg m - simp only [evalPoly, Int.mul_zero, Int.add_zero, Int.mul_one] - omega - exact sumGE_of_expMarginPoly hnn - (Int.toNat_of_nonneg (geTN2b_nonneg_of_outer h1 h2)).symm - (Int.toNat_of_nonneg (Int.le_of_lt (geTD2b_pos_of_outer h1 h2))).symm - (Int.toNat_of_nonneg hyp).symm - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Error/LtBridge.lean b/formal/ln/LnProof/LnProof/Error/LtBridge.lean index 926dc77ec..d7894e736 100644 --- a/formal/ln/LnProof/LnProof/Error/LtBridge.lean +++ b/formal/ln/LnProof/LnProof/Error/LtBridge.lean @@ -7,11 +7,10 @@ import LnProof.Error.LtFactoredCap `errLt_nonnegOn` proves `0 ≤ evalPoly certErrLtLit m` over the lt domain `[2^95, Sc-46]`. Here we identify the literal cert with the symbolic margin -`certErrLt = errLtW·23!·ltTD^23 − errLtK·(m+1)·G` (an `evalPoly_ext` identity, -exactly as `ltLo_eval_eq`), and read off the reduced inequality that -`lt_pos_cut_reduced` consumes directly, with no `sumGE`/`expMarginPoly` -(the curved cap numerator `G` sits on the `(m+1)` side, its denominator -`23!·ltTD^23` on the bias side). +`certErrLt = errLtW·23!·ltTD^23 − errLtK·(m+1)·G` through an `evalPoly_ext` +identity, and read off the reduced inequality consumed by `lt_pos_cut_reduced`. +The curved-cap numerator `G` sits on the `(m+1)` side and its denominator +`23!·ltTD^23` sits on the bias side. The constants are the octave-extracted cell parameters at the active `lnErrorBoundNum = 1698600000`: @@ -101,8 +100,8 @@ theorem certErrLt_nonnegOn : rw [errLt_eval_eq] exact errLt_nonnegOn x hlo hhi -/-- The lt cell cover proves the c-independent error-bound inequality, via the -`evalPoly_ext` identity and the direct `polySub` margin (no `sumGE`). -/ +/-- The lt cell cover proves the c-independent error-bound inequality through +the `evalPoly_ext` identity and the direct polynomial margin. -/ theorem errLt_reduced_ineq {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : ((m + 1) * 10 ^ 31 * (10 ^ 18 * 10 ^ 42) * (expNum 22 (evalPoly ltTN (m : Int)).toNat (evalPoly ltTD (m : Int)).toNat * diff --git a/formal/ln/LnProof/LnProof/Error/LtFactoredCap.lean b/formal/ln/LnProof/LnProof/Error/LtFactoredCap.lean index d233fea27..9e533fd11 100644 --- a/formal/ln/LnProof/LnProof/Error/LtFactoredCap.lean +++ b/formal/ln/LnProof/LnProof/Error/LtFactoredCap.lean @@ -1,15 +1,18 @@ -import LnProof.Error.FactoredCap +import LnProof.Floor.CertLtLo +import LnProof.Error.Core.Residue +import LnProof.Error.Core.Budget +import LnProof.Error.Core.CutDefs +import LnProof.Cert.BiasCapNum open FormalYul open FormalYul.Preservation /-! -# Factored-octave cap primitive for the LT branch (capUB / error-bound direction) +# Factored-octave upper cap -The LT-branch error-bound cut needs an *upper* cap on `e^(|H|·part)` (because -`acc = −K·|H| + …`, so lower-bounding `acc` upper-bounds `|H|`). This is the -`capUB` mirror of `ge_x1_cap_d22`: the tight degree-22 upper cap (with the -`2·tn^23` remainder tail) from `capUB22_of_int`, transported along +The LT-branch error-bound cut needs an upper cap on `e^(|H|·part)` because +`acc = −K·|H| + …`. The tight degree-22 cap, including the `2·tn^23` +remainder tail, is transported along `bracket_lt_up` to the true argument `(−x1W)·10^27 / QS`. -/ @@ -19,8 +22,130 @@ open LnYul LnFloor Common.Exp Common.Poly set_option maxRecDepth 100000 +theorem capBLtight : + capLB (BIASc * 2 ^ 27) QS + biasCapNum + (10 ^ 18 * 10 ^ 42) := + ⟨130, by decide⟩ + +theorem posConstNat_cast (c : Nat) : + ((posConstNat c : Nat) : Int) = + (((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + + lnBiasI * twoPow27I) * (lnErrorBoundDen : Int) := by + have hBc : ((BIASc * twoPow27N : Nat) : Int) = lnBiasI * twoPow27I := by + unfold twoPow27N twoPow27I lnBiasI + decide +kernel + have hLc : (((160 - c) * (LN2c * twoPow27N) : Nat) : Int) = + ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) := by + simp only [Int.natCast_mul] + unfold twoPow27N twoPow27I + rfl + have hden : ((lnErrorBoundDen : Nat) : Int) = (1000000000 : Int) := by + unfold lnErrorBoundDen + rfl + have hN : (((160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) : Nat) : Int) = + (((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I)) * + (1000000000 : Int) := by + rw [show (160 - c) * ((LN2c * twoPow27N) * lnErrorBoundDen) = + ((160 - c) * (LN2c * twoPow27N)) * lnErrorBoundDen by + simp only [Nat.mul_assoc]] + simp only [Int.natCast_mul, hLc, hden] + unfold posConstNat + simp only [Int.natCast_add, Int.natCast_mul, hBc, hN, hden] + rw [Int.add_mul] + +theorem posNegXNat_cast {m : Nat} + (hX : int256 (x1W (zWord m)) ≤ 0) : + ((posNegXNat m : Nat) : Int) = + (-int256 (x1W (zWord m)) * lnPhaseScaleI) * (lnErrorBoundDen : Int) := by + have hXn : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = + -int256 (x1W (zWord m)) := + Int.toNat_of_nonneg (by omega) + have hscale : ((lnPhaseScaleN : Nat) : Int) = lnPhaseScaleI := rfl + unfold posNegXNat + simp only [Int.natCast_mul, hXn, hscale] + +theorem posNegXNat_le_posConstNat {m c : Nat} + (hX : int256 (x1W (zWord m)) ≤ 0) (hc : c ≤ 160) + (hV0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + + lnBiasI) : + posNegXNat m ≤ posConstNat c := by + have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc + have hV0s : 0 ≤ posPhaseI m c := by + have hmul := Int.mul_nonneg hV0 + (by unfold twoPow27I; decide : 0 ≤ twoPow27I) + change 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + + lnBiasI) * twoPow27I at hmul + have hVs' : + (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + + lnBiasI) * twoPow27I = + int256 (x1W (zWord m)) * lnPhaseScaleI + + ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + + lnBiasI * twoPow27I := by + simpa [twoPow27I, lnPhaseScaleI, lnBiasI] using hVs + rw [hVs'] at hmul + simpa [posPhaseI, lnPhaseScaleI, twoPow27I, lnBiasI] using hmul + apply Int.ofNat_le.mp + rw [posNegXNat_cast hX, posConstNat_cast c] + unfold posPhaseI at hV0s + have hmain : + -int256 (x1W (zWord m)) * lnPhaseScaleI ≤ + ((160 - c : Nat) : Int) * ((LN2c : Int) * twoPow27I) + + lnBiasI * twoPow27I := by + rw [show -int256 (x1W (zWord m)) * lnPhaseScaleI = + -(int256 (x1W (zWord m)) * lnPhaseScaleI) by rw [Int.neg_mul]] + generalize int256 (x1W (zWord m)) * lnPhaseScaleI = A at hV0s ⊢ + omega + exact Int.mul_le_mul_of_nonneg_right hmain (Int.natCast_nonneg _) + +theorem capLB_first_order_self (p q : Nat) : + capLB p q (q + p) q := by + refine ⟨1, ?_⟩ + simp only [fact, expNum, Nat.pow_one, Nat.mul_one, Nat.one_mul, Nat.zero_add] + exact Nat.le_refl _ + +theorem capLB_cancel_first_order_budget {arg const neg q C W G V yT wT : Nat} + (hq : 0 < q) + (hconst : capLB const q C W) + (hneg : capUB neg q G V) + (hneg_le : neg ≤ const) + (hphase : const - neg ≤ arg) + (hW : 0 < W) + (hG : 0 < G) + (hbudget : yT * ((W * q) * G) ≤ + ((C * (q + (arg - (const - neg)))) * V) * wT) : + capLB arg q yT wT := by + have capE := capLB_first_order_self (arg - (const - neg)) q + have hsum0 := capLB_mul hconst capE + have hsplit : const + (arg - (const - neg)) = + ((const - neg) + (arg - (const - neg))) + neg := by + calc + const + (arg - (const - neg)) = + (const - neg + neg) + (arg - (const - neg)) := by + rw [Nat.sub_add_cancel hneg_le] + _ = ((const - neg) + (arg - (const - neg))) + neg := by + omega + rw [hsplit] at hsum0 + have capV := capLB_cancel (q := q) hq hsum0 hneg + have harg : (const - neg) + (arg - (const - neg)) = arg := by + exact Nat.add_sub_of_le hphase + rw [harg] at capV + refine capLB_weaken ?_ capV hbudget + exact Nat.mul_pos (Nat.mul_pos hW hq) hG + +theorem octaveBound_all : + (List.range 160).all + (fun k => decide (10 ^ 40 * (10 ^ 40) ^ k ≤ (10 ^ 40 + 160) * (10 ^ 40 - 1) ^ k)) + = true := by decide +kernel + +theorem octaveBound {k : Nat} (hk : k ≤ 159) : + 10 ^ 40 * (10 ^ 40) ^ k ≤ (10 ^ 40 + 160) * (10 ^ 40 - 1) ^ k := by + have h := List.all_eq_true.mp octaveBound_all k (List.mem_range.mpr (by omega)) + simp only [decide_eq_true_eq] at h + exact h + /-- Degree-22 curved upper cap for the LT x1/H part, transported along the floor -bracket `(−X1)·ltTD ≤ ltTN·2^99`. capUB analog of `ge_x1_cap_d22`. -/ +bracket `(−X1)·ltTD ≤ ltTN·2^99`. -/ theorem lt_x1_cap_d22 {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : capUB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS (expNum 22 (evalPoly ltTN (m : Int)).toNat (evalPoly ltTD (m : Int)).toNat * @@ -78,12 +203,10 @@ theorem lt_x1_cap_d22 {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : _ = TN.toNat * QS := by rw [hQSe]; simp only [Nat.mul_assoc, Nat.mul_comm] -/-- Factored LT positive-shift cut (capUB / error-bound direction). capUB analog -of `ge_pos_cut_factored`: the curved degree-22 upper cap `lt_x1_cap_d22` (`G/V`) -and the sharp bias `capBLtight` are cancelled reciprocally via +/-- The curved degree-22 upper cap (`G/V`) and sharp bias cap are cancelled via `capLB_cancel_first_order_budget`, producing the upper-cut -`capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen`. The surviving -`hbudget` is the per-`c` closing inequality; the octave power cancels in +`capLB (lnErrArg r) lnErrQ (wadRayNum x) wadRayStrictDen`. The `hbudget` +hypothesis is the per-`c` closing inequality; the octave power cancels in `lt_pos_cut_reduced`. -/ theorem lt_pos_cut_factored {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (_hc : c < 160) @@ -146,8 +269,8 @@ theorem lt_pos_cut_factored {m c x : Nat} {r : Int} (Nat.le_add_right _ _)) hbudget -/-- C-independent reduction of `lt_pos_cut_factored`'s `hbudget` (capUB mirror of -`ge_pos_cut_reduced`). The same monotone substitutions fold all `c`/`r`/`x` +/-- C-independent reduction of `lt_pos_cut_factored`'s closing budget. The +monotone substitutions fold all `c`/`r`/`x` dependence into a single inequality checked by the Kronecker cell cover. The curved cap numerator `G` sits on the `(m+1)` side and its denominator `V = fact 23 · ltTD^23` on the bias side. -/ @@ -175,7 +298,7 @@ theorem lt_pos_cut_reduced {m c x : Nat} {r : Int} have hphase : posPhaseNatLt m c ≤ lnErrArg r := Nat.le_trans (Nat.le_add_right _ _) hmin have hmineq : minPosAvail ≤ posAvailLt m c r := by unfold posAvailLt; omega - have hoct := octaveGeBound (k := 160 - c) (by omega) + have hoct := octaveBound (k := 160 - c) (by omega) -- Chain the octave bound with the reduced inequality, then cancel the common `10^40`. have keyineq : ((m + 1) * 10 ^ 31 * (10 ^ 18 * 10 ^ 42) * diff --git a/formal/ln/LnProof/LnProof/Floor.lean b/formal/ln/LnProof/LnProof/Floor.lean deleted file mode 100644 index 4b3965ba1..000000000 --- a/formal/ln/LnProof/LnProof/Floor.lean +++ /dev/null @@ -1,11 +0,0 @@ -/-! -# Floor facade - -The proof that the model meets the floor/cut specification. `Spec` is the -top-line floor-cut statement and its discharge (`lnWadToRayBody_floor`); -`CutEquiv` shows the floor spec coincides with the real-free `Spec.Cut` -predicates and that the model satisfies them. The supporting bracket/cap/cert -machinery lives in the rest of the `Floor/` directory. --/ -import LnProof.Floor.Spec -import LnProof.Floor.CutEquiv diff --git a/formal/ln/LnProof/LnProof/Floor/Assembly.lean b/formal/ln/LnProof/LnProof/Floor/Assembly.lean index 263ff9b91..a3beb8506 100644 --- a/formal/ln/LnProof/LnProof/Floor/Assembly.lean +++ b/formal/ln/LnProof/LnProof/Floor/Assembly.lean @@ -7,13 +7,13 @@ open FormalYul open FormalYul.Preservation /-! -# Floor-spec assembly: scale identities +# Strict-margin floor/error-bound cap assembly `lnWadToRayBody_floor_bracket` brackets the body output `r` against the pre-shift accumulator `V = X1·5^27 + ln2k + BIAS` at scale `2^72`. The caps live at -scale `QS = 10^27·2^99`, reached by multiplying `V` by `2^27`. This file -provides the exact decomposition of `V·2^27` into the three cap exponents -on each `clz` side. +scale `QS = 10^27·2^99`, reached by multiplying `V` by `2^27`. The shared +scale identities feed the `FloorSpecB` strict-margin chains for positive and +nonpositive output exponents. -/ namespace LnFloorCert @@ -22,10 +22,10 @@ open LnYul Common.Poly Common.Exp LnFloor /-- `V·2^27` splits into the three cap exponents (positive binade shift). -/ theorem v_scale_pos (X1v : Int) (c : Nat) (hc : c ≤ 160) : (X1v * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = X1v * 1000000000000000000000000000 + ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) + - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by have hl : ln2kInt c = (LN2c : Int) * ((160 - c : Nat) : Int) := by unfold ln2kInt rw [if_pos hc] @@ -40,10 +40,10 @@ theorem v_scale_pos (X1v : Int) (c : Nat) (hc : c ≤ 160) : /-- `V·2^27` splits with the `ln 2` term on the other side (negative shift). -/ theorem v_scale_neg (X1v : Int) (c : Nat) (hc : 160 < c) : (X1v * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 + + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 + ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = X1v * 1000000000000000000000000000 + - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by have hl : ln2kInt c = -((LN2c : Int) * ((c - 160 : Nat) : Int)) := by unfold ln2kInt rw [if_neg (by omega)] @@ -62,115 +62,16 @@ theorem v_scale_neg (X1v : Int) (c : Nat) (hc : 160 < c) : generalize hgL2 : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = L2 at * omega -/-! ## Master chains: caps at the body output -/ +/-! ## Strict-margin chains at the body output -/ -/-- Upper master chain, `m ≥ S` branch, nonnegative binade shift: -`e^(r/10^27) ≤ x/10^18` as a `capUB`, assembled from the `X1` cap, the -`2^k` cap, the bias cap, and the budget. -/ -theorem up_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) - (hc1 : 1 ≤ c) (hc : c ≤ 160) - (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr0 : 0 ≤ r) - (hmx : m * 2 ^ (160 - c) ≤ x) : - capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by - have cap1 := x1capGeUpF h1 h2 - have cap2 := capUB_pow QS_pos cap2U (160 - c) - have cap12 := capUB_mul QS_pos cap1 cap2 - have cap123 := capUB_mul QS_pos cap12 capBU - -- the exponent sum dominates r·2^99 - have hX1 := x1_nonneg_geF h1 h2 - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - have hple : r.toNat * 2 ^ 99 ≤ - (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 := by - have hsc : r * 2 ^ 72 * 2 ^ 27 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := - mul_le_mul_right_nonneg hr (by omega) - rw [hVs] at hsc - have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX1 - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have e99 : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [e99] at hsc - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hsc - generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hsc hLc - generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hVs hX1 cap1 cap2 cap12 cap123 hr h1 h2 hmx hc hc1 - omega - have hmul : r.toNat * 2 ^ 99 * QS ≤ - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27) * QS := - Nat.mul_le_mul_right _ hple - have capR := capUB_arg QS_pos hmul cap123 - -- weaken to the x target through the budget - refine capUB_weaken ?_ capR ?_ - · -- 0 < w - have h1' : 0 < (560227709747861399187319382270000000000000000000000000000000 : Nat) * - ((10 ^ 40 : Nat) ^ (160 - c)) := Nat.mul_pos (by decide) (Nat.pow_pos (by decide)) - exact Nat.mul_pos h1' (by decide) - · -- y·w' ≤ y'·w - have hb := budgetU_le (k := 160 - c) (by omega) - have hbm : m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) ≤ - m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := - Nat.mul_le_mul_left _ (Nat.mul_le_mul_left _ hb) - have hxm : m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) ≤ - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := - Nat.mul_le_mul_right _ hmx - have e1 : m * (10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (Sc * (10 ^ 31 - 3383)) * 10 ^ 18 = - m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e2 : m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e3 : x * (560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31)) = - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e3' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - rw [e3' ((10 ^ 40 : Nat) ^ (160 - c))] - generalize hgY : m * (10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (Sc * (10 ^ 31 - 3383)) * 10 ^ 18 = Y at e1 ⊢ - generalize hg1 : m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) = T1 at hbm e1 - generalize hg2 : m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - T2 at hbm e2 - generalize hg3 : m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - T3 at hxm e2 - generalize hg4 : x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = T4 at hxm e3 - generalize hg5 : x * (560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31)) = W4 at e3 ⊢ - omega - -/-- The lower budget folds from the worst-case mantissa to any `m ≥ 2^103`: -`(m+1)·2^k·(10^40)^k·10^137 ≤ m·(lower-cap product)`. -/ +/-- The lower budget folds from the worst-case mantissa to any `m ≥ 2^95`: +`(m+1)·2^k·(10^40)^k·10^142 ≤ m·(lower-cap product)`. -/ theorem budgetL_fold {m k : Nat} (hm : 2 ^ 95 ≤ m) (hk : k ≤ 159) : (m + 1) * (2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142) ≤ m * ((10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * (10 ^ 31 + 9990) * (10 ^ 31 - 10) * 10 ^ 18) := by have hb := budgetL_le (k := k) hk - -- (m+1)·2^103 ≤ m·(2^103+1) since 2^103 ≤ m + -- (m+1)·2^95 ≤ m·(2^95+1) since 2^95 ≤ m have hcross : (m + 1) * 2 ^ 95 ≤ m * (2 ^ 95 + 1) := by have e1 : (m + 1) * 2 ^ 95 = m * 2 ^ 95 + 2 ^ 95 := by rw [Nat.add_mul, Nat.one_mul] @@ -200,7 +101,7 @@ strictness slack. -/ theorem lo_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hr0 : -1 ≤ r) (hxm : x < (m + 1) * 2 ^ (160 - c)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -216,14 +117,14 @@ theorem lo_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 + 2 ^ 99 ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) rw [hVs] at hsc have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -321,154 +222,13 @@ theorem lo_ge_pos {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (10 ^ 18 * (10 ^ 31 - 10)) = T5 at eR ⊢ omega -/-- Upper master chain, `m ≥ S` branch, negative binade shift -(`c > 160`, exact mantissa `m = x·2^(c-160)`). -/ -theorem up_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) - (hc : 160 < c) (hc2 : c ≤ 255) - (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr0 : 0 ≤ r) - (hmx : m = x * 2 ^ (c - 160)) : - capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by - have cap1 := x1capGeUpF h1 h2 - have cap1B := capUB_mul QS_pos cap1 capBU - have hX1 := x1_nonneg_geF h1 h2 - have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc - -- the Nat split: X1·E + BIAS = pa + j·L with pa ≥ r·2^99 - have hsplit : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27 = - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27 - (c - 160) * (LN2c * 2 ^ 27)) + - (c - 160) * (LN2c * 2 ^ 27) := by - -- j·L ≤ X1·E + BIAS since V ≥ r ≥ 0 - have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX1 - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by - have hm := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) - have h0 : 0 ≤ r * 2 ^ 72 * 2 ^ 27 := - Int.mul_nonneg (Int.mul_nonneg hr0 (by omega)) (by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ - generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R27 at hm h0 - clear cap1 cap1B hX1 hVs hX1n hBc hLc h1 h2 hmx hc hc2 hr hr0 - omega - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 cap1B hr h1 h2 hc hc2 hmx - omega - rw [hsplit] at cap1B - have capV := capUB_cancel QS_pos cap1B (capLB_pow cap2L (c - 160)) - -- bring the exponent down to r·2^99 - have hple : r.toNat * 2 ^ 99 ≤ - (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27 - (c - 160) * (LN2c * 2 ^ 27) := by - have hsc : r * 2 ^ 72 * 2 ^ 27 + ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) ≤ - int256 (x1W (zWord m)) * 1000000000000000000000000000 + - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - have h := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) - generalize hgL : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = L at hVs ⊢ - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs ⊢ - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVs h - omega - have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX1 - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have e99 : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [e99] at hsc - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hsc hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hsc - generalize hgD : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hVs hX1 cap1 cap1B capV hr h1 h2 hc hc2 hmx hsplit - omega - have hmul : r.toNat * 2 ^ 99 * QS ≤ - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27 - (c - 160) * (LN2c * 2 ^ 27)) * QS := - Nat.mul_le_mul_right _ hple - have capR := capUB_arg QS_pos hmul capV - refine capUB_weaken ?_ capR ?_ - · have h1' : 0 < (560227709747861399187319382270000000000000000000000000000000 : Nat) * - (10 ^ 18 * 10 ^ 31) := by decide - exact Nat.mul_pos h1' (Nat.pow_pos (by decide)) - · -- m = x·2^j folding through budgetUn - have hb := budgetUn_le (j := c - 160) (by omega) - have hbf : x * 2 ^ (c - 160) * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 10 ^ 18 * Sc) ≤ - x * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160) * Sc) := by - have h := Nat.mul_le_mul_left (x * Sc) hb - have e1 : x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 2 ^ (c - 160) * 10 ^ 18) = - x * 2 ^ (c - 160) * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 10 ^ 18 * Sc) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e2 : x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) = - x * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160) * Sc) := by - simp only [Nat.mul_assoc, Nat.mul_comm] - rw [e1] at h - rw [e2] at h - exact h - have eY : m * 10000000000000000000000000003382 * (Sc * (10 ^ 31 - 3383)) * - ((10 ^ 40 : Nat) ^ (c - 160)) * 10 ^ 18 = - x * 2 ^ (c - 160) * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 10 ^ 18 * Sc) := by - rw [hmx, show (10000000000000000000000000003382 : Nat) = 10 ^ 31 + 3382 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have eW : x * (560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 18 * 10 ^ 31) * (2 * (10 ^ 40 - 1)) ^ (c - 160)) = - x * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160) * Sc) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have e' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - rw [e' ((2 * (10 ^ 40 - 1)) ^ (c - 160))] - generalize hT1 : m * 10000000000000000000000000003382 * (Sc * (10 ^ 31 - 3383)) * - ((10 ^ 40 : Nat) ^ (c - 160)) * 10 ^ 18 = T1 at eY ⊢ - generalize hT2 : x * 2 ^ (c - 160) * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 10 ^ 18 * Sc) = T2 at eY hbf - generalize hT3 : x * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160) * Sc) = T3 at hbf eW - generalize hT4 : x * (560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 18 * 10 ^ 31) * (2 * (10 ^ 40 - 1)) ^ (c - 160)) = T4 at eW ⊢ - omega - /-- Lower master chain, `m ≥ S` branch, negative binade shift. -/ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) + 116873961749927929127912020551560854268589826112230) (hr0 : -1 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -478,20 +238,20 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hVnn : -(2 ^ 99) ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 := by have h0 : -(2 ^ 72) ≤ r * 2 ^ 72 := by have := mul_le_mul_right_nonneg (show (-1 : Int) ≤ r from hr0) (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : r * 2 ^ 72 = T at this ⊢ omega have hg : -(2 ^ 72) ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ + 116873961749927929127912020551560854268589826112230 = V at hrlo ⊢ omega have := mul_le_mul_right_nonneg hg (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at this ⊢ have e : (-(2 ^ 72) : Int) * 2 ^ 27 = -(2 ^ 99) := by decide omega have hsplit : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + @@ -502,14 +262,14 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVnn hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hVnn hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -526,7 +286,7 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) BIASc * 2 ^ 27 + 2 ^ 99 - (c - 160) * (LN2c * 2 ^ 27) ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by @@ -537,14 +297,14 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs hVnn + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hsc hVs hVnn generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -600,150 +360,13 @@ theorem lo_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) at eR ⊢ omega -/-- Upper master chain, `m < S` branch, nonnegative binade shift. -/ -theorem up_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) - (hc1 : 1 ≤ c) (hc : c ≤ 160) - (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr0 : 0 ≤ r) - (hmx : m * 2 ^ (160 - c) ≤ x) : - capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by - have cap1 := x1capLtUpF h1 h2 - have hsum := capUB_mul QS_pos (capUB_pow QS_pos cap2U (160 - c)) capBU - have hX1 := x1_nonpos_ltF h1 h2 - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - -- split: kL + B = pa + |X1|·E with pa = V·2^27 ≥ 0 - have hsplit : (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 = - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 - - (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) + - (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 := by - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by - have hm := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) - have h0 : 0 ≤ r * 2 ^ 72 * 2 ^ 27 := - Int.mul_nonneg (Int.mul_nonneg hr0 (by omega)) (by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ - generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R27 at hm h0 - clear cap1 hsum hX1 hVs hX1n hBc hLc h1 h2 hmx hc hc1 hr hr0 - omega - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hsum hr h1 h2 hc hc1 hmx - omega - rw [hsplit] at hsum - have capV := capUB_cancel QS_pos hsum cap1 - have hple : r.toNat * 2 ^ 99 ≤ - (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 - - (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 := by - have hsc : r * 2 ^ 72 * 2 ^ 27 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := - mul_le_mul_right_nonneg hr (by omega) - have e99 : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [e99] at hsc - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hsum capV hr h1 h2 hc hc1 hmx hsplit - omega - have hmul : r.toNat * 2 ^ 99 * QS ≤ - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 - - (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) * QS := - Nat.mul_le_mul_right _ hple - have capR := capUB_arg QS_pos hmul capV - refine capUB_weaken ?_ capR ?_ - · have h1' : 0 < (10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31) := - Nat.mul_pos (Nat.pow_pos (by decide)) (by decide) - exact Nat.mul_pos h1' (by decide) - · have hb := budgetU_le (k := 160 - c) (by omega) - have hbm : m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) ≤ - m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := - Nat.mul_le_mul_left _ (Nat.mul_le_mul_left _ hb) - have hxm : m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) ≤ - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := - Nat.mul_le_mul_right _ hmx - have e1 : (2 * (10 ^ 40 + 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3383)) * - (m * 10000000000000000000000000003382) * 10 ^ 18 = - m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) := by - rw [show (10000000000000000000000000003382 : Nat) = 10 ^ 31 + 3382 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e2 : m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e3 : x * ((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31) * - 560227709747861399187319382270000000000000000000000000000000) = - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have e' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - rw [e' ((10 ^ 40 : Nat) ^ (160 - c))] - generalize hgY : (2 * (10 ^ 40 + 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3383)) * - (m * 10000000000000000000000000003382) * 10 ^ 18 = Y at e1 ⊢ - generalize hg1 : m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) = T1 at hbm e1 - generalize hg2 : m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - T2 at hbm e2 - generalize hg3 : m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - T3 at hxm e2 - generalize hg4 : x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = T4 at hxm e3 - generalize hg5 : x * ((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31) * - 560227709747861399187319382270000000000000000000000000000000) = W4 at e3 ⊢ - omega - /-- Lower master chain, `m < S` branch, nonnegative binade shift. -/ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) + 116873961749927929127912020551560854268589826112230) (hr0 : -1 ≤ r) (hxm : x < (m + 1) * 2 ^ (160 - c)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -752,20 +375,20 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc have hVnn : -(2 ^ 99) ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 := by have h0 : -(2 ^ 72) ≤ r * 2 ^ 72 := by have := mul_le_mul_right_nonneg (show (-1 : Int) ≤ r from hr0) (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : r * 2 ^ 72 = T at this ⊢ omega have hg : -(2 ^ 72) ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ + 116873961749927929127912020551560854268589826112230 = V at hrlo ⊢ omega have := mul_le_mul_right_nonneg hg (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at this ⊢ have e : (-(2 ^ 72) : Int) * 2 ^ 27 = -(2 ^ 99) := by decide omega have hsplit : (160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27 + 2 ^ 99 = @@ -775,14 +398,14 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVnn hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hVnn hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -802,7 +425,7 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by @@ -813,14 +436,14 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs hVnn + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hsc hVs hVnn generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -906,146 +529,14 @@ theorem lo_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (10 ^ 18 * (10 ^ 31 - 10)) = T5 at eR ⊢ omega -/-- Upper master chain, `m < S` branch, negative binade shift -(exact mantissa). -/ -theorem up_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) - (hc : 160 < c) (hc2 : c ≤ 255) - (hr : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr0 : 0 ≤ r) - (hmx : m = x * 2 ^ (c - 160)) : - capUB (r.toNat * 2 ^ 99) QS x (10 ^ 18) := by - have cap1 := x1capLtUpF h1 h2 - have hb := capLB_mul cap1 (capLB_pow cap2L (c - 160)) - have hX1 := x1_nonpos_ltF h1 h2 - have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc - -- split: B = pa + (|X1|·E + j·L) with pa = V·2^27 ≥ 0 - have hsplit : BIASc * 2 ^ 27 = - (BIASc * 2 ^ 27 - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27))) + - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27)) := by - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hV0 : 0 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by - have hm := mul_le_mul_right_nonneg hr (show (0 : Int) ≤ 2 ^ 27 by omega) - have h0 : 0 ≤ r * 2 ^ 72 * 2 ^ 27 := - Int.mul_nonneg (Int.mul_nonneg hr0 (by omega)) (by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ - generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R27 at hm h0 - clear cap1 hb hX1 hVs hX1n hBc hLc h1 h2 hmx hc hc2 hr hr0 - omega - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hb hr h1 h2 hc hc2 hmx - omega - have hsumB : capUB (BIASc * 2 ^ 27) QS (Sc * (10 ^ 31 - 3383)) (10 ^ 18 * 10 ^ 31) := - capBU - rw [hsplit] at hsumB - have capV := capUB_cancel QS_pos hsumB hb - have hple : r.toNat * 2 ^ 99 ≤ - BIASc * 2 ^ 27 - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27)) := by - have hsc : r * 2 ^ 72 * 2 ^ 27 ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := - mul_le_mul_right_nonneg hr (by omega) - have e99 : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [e99] at hsc - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hb capV hr h1 h2 hc hc2 hmx hsplit - omega - have hmul : r.toNat * 2 ^ 99 * QS ≤ - (BIASc * 2 ^ 27 - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27))) * QS := - Nat.mul_le_mul_right _ hple - have capR := capUB_arg QS_pos hmul capV - refine capUB_weaken ?_ capR ?_ - · have h1' : 0 < (10 ^ 18 * 10 ^ 31 : Nat) * - (560227709747861399187319382270000000000000000000000000000000 * - (2 * (10 ^ 40 - 1)) ^ (c - 160)) := - Nat.mul_pos (by decide) (Nat.mul_pos (by decide) (Nat.pow_pos (by decide))) - exact h1' - · have hbg := budgetUn_le (j := c - 160) (by omega) - have hbf := Nat.mul_le_mul_left (x * Sc) hbg - have eY : Sc * (10 ^ 31 - 3383) * (m * 10000000000000000000000000003382 * - (10 ^ 40 : Nat) ^ (c - 160)) * 10 ^ 18 = - x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * (10 ^ 40 : Nat) ^ (c - 160) * - 2 ^ (c - 160) * 10 ^ 18) := by - rw [hmx, show (10000000000000000000000000003382 : Nat) = 10 ^ 31 + 3382 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have eW : x * (10 ^ 18 * 10 ^ 31 * - (560227709747861399187319382270000000000000000000000000000000 * - (2 * (10 ^ 40 - 1)) ^ (c - 160))) = - x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have e' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - simp only [Nat.mul_assoc, Nat.mul_left_comm] - rw [e' ((2 * (10 ^ 40 - 1)) ^ (c - 160))] - generalize hT1 : Sc * (10 ^ 31 - 3383) * (m * 10000000000000000000000000003382 * - (10 ^ 40 : Nat) ^ (c - 160)) * 10 ^ 18 = T1 at eY ⊢ - generalize hT2 : x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 2 ^ (c - 160) * 10 ^ 18) = T2 at eY hbf - generalize hT3 : x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) = T3 at hbf eW - generalize hT4 : x * (10 ^ 18 * 10 ^ 31 * - (560227709747861399187319382270000000000000000000000000000000 * - (2 * (10 ^ 40 - 1)) ^ (c - 160))) = T4 at eW ⊢ - omega - /-- Lower master chain, `m < S` branch, negative binade shift (exact mantissa). -/ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) + 116873961749927929127912020551560854268589826112230) (hr0 : -1 ≤ r) (hmx : m = x * 2 ^ (c - 160)) : capLB ((r + 2).toNat * 2 ^ 99) QS (x * 10 ^ 31) (10 ^ 18 * (10 ^ 31 - 10)) := by @@ -1055,20 +546,20 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hVnn : -(2 ^ 99) ≤ (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 := by have h0 : -(2 ^ 72) ≤ r * 2 ^ 72 := by have := mul_le_mul_right_nonneg (show (-1 : Int) ≤ r from hr0) (show (0 : Int) ≤ 2 ^ 72 by omega) generalize hgT : r * 2 ^ 72 = T at this ⊢ omega have hg : -(2 ^ 72) ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by generalize hgV : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hrlo ⊢ + 116873961749927929127912020551560854268589826112230 = V at hrlo ⊢ omega have := mul_le_mul_right_nonneg hg (show (0 : Int) ≤ 2 ^ 27 by omega) generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at this ⊢ have e : (-(2 ^ 72) : Int) * 2 ^ 27 = -(2 ^ 99) := by decide omega have hsplit : BIASc * 2 ^ 27 + 2 ^ 99 = @@ -1080,14 +571,14 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hVnn hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hVnn hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1108,7 +599,7 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (c - 160) * (LN2c * 2 ^ 27)) ≤ (r + 2).toNat * 2 ^ 99 := by have hsc : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 := mul_le_mul_right_nonneg (by omega) (by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by @@ -1119,14 +610,14 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs hVnn + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hsc hVs hVnn generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1194,434 +685,6 @@ theorem lo_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (10 ^ 18 * (10 ^ 31 - 10)) = T4 at eR ⊢ omega -/-- A-atom master for negative outputs, `m < S` branch, `k ≥ 0`: -`e^(|r|/10^27) ≥ 10^18/x`. -/ -theorem an_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) - (hc1 : 1 ≤ c) (hc : c ≤ 160) - (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) - (hrneg : r < 0) - (hmx : m * 2 ^ (160 - c) ≤ x) : - capLB ((-r).toNat * 2 ^ 99) QS (10 ^ 18) x := by - have cap1 := x1capLtUpF h1 h2 - have hb := capUB_mul QS_pos (capUB_pow QS_pos cap2U (160 - c)) capBU - have hX1 := x1_nonpos_ltF h1 h2 - have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc - -- split: |X1|·E = pa + (kL + B) with pa = -V·2^27 ≥ 0 - have hsplit : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 - - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27)) + - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27) := by - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hV0 : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ 0 := by - have hm := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * - 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ 0 from by - generalize hgV' : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hr ⊢ - generalize hgR : (r + 1) * 2 ^ 72 = R at hr - have : R ≤ 0 := by - rw [← hgR] - have : r + 1 ≤ 0 := by omega - have := mul_le_mul_right_nonneg this (show (0 : Int) ≤ 2 ^ 72 by omega) - generalize hgT : (r + 1) * 2 ^ 72 = T at this ⊢ - omega - omega) (show (0 : Int) ≤ 2 ^ 27 by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hm ⊢ - clear cap1 hb hX1 hVs hrlo hr h1 h2 hmx hX1n hBc hLc - omega - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hb hr h1 h2 hc hc1 hmx hrlo hrneg - omega - rw [hsplit] at cap1 - have capV := capLB_cancel QS_pos cap1 hb - have hple : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 - - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27) ≤ (-r).toNat * 2 ^ 99 := by - have hsc : (-r) * 2 ^ 72 * 2 ^ 27 ≥ -(int256 (x1W (zWord m)) * 7450580596923828125 + - ln2kInt c + 116873961749927929127912020551516294209054209107914) * 2 ^ 27 := by - have h := mul_le_mul_right_nonneg hrlo (show (0 : Int) ≤ 2 ^ 27 by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) = V at h ⊢ - generalize hgR : r * 2 ^ 72 * 2 ^ 27 = R at h - have e1 : (-r) * 2 ^ 72 * 2 ^ 27 = -(r * 2 ^ 72 * 2 ^ 27) := by - rw [Int.neg_mul, Int.neg_mul] - have e2 : -V * 2 ^ 27 = -(V * 2 ^ 27) := Int.neg_mul _ _ - generalize hgV2 : V * 2 ^ 27 = V27 at h e2 ⊢ - omega - have e99 : (-r) * 2 ^ 72 * 2 ^ 27 = (-r) * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [e99] at hsc - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hnegV : -(int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = - -((int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27) := - Int.neg_mul _ _ - rw [hnegV] at hsc - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hb capV hr h1 h2 hc hc1 hmx hsplit hrlo - omega - have hmul : ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 - - ((160 - c) * (LN2c * 2 ^ 27) + BIASc * 2 ^ 27)) * QS ≤ - (-r).toNat * 2 ^ 99 * QS := - Nat.mul_le_mul_right _ hple - have capR := capLB_arg QS_pos hmul capV - refine capLB_weaken ?_ capR ?_ - · have h1' : 0 < m * 10000000000000000000000000003382 := by - have : 0 < m := by simp only [MLO] at h1; omega - exact Nat.mul_pos this (by decide) - exact Nat.mul_pos h1' (Nat.mul_pos (Nat.pow_pos (by decide)) (by decide)) - · have hbg := budgetU_le (k := 160 - c) (by omega) - have hbm : m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) ≤ - m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := - Nat.mul_le_mul_left _ (Nat.mul_le_mul_left _ hbg) - have hxm : m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) ≤ - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := - Nat.mul_le_mul_right _ hmx - have e1 : 10 ^ 18 * (m * 10000000000000000000000000003382 * - ((2 * (10 ^ 40 + 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3383)))) = - m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) := by - rw [show (10000000000000000000000000003382 : Nat) = 10 ^ 31 + 3382 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e2 : m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := by - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have e3 : 560227709747861399187319382270000000000000000000000000000000 * - ((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31)) * x = - x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have e' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - rw [e' ((10 ^ 40 : Nat) ^ (160 - c))] - generalize hT1 : 10 ^ 18 * (m * 10000000000000000000000000003382 * - ((2 * (10 ^ 40 + 1)) ^ (160 - c) * (Sc * (10 ^ 31 - 3383)))) = T1 at e1 ⊢ - generalize hT2 : m * (Sc * ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ (160 - c) * - (10 ^ 31 - 3383) * 10 ^ 18)) = T2 at hbm e1 - generalize hT3 : m * (Sc * (2 ^ (160 - c) * (10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - T3 at hbm e2 - generalize hT4 : m * 2 ^ (160 - c) * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = - T4 at hxm e2 - generalize hT5 : x * (Sc * ((10 ^ 40 : Nat) ^ (160 - c) * 10 ^ 80)) = T5 at hxm e3 - generalize hT6 : 560227709747861399187319382270000000000000000000000000000000 * - ((10 ^ 40 : Nat) ^ (160 - c) * (10 ^ 18 * 10 ^ 31)) * x = T6 at e3 ⊢ - omega - -/-- A-atom master for negative outputs, `m ≥ S` branch, negative shift -(exact mantissa). -/ -theorem an_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) - (hc : 160 < c) (hc2 : c ≤ 255) - (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) - (hrneg : r < 0) - (hmx : m = x * 2 ^ (c - 160)) : - capLB ((-r).toNat * 2 ^ 99) QS (10 ^ 18) x := by - have cap1 := x1capGeUpF h1 h2 - have hb := capUB_mul QS_pos cap1 capBU - have hsum := capLB_pow cap2L (c - 160) - have hX1 := x1_nonneg_geF h1 h2 - have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc - -- split: jL = pa + (X1·E + B) with pa = -V·2^27 ≥ 0 - have hsplit : (c - 160) * (LN2c * 2 ^ 27) = - ((c - 160) * (LN2c * 2 ^ 27) - - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27)) + - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27) := by - have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX1 - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hV0 : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ 0 := by - have hVle : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ 0 := by - have hR : (r + 1) * 2 ^ 72 ≤ 0 := by - have hle : r + 1 ≤ 0 := by omega - have := mul_le_mul_right_nonneg hle (show (0 : Int) ≤ 2 ^ 72 by omega) - generalize hgT : (r + 1) * 2 ^ 72 = T at this ⊢ - omega - generalize hgV' : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hr ⊢ - clear cap1 hb hsum hX1 hVs hrlo h1 h2 hmx hX1n hBc hLc - omega - have := mul_le_mul_right_nonneg hVle (show (0 : Int) ≤ 2 ^ 27 by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ - clear cap1 hb hsum hX1 hVs hrlo hr h1 h2 hmx hX1n hBc hLc - omega - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hb hsum hr h1 h2 hc hc2 hmx hrlo hrneg - omega - rw [hsplit] at hsum - have capV := capLB_cancel QS_pos hsum hb - have hple : (c - 160) * (LN2c * 2 ^ 27) - - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27) ≤ (-r).toNat * 2 ^ 99 := by - have hsc := mul_le_mul_right_nonneg hrlo (show (0 : Int) ≤ 2 ^ 27 by omega) - have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hX1 - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have er : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [er] at hsc - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hb hsum capV hr h1 h2 hc hc2 hmx hsplit hrlo - omega - have hmul : ((c - 160) * (LN2c * 2 ^ 27) - - ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - BIASc * 2 ^ 27)) * QS ≤ (-r).toNat * 2 ^ 99 * QS := - Nat.mul_le_mul_right _ hple - have capR := capLB_arg QS_pos hmul capV - refine capLB_weaken ?_ capR ?_ - · have hm0 : 0 < m := by simp only [Sc] at h1; omega - have hScp : 0 < Sc := by simp only [Sc]; omega - exact Nat.mul_pos (Nat.pow_pos (by omega)) - (Nat.mul_pos (Nat.mul_pos hm0 (by omega)) (Nat.mul_pos hScp (by omega))) - · have hbg := budgetUn_le (j := c - 160) (by omega) - have hbf := Nat.mul_le_mul_left (x * Sc) hbg - have eL : 10 ^ 18 * ((10 ^ 40 : Nat) ^ (c - 160) * - (m * 10000000000000000000000000003382 * (Sc * (10 ^ 31 - 3383)))) = - x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * (10 ^ 40 : Nat) ^ (c - 160) * - 2 ^ (c - 160) * 10 ^ 18) := by - rw [hmx, show (10000000000000000000000000003382 : Nat) = 10 ^ 31 + 3382 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have eR : (2 * (10 ^ 40 - 1)) ^ (c - 160) * - (560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 18 * 10 ^ 31)) * x = - x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have e' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - rw [e' ((2 * (10 ^ 40 - 1)) ^ (c - 160))] - generalize hT1 : 10 ^ 18 * ((10 ^ 40 : Nat) ^ (c - 160) * - (m * 10000000000000000000000000003382 * (Sc * (10 ^ 31 - 3383)))) = T1 at eL ⊢ - generalize hT2 : x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 2 ^ (c - 160) * 10 ^ 18) = T2 at eL hbf - generalize hT3 : x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) = T3 at hbf eR - generalize hT4 : (2 * (10 ^ 40 - 1)) ^ (c - 160) * - (560227709747861399187319382270000000000000000000000000000000 * - (10 ^ 18 * 10 ^ 31)) * x = T4 at eR ⊢ - omega - -/-- A-atom master for negative outputs, `m < S` branch, negative shift -(exact mantissa). -/ -theorem an_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) - (hc : 160 < c) (hc2 : c ≤ 255) - (hrlo : r * 2 ^ 72 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) - (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) - (hrneg : r < 0) - (hmx : m = x * 2 ^ (c - 160)) : - capLB ((-r).toNat * 2 ^ 99) QS (10 ^ 18) x := by - have cap1 := x1capLtUpF h1 h2 - have hsum := capLB_mul cap1 (capLB_pow cap2L (c - 160)) - have hX1 := x1_nonpos_ltF h1 h2 - have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc - have hsplit : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27) = - ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27) - BIASc * 2 ^ 27) + BIASc * 2 ^ 27 := by - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have hV0 : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ 0 := by - have hVle : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ 0 := by - have hR : (r + 1) * 2 ^ 72 ≤ 0 := by - have hle : r + 1 ≤ 0 := by omega - have := mul_le_mul_right_nonneg hle (show (0 : Int) ≤ 2 ^ 72 by omega) - generalize hgT : (r + 1) * 2 ^ 72 = T at this ⊢ - omega - generalize hgV' : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 = V at hr ⊢ - clear cap1 hsum hX1 hVs hrlo h1 h2 hmx hX1n hBc hLc - omega - have := mul_le_mul_right_nonneg hVle (show (0 : Int) ≤ 2 ^ 27 by omega) - generalize hgV' : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at this ⊢ - clear cap1 hsum hX1 hVs hrlo hr h1 h2 hmx hX1n hBc hLc - omega - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hV0 hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hsum hr h1 h2 hc hc2 hmx hrlo hrneg - omega - rw [hsplit] at hsum - have capV := capLB_cancel QS_pos hsum capBU - have hple : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27) - BIASc * 2 ^ 27 ≤ (-r).toNat * 2 ^ 99 := by - have hsc := mul_le_mul_right_nonneg hrlo (show (0 : Int) ≤ 2 ^ 27 by omega) - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by - decide +kernel - have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = - ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by - simp only [Int.natCast_mul] - rfl - have er : r * 2 ^ 72 * 2 ^ 27 = r * 2 ^ 99 := by - rw [Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from by decide] - rw [er] at hsc - generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hsc hVs - generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs - generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc - generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ - generalize hgD : (-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 = D at ⊢ - have hAD : (D : Int) = -A := by - rw [← hgA, ← hgD, Int.natCast_mul, hX1n] - rw [show (-int256 (x1W (zWord m))) * ((1000000000000000000000000000 : Nat) : Int) = - -(int256 (x1W (zWord m)) * ((1000000000000000000000000000 : Nat) : Int)) from by - rw [Int.neg_mul]] - rfl - generalize hgE : (BIASc * 2 ^ 27 : Nat) = E at hBc ⊢ - clear hX1n hX1 cap1 hsum capV hr h1 h2 hc hc2 hmx hsplit hrlo - omega - have hmul : ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000 + - (c - 160) * (LN2c * 2 ^ 27) - BIASc * 2 ^ 27) * QS ≤ - (-r).toNat * 2 ^ 99 * QS := - Nat.mul_le_mul_right _ hple - have capR := capLB_arg QS_pos hmul capV - refine capLB_weaken ?_ capR ?_ - · have hm0 : 0 < m := by simp only [MLO] at h1; omega - have hScp : 0 < Sc := by simp only [Sc]; omega - exact Nat.mul_pos (Nat.mul_pos (Nat.mul_pos hm0 (by omega)) (Nat.pow_pos (by omega))) - (Nat.mul_pos hScp (by omega)) - · have hbg := budgetUn_le (j := c - 160) (by omega) - have hbf := Nat.mul_le_mul_left (x * Sc) hbg - have eL : 10 ^ 18 * (m * 10000000000000000000000000003382 * - (10 ^ 40 : Nat) ^ (c - 160) * (Sc * (10 ^ 31 - 3383))) = - x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * (10 ^ 40 : Nat) ^ (c - 160) * - 2 ^ (c - 160) * 10 ^ 18) := by - rw [hmx, show (10000000000000000000000000003382 : Nat) = 10 ^ 31 + 3382 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - have eR : 560227709747861399187319382270000000000000000000000000000000 * - (2 * (10 ^ 40 - 1)) ^ (c - 160) * (10 ^ 18 * 10 ^ 31) * x = - x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) := by - rw [show (560227709747861399187319382270000000000000000000000000000000 : Nat) = - Sc * 10 ^ 31 from by decide] - have e' : ∀ P : Nat, (10 : Nat) ^ 18 * ((10 : Nat) ^ 31 * ((10 : Nat) ^ 31 * P)) = - (10 : Nat) ^ 80 * P := by - intro P - rw [← Nat.mul_assoc, ← Nat.mul_assoc, - show ((10 : Nat) ^ 18 * 10 ^ 31 * 10 ^ 31) = 10 ^ 80 from by decide] - simp only [Nat.mul_assoc, Nat.mul_comm, Nat.mul_left_comm] - rw [e' ((2 * (10 ^ 40 - 1)) ^ (c - 160))] - generalize hT1 : 10 ^ 18 * (m * 10000000000000000000000000003382 * - (10 ^ 40 : Nat) ^ (c - 160) * (Sc * (10 ^ 31 - 3383))) = T1 at eL ⊢ - generalize hT2 : x * Sc * ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * - (10 ^ 40 : Nat) ^ (c - 160) * 2 ^ (c - 160) * 10 ^ 18) = T2 at eL hbf - generalize hT3 : x * Sc * (10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ (c - 160)) = T3 at hbf eR - generalize hT4 : 560227709747861399187319382270000000000000000000000000000000 * - (2 * (10 ^ 40 - 1)) ^ (c - 160) * (10 ^ 18 * 10 ^ 31) * x = T4 at eR ⊢ - omega - /-- The reciprocal strict budget folds from the worst-case mantissa. -/ theorem budgetB_fold {m k : Nat} (hm : 2 ^ 95 ≤ m) (hk : k ≤ 159) : (m + 1) * 2 ^ k * ((10 : Nat) ^ 31 * (10 ^ 40 : Nat) ^ k * (10 ^ 18 * 10 ^ 31) * @@ -1658,7 +721,7 @@ theorem budgetB_fold {m k : Nat} (hm : 2 ^ 95 ≤ m) (hk : k ≤ 159) : theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc1 : 1 ≤ c) (hc : c ≤ 160) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrneg : r + 2 ≤ 0) (hxm : x < (m + 1) * 2 ^ (160 - c)) : capUB ((-(r + 2)).toNat * 2 ^ 99) QS (10 ^ 18 * (10 ^ 31 - 10)) (x * 10 ^ 31) := by @@ -1668,11 +731,11 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hVs := v_scale_pos (int256 (x1W (zWord m))) c hc -- the exponent gap: -V·2^27 ≥ (|r+2|+1)·2^99 + 2^27 have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551560854268589826112230 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (show (0 : Int) ≤ 2 ^ 27 by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -1687,7 +750,7 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1699,7 +762,7 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) generalize hgT : (r + 1) * 2 ^ 99 = T at this ⊢ omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1722,14 +785,14 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((160 - c) * (LN2c * 2 ^ 27) : Nat) : Int) = ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((160 - c : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (160 - c) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1818,7 +881,7 @@ theorem bn_lt_pos {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrneg : r + 2 ≤ 0) (hmx : m = x * 2 ^ (c - 160)) : capUB ((-(r + 2)).toNat * 2 ^ 99) QS (10 ^ 18 * (10 ^ 31 - 10)) (x * 10 ^ 31) := by @@ -1828,11 +891,11 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1 := x1_nonneg_geF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551560854268589826112230 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (show (0 : Int) ≤ 2 ^ 27 by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -1849,7 +912,7 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1861,7 +924,7 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) generalize hgT : (r + 1) * 2 ^ 99 = T at this ⊢ omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1882,14 +945,14 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := Int.toNat_of_nonneg hX1 have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -1950,7 +1013,7 @@ theorem bn_ge_neg {m c x : Nat} {r : Int} (h1 : Sc ≤ m) (h2 : m < MHI) theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) (hc : 160 < c) (hc2 : c ≤ 255) (hr : int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 < (r + 1) * 2 ^ 72) + 116873961749927929127912020551560854268589826112230 < (r + 1) * 2 ^ 72) (hrneg : r + 2 ≤ 0) (hmx : m = x * 2 ^ (c - 160)) : capUB ((-(r + 2)).toNat * 2 ^ 99) QS (10 ^ 18 * (10 ^ 31 - 10)) (x * 10 ^ 31) := by @@ -1960,11 +1023,11 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1 := x1_nonpos_ltF h1 h2 have hVs := v_scale_neg (int256 (x1W (zWord m))) c hc have hgap : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 ≤ + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 ≤ (r + 1) * 2 ^ 99 - 2 ^ 27 := by have hsc := mul_le_mul_right_nonneg (show int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 ≤ (r + 1) * 2 ^ 72 - 1 + 116873961749927929127912020551560854268589826112230 ≤ (r + 1) * 2 ^ 72 - 1 from by omega) (show (0 : Int) ≤ 2 ^ 27 by omega) have er : ((r + 1) * 2 ^ 72 - 1) * 2 ^ 27 = (r + 1) * 2 ^ 99 - 2 ^ 27 := by rw [Int.sub_mul, Int.mul_assoc, show ((2 : Int) ^ 72 * 2 ^ 27) = 2 ^ 99 from @@ -1980,7 +1043,7 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by @@ -1992,7 +1055,7 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) generalize hgT : (r + 1) * 2 ^ 99 = T at this ⊢ omega generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ @@ -2015,14 +1078,14 @@ theorem bn_lt_neg {m c x : Nat} {r : Int} (h1 : MLO ≤ m) (h2 : m < Sc) have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := Int.toNat_of_nonneg (by omega) have hBc : ((BIASc * 2 ^ 27 : Nat) : Int) = - 116873961749927929127912020551516294209054209107914 * 2 ^ 27 := by + 116873961749927929127912020551560854268589826112230 * 2 ^ 27 := by decide +kernel have hLc : (((c - 160) * (LN2c * 2 ^ 27) : Nat) : Int) = ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) := by simp only [Int.natCast_mul] rfl generalize hgV : (int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914) * 2 ^ 27 = V27 at hgap hVs + 116873961749927929127912020551560854268589826112230) * 2 ^ 27 = V27 at hgap hVs generalize hgA : int256 (x1W (zWord m)) * 1000000000000000000000000000 = A at hVs generalize hgB : ((c - 160 : Nat) : Int) * ((LN2c : Int) * 2 ^ 27) = B at hVs hLc generalize hgC : (c - 160) * (LN2c * 2 ^ 27) = Cn at hLc ⊢ diff --git a/formal/ln/LnProof/LnProof/Floor/Bracket.lean b/formal/ln/LnProof/LnProof/Floor/Bracket.lean index 1eaf013f0..363be9658 100644 --- a/formal/ln/LnProof/LnProof/Floor/Bracket.lean +++ b/formal/ln/LnProof/LnProof/Floor/Bracket.lean @@ -8,11 +8,12 @@ open FormalYul.Preservation # Pipeline brackets against the certificate rationals For each mantissa `m`, the pipeline value `X1 = int256 (x1W (zWord m))` -is trapped between the certificate bracket rationals: on `m ≥ S`, -`geTN2b/geTD2b ≤ X1/2^99 ≤ geTN/geTD`, and on `m ≤ S` the mirrored -brackets hold for `-X1`. The chains run through the exact division -brackets of `z` and `u`, the Stages sandwiches for the Horner stages, and -divided-difference monotonicity of the homogenized `p`/`q` polynomials. +is compared with the certificate bracket rationals: on `m ≥ S`, +`geTN2b/geTD2b ≤ X1/2^99`; on `m ≤ S`, the brackets trap +`-X1/2^99` between `ltTN2b/ltTD2b` and `ltTN/ltTD`. The chains run through +the exact division brackets of `z` and `u`, the Stages sandwiches for the +Horner stages, and divided-difference monotonicity of the homogenized `p`/`q` +polynomials. -/ set_option maxRecDepth 4096 @@ -958,29 +959,6 @@ theorem evalWLO_ge (m : Nat) : evalPoly_polyMul, evalPoly_polyScale, evalA2_ge, evalA_ge, evalB_ge, evalB2_ge] omega -theorem evalTN_ge (m : Nat) : - evalPoly geTN (m : Int) = - 2 ^ 17 * ((((m : Int) - Sc) * (((m : Int) + Sc))) * - homEvalI PPc (evalPoly geWLO (m : Int)) (evalPoly geD8 (m : Int))) := by - show evalPoly (polyScale (2 ^ 17) (polyMul (polyMul geA geB) gePPHwlo)) (m : Int) = _ - rw [evalPoly_polyScale, evalPoly_polyMul, evalPoly_polyMul, evalA_ge, evalB_ge] - have h : evalPoly gePPHwlo (m : Int) = - homEvalI PPc (evalPoly geWLO (m : Int)) (evalPoly geD8 (m : Int)) := by - show evalPoly (homPoly PPc geWLO geD8) (m : Int) = _ - exact evalPoly_homPoly PPc geWLO geD8 (m : Int) - rw [h] - -theorem evalTD_ge (m : Nat) : - evalPoly geTD (m : Int) = - -homEvalI QQc (evalPoly geA96 (m : Int)) (evalPoly geB2 (m : Int)) := by - show evalPoly (polyNeg geQQHws) (m : Int) = _ - rw [evalPoly_polyNeg] - have h : evalPoly geQQHws (m : Int) = - homEvalI QQc (evalPoly geA96 (m : Int)) (evalPoly geB2 (m : Int)) := by - show evalPoly (homPoly QQc geA96 geB2) (m : Int) = _ - exact evalPoly_homPoly QQc geA96 geB2 (m : Int) - rw [h] - theorem evalWS_ge (m : Nat) : evalPoly certGeWS (m : Int) = 2333000000000000000000000000 * (((m : Int) + Sc) * ((m : Int) + Sc)) - @@ -1047,361 +1025,6 @@ theorem evalTD2b_ge (m : Nat) : rw [evalPoly_polyScale] rw [h2] -/-- The pipeline value sits below the upper certificate rational on the -`m ≥ S` branch: `X1 · TD(m) ≤ TN(m) · 2^99`. -/ -theorem bracket_ge_up {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : - int256 (x1W (zWord m)) * evalPoly geTD (m : Int) ≤ - evalPoly geTN (m : Int) * 2 ^ 99 := by - have hMLO : MLO ≤ m := by - simp only [MLO]; simp only [Sc] at h1; omega - have hSle : Sc ≤ m := by simp only [Sc] at h1 ⊢; omega - -- z and its division bracket - obtain ⟨q, hzq, hq1, hq2⟩ := z_bracket_ge hSle h2 - have hzr := zWord_range hMLO h2 - have hwlt : zWord m < 2 ^ 256 := by unfold zWord; exact evmSdiv_lt _ _ - have hx1 : x1W (zWord m) = hAt (int256 (zWord m)) := by - unfold hAt; rw [ofInt_toInt hwlt] - obtain ⟨heq, hmul⟩ := hAt_facts (int256 (zWord m)) hzr.1 hzr.2 - -- u-hat and its division bracket - have huv : uVal (int256 (zWord m)) = q * q / 2 ^ 104 := by - unfold uVal - rw [hzq] - have e : -(q : Int) * -(q : Int) = ((q * q : Nat) : Int) := by - rw [Int.neg_mul_neg] - omega - rw [e] - omega - have hu_le : q * q / 2 ^ 104 ≤ Uc := by - have := uVal_le (int256 (zWord m)) hzr.1 hzr.2 - rw [huv] at this - exact this - have hudm := Nat.div_add_mod (q * q) (2 ^ 104) - have huml := Nat.mod_lt (q * q) (y := 2 ^ 104) (by omega) - -- the quotient is at least one on this branch - have hq_ge1 : 1 ≤ q := by - rcases Nat.eq_zero_or_pos q with h0 | h - · exfalso - subst h0 - have hA46 : (46 : Int) ≤ (m : Int) - Sc := by simp only [Sc] at h1 ⊢; omega - have hBmax : (m : Int) + Sc ≤ 34624238973196922243142627472244 := by - simp only [MHI] at h2; simp only [Sc]; omega - have h46 : (46 : Int) * 2 ^ 100 ≤ ((m : Int) - Sc) * 2 ^ 100 := - mul_le_mul_right_nonneg hA46 (by omega) - omega - · exact h - -- stage sandwiches at u-hat, with every heavy term made opaque - obtain ⟨pw, plo, phi, psl, psh⟩ := pS4_facts hu_le - obtain ⟨qw, qlo, qhi, qsl, qsh⟩ := qS5_facts hu_le - rw [huv] at heq hmul - generalize hw1 : pS4 (q * q / 2 ^ 104) = pword at heq hmul pw plo phi psl psh - generalize hw2 : qS5 (q * q / 2 ^ 104) = qword at heq qw qlo qhi qsl qsh - generalize hPP : evalPoly PPc ((q * q / 2 ^ 104 : Nat) : Int) = PPv at psl psh - generalize hQQ : evalPoly QQc ((q * q / 2 ^ 104 : Nat) : Int) = QQv at qsl qsh - have hxe : x1W (zWord m) = evmSdiv (evmMul pword (uint256OfInt (int256 (zWord m)))) qword := - hx1.trans heq - have hnum_neg : int256 (evmMul pword (uint256OfInt (int256 (zWord m)))) < 0 := by - rw [hmul, hzq] - have h := mul_le_mul_left_nonneg (show (1 : Int) ≤ (q : Int) by omega) - (show (0 : Int) ≤ int256 pword by omega) - have e : int256 pword * -(q : Int) = -(int256 pword * (q : Int)) := Int.mul_neg _ _ - omega - have hpz := pz_bound plo phi hzr.1 hzr.2 - have hX1v : int256 (x1W (zWord m)) = - (((int256 pword * (q : Int)).toNat / (-int256 qword).toNat : Nat) : Int) := by - rw [hxe, evmSdiv_neg_neg (evmMul_lt _ _) qw hnum_neg - (by rw [hmul]; exact hpz.1) (by omega), hmul, hzq] - have e : -(int256 pword * -(q : Int)) = int256 pword * (q : Int) := by - rw [Int.mul_neg] - omega - rw [e] - have hpq_pos : (0 : Int) ≤ int256 pword * (q : Int) := - Int.mul_nonneg (by omega) (by omega) - have hX1_nn : (0 : Int) ≤ int256 (x1W (zWord m)) := by - rw [hX1v] - exact Int.natCast_nonneg _ - -- the division bracket for X1 - have hdiv := Nat.div_mul_le_self (int256 pword * (q : Int)).toNat (-int256 qword).toNat - have hX1br : int256 (x1W (zWord m)) * (-int256 qword) ≤ int256 pword * (q : Int) := by - rw [hX1v] - have e : (((int256 pword * (q : Int)).toNat / (-int256 qword).toNat : Nat) : Int) * - (-int256 qword) = - ((((int256 pword * (q : Int)).toNat / (-int256 qword).toNat) * - (-int256 qword).toNat : Nat) : Int) := by - rw [Int.natCast_mul] - have : ((-int256 qword).toNat : Int) = -int256 qword := by omega - rw [this] - rw [e] - omega - clear heq hxe hmul hX1v hnum_neg hdiv hpz hx1 hzr hwlt hudm huml hzq hw1 hw2 - generalize hXg : int256 (x1W (zWord m)) = X1v at hX1br hX1_nn ⊢ - -- value abbreviations - have huI1 : ((q * q / 2 ^ 104 : Nat) : Int) * 2 ^ 104 ≤ (q : Int) * q := by - have e : (q : Int) * q = ((q * q : Nat) : Int) := by omega - rw [e] - omega - have huI2 : (q : Int) * q ≤ ((q * q / 2 ^ 104 : Nat) : Int) * 2 ^ 104 + 2 ^ 104 - 1 := by - have e : (q : Int) * q = ((q * q : Nat) : Int) := by omega - rw [e] - omega - -- ordering of the P arguments: WLO ≤ u-hat · D8 - have hcastA : ((m - Sc : Nat) : Int) = (m : Int) - Sc := by omega - have hcastB : ((m + Sc : Nat) : Int) = (m : Int) + Sc := by omega - have hwloLt := wlo_lt_un (d := m - Sc) (q := q) (u := q * q / 2 ^ 104) - (B := m + Sc) (by omega) - (by omega) (by simp only [MHI] at h2; simp only [Sc] at *; omega) - (by rw [hcastA, hcastB]; exact hq2) - huI2 - have hordP : evalPoly geWLO (m : Int) ≤ - ((q * q / 2 ^ 104 : Nat) : Int) * evalPoly geD8 (m : Int) := by - rw [evalWLO_ge, evalD8_ge] - rw [hcastA, hcastB] at hwloLt - have e1 : ((q * q / 2 ^ 104 : Nat) : Int) * (8 * (((m : Int) + Sc) * ((m : Int) + Sc))) = - 8 * (((q * q / 2 ^ 104 : Nat) : Int) * (((m : Int) + Sc) * ((m : Int) + Sc))) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - have e2 : (((m : Int) - Sc) * ((m : Int) - Sc)) * 2 ^ 99 = - 2 ^ 99 * (((m : Int) - Sc) * ((m : Int) - Sc)) := Int.mul_comm _ _ - omega - -- ordering of the Q arguments: u-hat · B2 ≤ A96 - have hunle := un_le_dsq (d := m - Sc) (q := q) (u := q * q / 2 ^ 104) - (B := m + Sc) (by omega) - (by rw [hcastA, hcastB]; exact hq1) huI1 - have hordQ : ((q * q / 2 ^ 104 : Nat) : Int) * evalPoly geB2 (m : Int) ≤ - evalPoly geA96 (m : Int) := by - rw [evalB2_ge, evalA96_ge] - rw [hcastA, hcastB] at hunle - exact hunle - -- box bounds - have hB2nn : (0 : Int) ≤ evalPoly geB2 (m : Int) := by - rw [evalB2_ge] - exact Int.mul_nonneg (by simp only [Sc]; omega) (by simp only [Sc]; omega) - have hD8nn : (0 : Int) ≤ evalPoly geD8 (m : Int) := by - rw [evalD8_ge] - refine Int.mul_nonneg (by omega) (Int.mul_nonneg ?_ ?_) <;> - simp only [Sc] <;> omega - have hu_lt_UB : ((q * q / 2 ^ 104 : Nat) : Int) ≤ 2333000000000000000000000000 := by - simp only [Uc] at hu_le - omega - have hb1P : ((q * q / 2 ^ 104 : Nat) : Int) * evalPoly geD8 (m : Int) ≤ - 2333000000000000000000000000 * evalPoly geD8 (m : Int) := - mul_le_mul_right_nonneg hu_lt_UB hD8nn - have hb2P : -(2333000000000000000000000000 * evalPoly geD8 (m : Int)) ≤ - evalPoly geWLO (m : Int) := by - rw [evalWLO_ge, evalD8_ge] - have hAB : ((m : Int) - Sc) * ((m : Int) + Sc) ≤ - ((m : Int) + Sc) * ((m : Int) + Sc) := - mul_le_mul_right_nonneg (by omega) (by simp only [Sc]; omega) - have hsq : (0 : Int) ≤ (((m : Int) - Sc) * ((m : Int) - Sc)) := by - refine Int.mul_nonneg ?_ ?_ <;> simp only [Sc] at h1 ⊢ <;> omega - have hBB : (0 : Int) ≤ ((m : Int) + Sc) * ((m : Int) + Sc) := by - refine Int.mul_nonneg ?_ ?_ <;> simp only [Sc] <;> omega - generalize ((m : Int) - Sc) * ((m : Int) - Sc) = AA at * - generalize ((m : Int) - Sc) * ((m : Int) + Sc) = AB at * - generalize ((m : Int) + Sc) * ((m : Int) + Sc) = BB at * - have h99 : (0 : Int) ≤ 2 ^ 99 * AA := Int.mul_nonneg (by omega) hsq - omega - -- P comparison through collapse and monotonicity - have hcolP : homEvalI PPc (((q * q / 2 ^ 104 : Nat) : Int) * - evalPoly geD8 (m : Int)) (evalPoly geD8 (m : Int)) = - evalPoly geD8 (m : Int) ^ 4 * PPv := by - rw [show PPc = (8203564106909714963200842018502018851024462725819431901516251320229929630934299039494945066816553616430456446611805193566972803059892092928 : Int) :: PP3c from rfl, - homEvalI_collapse, ← hPP] - rfl - have hBpos : (0 : Int) < (m : Int) + Sc := by simp only [Sc]; omega - have hD8pos : (0 : Int) < evalPoly geD8 (m : Int) := by - rw [evalD8_ge] - exact Int.mul_pos (by omega) (Int.mul_pos hBpos hBpos) - have hB2pos : (0 : Int) < evalPoly geB2 (m : Int) := by - rw [evalB2_ge] - exact Int.mul_pos hBpos hBpos - have hPanti := homEvalI_PPc_anti (n1 := ((q * q / 2 ^ 104 : Nat) : Int) * - evalPoly geD8 (m : Int)) (n2 := evalPoly geWLO (m : Int)) - (D := evalPoly geD8 (m : Int)) hD8pos hordP hb1P hb2P - have hPfin : int256 pword * 2 ^ 358 * evalPoly geD8 (m : Int) ^ 4 ≤ - homEvalI PPc (evalPoly geWLO (m : Int)) (evalPoly geD8 (m : Int)) := by - have hD84 : (0 : Int) ≤ evalPoly geD8 (m : Int) ^ 4 := by - have h2' : evalPoly geD8 (m : Int) ^ 2 = evalPoly geD8 (m : Int) * - evalPoly geD8 (m : Int) := by - have h := Int.pow_succ (evalPoly geD8 (m : Int)) 1 - rw [pow_one] at h - exact h - have h4' : evalPoly geD8 (m : Int) ^ 4 = evalPoly geD8 (m : Int) ^ 2 * - evalPoly geD8 (m : Int) ^ 2 := by - have h3 := Int.pow_succ (evalPoly geD8 (m : Int)) 2 - have h4 := Int.pow_succ (evalPoly geD8 (m : Int)) 3 - rw [h3] at h4 - rw [h4, h2'] - simp only [Int.mul_assoc] - rw [h4', h2'] - exact Int.mul_nonneg (Int.mul_nonneg (by omega) (by omega)) - (Int.mul_nonneg (by omega) (by omega)) - have s1 : int256 pword * 2 ^ 358 * evalPoly geD8 (m : Int) ^ 4 ≤ - PPv * evalPoly geD8 (m : Int) ^ 4 := - mul_le_mul_right_nonneg psh hD84 - have e1 : PPv * evalPoly geD8 (m : Int) ^ 4 = - evalPoly geD8 (m : Int) ^ 4 * PPv := Int.mul_comm _ _ - generalize hg1 : homEvalI PPc (((q * q / 2 ^ 104 : Nat) : Int) * - evalPoly geD8 (m : Int)) (evalPoly geD8 (m : Int)) = HU at hPanti hcolP - generalize hg2 : homEvalI PPc (evalPoly geWLO (m : Int)) - (evalPoly geD8 (m : Int)) = HW at hPanti ⊢ - generalize hg3 : PPv * evalPoly geD8 (m : Int) ^ 4 = P1 at s1 e1 - generalize hg4 : evalPoly geD8 (m : Int) ^ 4 * PPv = P2 at e1 hcolP - generalize hg5 : int256 pword * 2 ^ 358 * evalPoly geD8 (m : Int) ^ 4 = P0 at s1 ⊢ - omega - -- Q comparison - have hb1Q : evalPoly geA96 (m : Int) ≤ - 2333000000000000000000000000 * evalPoly geB2 (m : Int) := by - have hws := geWS_nonneg (m := (m : Int)) - (by simp only [Sc] at h1; omega) (by simp only [MHI] at h2; omega) - rw [evalWS_ge] at hws - rw [evalA96_ge, evalB2_ge] - omega - have hb2Q : -(2333000000000000000000000000 * evalPoly geB2 (m : Int)) ≤ - ((q * q / 2 ^ 104 : Nat) : Int) * evalPoly geB2 (m : Int) := by - have h := Int.mul_nonneg (Int.natCast_nonneg (q * q / 2 ^ 104)) (by omega : - (0 : Int) ≤ evalPoly geB2 (m : Int)) - have h2' : (0 : Int) ≤ 2333000000000000000000000000 * evalPoly geB2 (m : Int) := - Int.mul_nonneg (by omega) (by omega) - omega - have hQmono := homEvalI_QQc_mono (n1 := evalPoly geA96 (m : Int)) - (n2 := ((q * q / 2 ^ 104 : Nat) : Int) * evalPoly geB2 (m : Int)) - (D := evalPoly geB2 (m : Int)) hB2pos hordQ hb1Q hb2Q - have hcolQ : homEvalI QQc (((q * q / 2 ^ 104 : Nat) : Int) * - evalPoly geB2 (m : Int)) (evalPoly geB2 (m : Int)) = - evalPoly geB2 (m : Int) ^ 5 * QQv := by - rw [show QQc = (-(2202127471863542086976841246820549867195347718960342176144462014556523185327760268707187588705852038374958668534379582118318610928980329275922055168 : Int)) :: QQ4c from rfl, - homEvalI_collapse, ← hQQ] - rfl - have hQfin : -homEvalI QQc (evalPoly geA96 (m : Int)) (evalPoly geB2 (m : Int)) ≤ - -int256 qword * 2 ^ 386 * evalPoly geB2 (m : Int) ^ 5 := by - have hB25 : (0 : Int) ≤ evalPoly geB2 (m : Int) ^ 5 := pow_nonneg' (by omega) 5 - have s1 : evalPoly geB2 (m : Int) ^ 5 * QQv ≤ - homEvalI QQc (evalPoly geA96 (m : Int)) (evalPoly geB2 (m : Int)) := by - rw [← hcolQ] - exact hQmono - have s2 : int256 qword * 2 ^ 386 * evalPoly geB2 (m : Int) ^ 5 ≤ - QQv * evalPoly geB2 (m : Int) ^ 5 := - mul_le_mul_right_nonneg qsh hB25 - have e1 : QQv * evalPoly geB2 (m : Int) ^ 5 = - evalPoly geB2 (m : Int) ^ 5 * QQv := Int.mul_comm _ _ - have e2 : -int256 qword * 2 ^ 386 * evalPoly geB2 (m : Int) ^ 5 = - -(int256 qword * 2 ^ 386 * evalPoly geB2 (m : Int) ^ 5) := by - rw [Int.neg_mul, Int.neg_mul] - omega - -- final assembly - rw [evalTD_ge, evalTN_ge] - generalize hPHV : homEvalI PPc (evalPoly geWLO (m : Int)) - (evalPoly geD8 (m : Int)) = PHV at hPfin ⊢ - generalize hQHVg : homEvalI QQc (evalPoly geA96 (m : Int)) - (evalPoly geB2 (m : Int)) = QHV at hQfin ⊢ - have hD8e := evalD8_ge m - have hB2e := evalB2_ge m - generalize hD8g : evalPoly geD8 (m : Int) = D8v at hPfin hD8e - generalize hB2g : evalPoly geB2 (m : Int) = B2v at hQfin hB2e - have hqpos : (0 : Int) < -int256 qword := by omega - have hppos : (0 : Int) ≤ int256 pword := by omega - have hApos : (0 : Int) ≤ (m : Int) - Sc := by simp only [Sc] at h1 ⊢; omega - have hB25 : (0 : Int) ≤ B2v ^ 5 := by - rw [hB2e] - exact pow_nonneg' (Int.mul_nonneg (by omega) (by omega)) 5 - have hD84 : (0 : Int) ≤ D8v ^ 4 := by - rw [hD8e] - refine pow_nonneg' (Int.mul_nonneg (by omega) (Int.mul_nonneg ?_ ?_)) 4 <;> - simp only [Sc] <;> omega - -- Replace -QHV by the bounded qword expression. - have s1 : X1v * -QHV ≤ X1v * (-int256 qword * 2 ^ 386 * B2v ^ 5) := by - have h := mul_le_mul_left_nonneg hQfin hX1_nn - exact h - -- Pull the division bracket through. - have s2 : X1v * (-int256 qword * 2 ^ 386 * B2v ^ 5) ≤ - int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) := by - have e1 : X1v * (-int256 qword * 2 ^ 386 * B2v ^ 5) = - (X1v * -int256 qword) * (2 ^ 386 * B2v ^ 5) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - have hf : (0 : Int) ≤ 2 ^ 386 * B2v ^ 5 := Int.mul_nonneg (by omega) hB25 - have h := mul_le_mul_right_nonneg hX1br hf - omega - -- Multiply by B and use the z bracket. - have s3 : int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) * ((m : Int) + Sc) ≤ - int256 pword * (((m : Int) - Sc) * 2 ^ 100) * (2 ^ 386 * B2v ^ 5) := by - have e1 : int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) * ((m : Int) + Sc) = - (int256 pword * (2 ^ 386 * B2v ^ 5)) * ((q : Int) * ((m : Int) + Sc)) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - have e2 : int256 pword * (((m : Int) - Sc) * 2 ^ 100) * (2 ^ 386 * B2v ^ 5) = - (int256 pword * (2 ^ 386 * B2v ^ 5)) * (((m : Int) - Sc) * 2 ^ 100) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - have hf : (0 : Int) ≤ int256 pword * (2 ^ 386 * B2v ^ 5) := - Int.mul_nonneg hppos (Int.mul_nonneg (by omega) hB25) - have h := mul_le_mul_left_nonneg hq1 hf - omega - -- Bring in the P bound. - have s4 : int256 pword * (((m : Int) - Sc) * 2 ^ 100) * (2 ^ 386 * B2v ^ 5) * - (2 ^ 358 * D8v ^ 4) ≤ - PHV * (((m : Int) - Sc) * (2 ^ 486 * B2v ^ 5)) := by - have e1 : int256 pword * (((m : Int) - Sc) * 2 ^ 100) * (2 ^ 386 * B2v ^ 5) * - (2 ^ 358 * D8v ^ 4) = - (int256 pword * 2 ^ 358 * D8v ^ 4) * - (((m : Int) - Sc) * (2 ^ 100 * 2 ^ 386 * B2v ^ 5)) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - have hf : (0 : Int) ≤ ((m : Int) - Sc) * (2 ^ 100 * 2 ^ 386 * B2v ^ 5) := - Int.mul_nonneg hApos (Int.mul_nonneg (by omega) hB25) - have h := mul_le_mul_right_nonneg hPfin hf - have e2 : PHV * (((m : Int) - Sc) * (2 ^ 100 * 2 ^ 386 * B2v ^ 5)) = - PHV * (((m : Int) - Sc) * (2 ^ 486 * B2v ^ 5)) := by - rw [show ((2 : Int) ^ 100 * 2 ^ 386) = 2 ^ 486 from by decide] - omega - -- multiplied chain and cancellation - have hD84pos : (0 : Int) < D8v ^ 4 := by - rw [hD8e] - refine pow_pos' (Int.mul_pos (by omega) (Int.mul_pos hBpos hBpos)) 4 - have hMpos : (0 : Int) < ((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4) := - Int.mul_pos hBpos (Int.mul_pos (by omega) hD84pos) - have hMnn : (0 : Int) ≤ ((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4) := by omega - have k1 : X1v * -QHV * (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) ≤ - X1v * (-int256 qword * 2 ^ 386 * B2v ^ 5) * - (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) := - mul_le_mul_right_nonneg s1 hMnn - have k2 : X1v * (-int256 qword * 2 ^ 386 * B2v ^ 5) * - (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) ≤ - int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) * - (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) := - mul_le_mul_right_nonneg s2 hMnn - have k3 : int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) * - (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) = - int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) * ((m : Int) + Sc) * - (2 ^ 358 * D8v ^ 4) := by - simp only [Int.mul_assoc] - have k4 : int256 pword * (q : Int) * (2 ^ 386 * B2v ^ 5) * ((m : Int) + Sc) * - (2 ^ 358 * D8v ^ 4) ≤ - int256 pword * (((m : Int) - Sc) * 2 ^ 100) * (2 ^ 386 * B2v ^ 5) * - (2 ^ 358 * D8v ^ 4) := - mul_le_mul_right_nonneg s3 (Int.mul_nonneg (by omega) (by omega)) - have k6 : 2 ^ 17 * (((m : Int) - Sc) * ((m : Int) + Sc) * PHV) * 2 ^ 99 * - (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) = - PHV * (((m : Int) - Sc) * (2 ^ 486 * B2v ^ 5)) := by - rw [hD8e, hB2e] - rw [show ((8 : Int) * (((m : Int) + Sc) * ((m : Int) + Sc))) ^ 4 = - 4096 * (((m : Int) + Sc) * ((m : Int) + Sc)) ^ 4 from by - rw [mul_pow] - rw [show ((8 : Int) ^ 4) = 4096 from by decide]] - rw [show (((m : Int) + Sc) * ((m : Int) + Sc)) ^ 5 = - (((m : Int) + Sc) * ((m : Int) + Sc)) ^ 4 * - (((m : Int) + Sc) * ((m : Int) + Sc)) from by - rw [Int.pow_succ]] - have hAC : 2 ^ 17 * (((m : Int) - Sc) * ((m : Int) + Sc) * PHV) * 2 ^ 99 * - (((m : Int) + Sc) * (2 ^ 358 * (4096 * (((m : Int) + Sc) * ((m : Int) + Sc)) ^ 4))) = - (2 ^ 17 * 2 ^ 99 * 2 ^ 358 * 4096) * - (PHV * (((m : Int) - Sc) * ((((m : Int) + Sc) * ((m : Int) + Sc)) ^ 4 * - (((m : Int) + Sc) * ((m : Int) + Sc))))) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - rw [hAC, show ((2 : Int) ^ 17 * 2 ^ 99 * 2 ^ 358 * 4096) = 2 ^ 486 from by decide] - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - have key : X1v * -QHV * (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) ≤ - 2 ^ 17 * (((m : Int) - Sc) * ((m : Int) + Sc) * PHV) * 2 ^ 99 * - (((m : Int) + Sc) * (2 ^ 358 * D8v ^ 4)) := by - rw [k6] - omega - exact Int.le_of_mul_le_mul_right key hMpos - /-- The pipeline value sits above the lower certificate rational on the `m ≥ S` branch: `TN2b(m) · 2^99 ≤ X1 · TD2b(m)`. -/ theorem bracket_ge_lo {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) : diff --git a/formal/ln/LnProof/LnProof/Floor/Budget.lean b/formal/ln/LnProof/LnProof/Floor/Budget.lean index 5bf7227f3..5c5361deb 100644 --- a/formal/ln/LnProof/LnProof/Floor/Budget.lean +++ b/formal/ln/LnProof/LnProof/Floor/Budget.lean @@ -3,16 +3,11 @@ import Common.Foundation.ExpSum /-! # Per-exponent budget inequalities -The floor-spec assembly multiplies the `X1` caps with the `2^k` caps -(`cap2U`/`cap2L` raised to the binade shift `k = 160 - clz`), the bias -caps, and one output ulp (`capEL`), then weakens the resulting rational -to the `x/10^18` target through the mantissa window. The weakening step -reduces, per `k`, to one of the four integer inequalities certified here -by kernel evaluation over the whole `k` range. The slack that closes -each of them is the bias margin: `9.99e-28 (capEL) - 3.401e-28 (cert ε) - -3.404e-28 (bias) - 1e-30 (strictness) - 2^-95 ((m+1)/m padding) > 0` on -the low side, and `3.402e-28 (bias) - 3.401e-28 (cert ε) - k·1e-40 > 0` on -the high side. +The floor-spec assembly multiplies the lower `X1` caps with the `2^k` +caps, the bias caps, and one output ulp, then weakens the resulting +rational to the `x/10^18` target through the mantissa window. The four +remaining integer inequalities cover nonnegative and negative binade +shifts for the direct and reciprocal branches. Also provides `capLB_cancel`, the lower mirror of `capUB_cancel`, used to move the `2^|k|` factor across the quotient when `k < 0`. @@ -48,47 +43,24 @@ end Common.Exp namespace LnFloorCert -/-- Upper weakening budget, `k = 160 - clz ≥ 0` (worst case `x = m 2^k`). -/ -def budgetU (k : Nat) : Bool := - decide ((10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ k * (10 ^ 31 - 3383) * 10 ^ 18 ≤ - 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 80) - /-- Lower weakening budget, `k ≥ 0` (worst case `x = (m+1) 2^k`, `m = 2^95`). -/ def budgetL (k : Nat) : Bool := decide ((2 ^ 95 + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142 ≤ 2 ^ 95 * (10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * (10 ^ 31 + 9990) * (10 ^ 31 - 10) * 10 ^ 18) -/-- Upper weakening budget, `k < 0` with `j = -k` (exact mantissa `m = x 2^j`). -/ -def budgetUn (j : Nat) : Bool := - decide ((10 ^ 31 + 3382) * (10 ^ 31 - 3383) * (10 ^ 40 : Nat) ^ j * 2 ^ j * 10 ^ 18 ≤ - 10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ j) - /-- Lower weakening budget, `k < 0` (exact mantissa). -/ def budgetLn (j : Nat) : Bool := decide ((10 : Nat) ^ 142 * (2 * (10 ^ 40 + 1)) ^ j ≤ 2 ^ j * (10 ^ 40 : Nat) ^ j * (10 ^ 31 - 3385) * (10 ^ 31 - 3384) * (10 ^ 31 + 9990) * (10 ^ 31 - 10) * 10 ^ 18) -theorem budgetU_all : (List.range 160).all budgetU = true := by - decide +kernel - theorem budgetL_all : (List.range 160).all budgetL = true := by decide +kernel -theorem budgetUn_all : (List.range 96).all budgetUn = true := by - decide +kernel - theorem budgetLn_all : (List.range 96).all budgetLn = true := by decide +kernel -theorem budgetU_le {k : Nat} (hk : k ≤ 159) : - (10 ^ 31 + 3382) * (2 * (10 ^ 40 + 1)) ^ k * (10 ^ 31 - 3383) * 10 ^ 18 ≤ - 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 80 := by - have h := List.all_eq_true.mp budgetU_all k (List.mem_range.mpr (by omega)) - simp only [budgetU, decide_eq_true_eq] at h - exact h - theorem budgetL_le {k : Nat} (hk : k ≤ 159) : (2 ^ 95 + 1) * 2 ^ k * (10 ^ 40 : Nat) ^ k * 10 ^ 142 ≤ 2 ^ 95 * (10 ^ 31 - 3385) * (2 * (10 ^ 40 - 1)) ^ k * (10 ^ 31 - 3384) * @@ -97,13 +69,6 @@ theorem budgetL_le {k : Nat} (hk : k ≤ 159) : simp only [budgetL, decide_eq_true_eq] at h exact h -theorem budgetUn_le {j : Nat} (hj : j ≤ 95) : - (10 ^ 31 + 3382) * (10 ^ 31 - 3383) * (10 ^ 40 : Nat) ^ j * 2 ^ j * 10 ^ 18 ≤ - 10 ^ 80 * (2 * (10 ^ 40 - 1)) ^ j := by - have h := List.all_eq_true.mp budgetUn_all j (List.mem_range.mpr (by omega)) - simp only [budgetUn, decide_eq_true_eq] at h - exact h - theorem budgetLn_le {j : Nat} (hj : j ≤ 95) : (10 : Nat) ^ 142 * (2 * (10 ^ 40 + 1)) ^ j ≤ 2 ^ j * (10 ^ 40 : Nat) ^ j * (10 ^ 31 - 3385) * (10 ^ 31 - 3384) * diff --git a/formal/ln/LnProof/LnProof/Floor/Caps.lean b/formal/ln/LnProof/LnProof/Floor/Caps.lean index 48132e4b6..b0ffb9d16 100644 --- a/formal/ln/LnProof/LnProof/Floor/Caps.lean +++ b/formal/ln/LnProof/LnProof/Floor/Caps.lean @@ -8,10 +8,9 @@ open FormalYul.Preservation /-! # From cell certificates to exponential caps -Converts the kernel-checked nonnegativity of the four main certificate -polynomials into `capUB`/`capLB` facts about the pipeline value `X1`: -integer-scaled statements of `e^(X1/2^99) ≤ (m/S)(1+ε)` and the three -mirrors, with `ε = 42/10^29`, over the common denominator `10^27 · 2^99`. +Converts the kernel-checked lower certificate polynomials into the +`capLB`/`capUB` facts about the pipeline value used by the floor and error +proofs, over the common denominator `10^27 · 2^99`. -/ namespace LnFloorCert @@ -19,16 +18,6 @@ open LnYul Common.Poly Common.Exp set_option maxRecDepth 100000 -theorem evalCertGeUp (m : Nat) : - evalPoly certGeUp (m : Int) = - (EUD + EUN) * KF1 * ((m : Int) * evalPoly geTD (m : Int) ^ 23) + - -(Sc : Int) * EUD * - (23 * (expNumI 22 (evalPoly geTN (m : Int)) (evalPoly geTD (m : Int)) * - evalPoly geTD (m : Int)) + 2 * evalPoly geTN (m : Int) ^ 23) := by - unfold certGeUp - simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, evalPoly_polyPow, - evalPoly_expPolyNum, eval01] - theorem evalCertGeLo (m : Nat) : evalPoly certGeLo (m : Int) = EUD * (Sc : Int) * @@ -38,15 +27,6 @@ theorem evalCertGeLo (m : Nat) : simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, evalPoly_polyPow, evalPoly_expPolyNum, eval01] -theorem evalCertLtUp (m : Nat) : - evalPoly certLtUp (m : Int) = - (EUD + EUN) * ((m : Int) * - expNumI 22 (evalPoly ltTN2b (m : Int)) (evalPoly ltTD2b (m : Int))) + - -EUD * (Sc : Int) * KF * evalPoly ltTD2b (m : Int) ^ 22 := by - unfold certLtUp - simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, evalPoly_polyPow, - evalPoly_expPolyNum, eval01] - theorem evalCertLtLo (m : Nat) : evalPoly certLtLo (m : Int) = (Sc : Int) * EUD * KF1 * evalPoly ltTD (m : Int) ^ 23 + @@ -57,25 +37,12 @@ theorem evalCertLtLo (m : Nat) : simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, evalPoly_polyPow, evalPoly_expPolyNum, eval01] -theorem evalCertGeH (m : Nat) : - evalPoly certGeH (m : Int) = - 24 * evalPoly geTD (m : Int) + -2 * evalPoly geTN (m : Int) := by - show evalPoly (polyAdd (polyScale 24 geTD) (polyScale (-2) geTN)) (m : Int) = _ - simp only [evalPoly_polyAdd, evalPoly_polyScale] - theorem evalCertLtH (m : Nat) : evalPoly certLtH (m : Int) = 24 * evalPoly ltTD (m : Int) + -2 * evalPoly ltTN (m : Int) := by show evalPoly (polyAdd (polyScale 24 ltTD) (polyScale (-2) ltTN)) (m : Int) = _ simp only [evalPoly_polyAdd, evalPoly_polyScale] -theorem evalCertGeTD (m : Nat) : - evalPoly certGeTD (m : Int) = evalPoly geTD (m : Int) + -1 := by - show evalPoly (polyAdd geTD [-1]) (m : Int) = _ - rw [evalPoly_polyAdd] - show _ + ((-1 : Int) + (m : Int) * 0) = _ - omega - theorem evalCertGeTD2 (m : Nat) : evalPoly certGeTD2 (m : Int) = evalPoly geTD2b (m : Int) + -1 := by show evalPoly (polyAdd geTD2b [-1]) (m : Int) = _ @@ -125,53 +92,6 @@ theorem capLB22_of_int {tn td y w : Nat} /-! ## Certificate nonnegativity to caps at the certificate rationals -/ -theorem capGeUp {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) - (hup : 0 ≤ evalPoly certGeUp (m : Int)) : - capUB (evalPoly geTN (m : Int)).toNat (evalPoly geTD (m : Int)).toNat - (m * 10000000000000000000000000003382) - 560227709747861399187319382270000000000000000000000000000000 := by - have hw1 : (56022770974786139918731938273 : Int) ≤ (m : Int) := by - simp only [Sc] at h1; omega - have hw2 : (m : Int) ≤ 79228162514264337593543950335 := by - simp only [MHI] at h2; omega - have hTN0 : 0 ≤ evalPoly geTN (m : Int) := geTN_nonneg hw1 hw2 - have hTD1 : 1 ≤ evalPoly geTD (m : Int) := by - have h := geTD_nonneg hw1 hw2 - rw [evalCertGeTD] at h - omega - have hHc : 2 * evalPoly geTN (m : Int) ≤ 24 * evalPoly geTD (m : Int) := by - have h := geH_nonneg hw1 hw2 - rw [evalCertGeH] at h - omega - have htn : ((evalPoly geTN (m : Int)).toNat : Int) = evalPoly geTN (m : Int) := - Int.toNat_of_nonneg hTN0 - have htd : ((evalPoly geTD (m : Int)).toNat : Int) = evalPoly geTD (m : Int) := - Int.toNat_of_nonneg (by omega) - refine capUB22_of_int (by omega) (by omega) ?_ - rw [htn, htd] - rw [evalCertGeUp] at hup - simp only [EUD, EUN, KF1, Sc] at hup - simp only [Int.natCast_mul] - rw [show ((560227709747861399187319382270000000000000000000000000000000 : Nat) : Int) = 560227709747861399187319382270000000000000000000000000000000 from rfl, - show ((10000000000000000000000000003382 : Nat) : Int) = 10000000000000000000000000003382 from rfl] - have eS : expNumI 22 (evalPoly geTN (m : Int)) (evalPoly geTD (m : Int)) * - (23 * evalPoly geTD (m : Int)) = - 23 * (expNumI 22 (evalPoly geTN (m : Int)) (evalPoly geTD (m : Int)) * - evalPoly geTD (m : Int)) := by - simp only [Int.mul_assoc, Int.mul_comm] - rw [eS] - have eR : (m : Int) * 10000000000000000000000000003382 * - (25852016738884976640000 * evalPoly geTD (m : Int) ^ 23) = - 10000000000000000000000000003382 * 25852016738884976640000 * - ((m : Int) * evalPoly geTD (m : Int) ^ 23) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - rw [eR] - generalize hgET : expNumI 22 (evalPoly geTN (m : Int)) (evalPoly geTD (m : Int)) * - evalPoly geTD (m : Int) = ET at hup ⊢ - generalize hgN23 : evalPoly geTN (m : Int) ^ 23 = N23 at hup ⊢ - generalize hgMT : (m : Int) * evalPoly geTD (m : Int) ^ 23 = MT at hup ⊢ - omega - theorem capGeLo {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) (hlo : 0 ≤ evalPoly certGeLo (m : Int)) : capLB (evalPoly geTN2b (m : Int)).toNat (evalPoly geTD2b (m : Int)).toNat @@ -208,42 +128,6 @@ theorem capGeLo {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) generalize hgMT : (m : Int) * evalPoly geTD2b (m : Int) ^ 22 = MT at hlo ⊢ omega -theorem capLtUp {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) - (hup : 0 ≤ evalPoly certLtUp (m : Int)) : - capLB (evalPoly ltTN2b (m : Int)).toNat (evalPoly ltTD2b (m : Int)).toNat - 560227709747861399187319382270000000000000000000000000000000 - (m * 10000000000000000000000000003382) := by - have hw1 : (39614081257132168796771975168 : Int) ≤ (m : Int) := by - simp only [MLO] at h1; omega - have hw2 : (m : Int) ≤ 56022770974786139918731938181 := by - simp only [Sc] at h2; omega - have hTN0 : 0 ≤ evalPoly ltTN2b (m : Int) := ltTN2_nonneg hw1 hw2 - have hTD1 : 1 ≤ evalPoly ltTD2b (m : Int) := by - have h := ltTD2_nonneg hw1 hw2 - rw [evalCertLtTD2] at h - omega - have htn : ((evalPoly ltTN2b (m : Int)).toNat : Int) = evalPoly ltTN2b (m : Int) := - Int.toNat_of_nonneg hTN0 - have htd : ((evalPoly ltTD2b (m : Int)).toNat : Int) = evalPoly ltTD2b (m : Int) := - Int.toNat_of_nonneg (by omega) - refine capLB22_of_int ?_ - rw [htn, htd] - rw [evalCertLtUp] at hup - simp only [EUD, EUN, KF, Sc] at hup - simp only [Int.natCast_mul] - rw [show ((560227709747861399187319382270000000000000000000000000000000 : Nat) : Int) = 560227709747861399187319382270000000000000000000000000000000 from rfl, - show ((10000000000000000000000000003382 : Nat) : Int) = 10000000000000000000000000003382 from rfl] - have eR : expNumI 22 (evalPoly ltTN2b (m : Int)) (evalPoly ltTD2b (m : Int)) * - ((m : Int) * 10000000000000000000000000003382) = - 10000000000000000000000000003382 * - ((m : Int) * expNumI 22 (evalPoly ltTN2b (m : Int)) (evalPoly ltTD2b (m : Int))) := by - simp only [Int.mul_assoc, Int.mul_comm, Int.mul_left_comm] - rw [eR] - generalize hgME : (m : Int) * expNumI 22 (evalPoly ltTN2b (m : Int)) - (evalPoly ltTD2b (m : Int)) = ME at hup ⊢ - generalize hgT22 : evalPoly ltTD2b (m : Int) ^ 22 = T22 at hup ⊢ - omega - theorem capLtLo {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hlo : 0 ≤ evalPoly certLtLo (m : Int)) : capUB (evalPoly ltTN (m : Int)).toNat (evalPoly ltTD (m : Int)).toNat @@ -353,63 +237,6 @@ theorem x1_nonpos_lt {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) : /-! ## Caps at the pipeline value over the common denominator 10^27 · 2^99 -/ -theorem x1capGeUp {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) - (hup : 0 ≤ evalPoly certGeUp (m : Int)) : - capUB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) - 633825300114114700748351602688000000000000000000000000000 - (m * 10000000000000000000000000003382) - 560227709747861399187319382270000000000000000000000000000000 := by - have hw1 : (56022770974786139918731938273 : Int) ≤ (m : Int) := by - simp only [Sc] at h1; omega - have hw2 : (m : Int) ≤ 79228162514264337593543950335 := by - simp only [MHI] at h2; omega - have hTN0 : 0 ≤ evalPoly geTN (m : Int) := geTN_nonneg hw1 hw2 - have hTD1 : 1 ≤ evalPoly geTD (m : Int) := by - have h := geTD_nonneg hw1 hw2 - rw [evalCertGeTD] at h - omega - refine capUB_arg (q' := (evalPoly geTD (m : Int)).toNat) (by omega) ?_ - (capGeUp h1 h2 hup) - rcases Int.lt_or_le (int256 (x1W (zWord m))) 0 with hneg | hpos - · have h0 : (int256 (x1W (zWord m))).toNat = 0 := by omega - rw [h0] - omega - · have hX1n : ((int256 (x1W (zWord m))).toNat : Int) = int256 (x1W (zWord m)) := - Int.toNat_of_nonneg hpos - have htd : ((evalPoly geTD (m : Int)).toNat : Int) = evalPoly geTD (m : Int) := - Int.toNat_of_nonneg (by omega) - have htn : ((evalPoly geTN (m : Int)).toNat : Int) = evalPoly geTN (m : Int) := - Int.toNat_of_nonneg hTN0 - refine Int.ofNat_le.mp ?_ - simp only [Int.natCast_mul] - rw [show ((1000000000000000000000000000 : Nat) : Int) = - 1000000000000000000000000000 from rfl, - show ((633825300114114700748351602688000000000000000000000000000 : Nat) : Int) = - 633825300114114700748351602688000000000000000000000000000 from rfl, - hX1n, htd, htn] - have hbr := bracket_ge_up h1 h2 - have c1 := mul_le_mul_right_nonneg hbr - (show (0 : Int) ≤ 1000000000000000000000000000 by omega) - have e1 : int256 (x1W (zWord m)) * 1000000000000000000000000000 * - evalPoly geTD (m : Int) = - int256 (x1W (zWord m)) * evalPoly geTD (m : Int) * 1000000000000000000000000000 := by - ring - have e2 : evalPoly geTN (m : Int) * 2 ^ 99 * 1000000000000000000000000000 = - evalPoly geTN (m : Int) * - 633825300114114700748351602688000000000000000000000000000 := by - rw [Int.mul_assoc, show (2 : Int) ^ 99 * 1000000000000000000000000000 = - 633825300114114700748351602688000000000000000000000000000 from by decide] - generalize hp1 : int256 (x1W (zWord m)) * evalPoly geTD (m : Int) * - 1000000000000000000000000000 = A at c1 e1 - generalize hp2 : int256 (x1W (zWord m)) * 1000000000000000000000000000 * - evalPoly geTD (m : Int) = B at e1 ⊢ - generalize hp3 : evalPoly geTN (m : Int) * 2 ^ 99 * - 1000000000000000000000000000 = C at c1 e2 - generalize hp4 : evalPoly geTN (m : Int) * - 633825300114114700748351602688000000000000000000000000000 = D at e2 ⊢ - clear hp1 hp2 hp3 hp4 hbr hpos hX1n htd htn hTN0 hTD1 hw1 hw2 hup h1 h2 - omega - theorem x1capGeLo {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) (hlo : 0 ≤ evalPoly certGeLo (m : Int)) : capLB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) @@ -464,60 +291,6 @@ theorem x1capGeLo {m : Nat} (h1 : Sc + 46 ≤ m) (h2 : m < MHI) clear hp1 hp2 hp3 hp4 hbr hpos hX1n htd htn hTN0 hTD1 hw1 hw2 hlo h1 h2 omega -theorem x1capLtUp {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) - (hup : 0 ≤ evalPoly certLtUp (m : Int)) : - capLB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) - 633825300114114700748351602688000000000000000000000000000 - 560227709747861399187319382270000000000000000000000000000000 - (m * 10000000000000000000000000003382) := by - have hw1 : (39614081257132168796771975168 : Int) ≤ (m : Int) := by - simp only [MLO] at h1; omega - have hw2 : (m : Int) ≤ 56022770974786139918731938181 := by - simp only [Sc] at h2; omega - have hTN0 : 0 ≤ evalPoly ltTN2b (m : Int) := ltTN2_nonneg hw1 hw2 - have hTD1 : 1 ≤ evalPoly ltTD2b (m : Int) := by - have h := ltTD2_nonneg hw1 hw2 - rw [evalCertLtTD2] at h - omega - refine capLB_arg (q' := (evalPoly ltTD2b (m : Int)).toNat) (by omega) ?_ - (capLtUp h1 h2 hup) - have hneg := x1_nonpos_lt h1 h2 - have hX1n : (((-int256 (x1W (zWord m))).toNat : Nat) : Int) = -int256 (x1W (zWord m)) := - Int.toNat_of_nonneg (by omega) - have htd : ((evalPoly ltTD2b (m : Int)).toNat : Int) = evalPoly ltTD2b (m : Int) := - Int.toNat_of_nonneg (by omega) - have htn : ((evalPoly ltTN2b (m : Int)).toNat : Int) = evalPoly ltTN2b (m : Int) := - Int.toNat_of_nonneg hTN0 - refine Int.ofNat_le.mp ?_ - simp only [Int.natCast_mul] - rw [show ((1000000000000000000000000000 : Nat) : Int) = - 1000000000000000000000000000 from rfl, - show ((633825300114114700748351602688000000000000000000000000000 : Nat) : Int) = - 633825300114114700748351602688000000000000000000000000000 from rfl, - hX1n, htd, htn] - have hbr := bracket_lt_lo h1 h2 - have c1 := mul_le_mul_right_nonneg hbr - (show (0 : Int) ≤ 1000000000000000000000000000 by omega) - have e1 : -int256 (x1W (zWord m)) * 1000000000000000000000000000 * - evalPoly ltTD2b (m : Int) = - -int256 (x1W (zWord m)) * evalPoly ltTD2b (m : Int) * 1000000000000000000000000000 := by - ring - have e2 : evalPoly ltTN2b (m : Int) * 2 ^ 99 * 1000000000000000000000000000 = - evalPoly ltTN2b (m : Int) * - 633825300114114700748351602688000000000000000000000000000 := by - rw [Int.mul_assoc, show (2 : Int) ^ 99 * 1000000000000000000000000000 = - 633825300114114700748351602688000000000000000000000000000 from by decide] - generalize hp1 : -int256 (x1W (zWord m)) * evalPoly ltTD2b (m : Int) * - 1000000000000000000000000000 = A at c1 e1 - generalize hp2 : -int256 (x1W (zWord m)) * 1000000000000000000000000000 * - evalPoly ltTD2b (m : Int) = B at e1 ⊢ - generalize hp3 : evalPoly ltTN2b (m : Int) * 2 ^ 99 * - 1000000000000000000000000000 = C at c1 e2 - generalize hp4 : evalPoly ltTN2b (m : Int) * - 633825300114114700748351602688000000000000000000000000000 = D at e2 ⊢ - clear hp1 hp2 hp3 hp4 hbr hneg hX1n htd htn hTN0 hTD1 hw1 hw2 hup h1 h2 - omega - theorem x1capLtLo {m : Nat} (h1 : MLO ≤ m) (h2 : m + 46 ≤ Sc) (hlo : 0 ≤ evalPoly certLtLo (m : Int)) : capUB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean new file mode 100644 index 000000000..ea2998788 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean @@ -0,0 +1,554 @@ +import Mathlib.Analysis.Calculus.Deriv.MeanValue +import LnProof.Floor.CarryIndependent.Atanh +import LnProof.Floor.CarryIndependent.Normalization + +open scoped BigOperators +open Set + +namespace LnFloorCarry + +open Finset LnYul + +set_option maxRecDepth 8192 + +noncomputable section + +private def crossLog (t : Real) : Real := + Real.log (1 + t) - Real.log (1 - t) + +private def crossTerm (t : Real) (j : Nat) : Real := + 2 * t * ((t ^ 2) ^ j / (2 * j + 1)) + +private def derivativeTerm (v : Real) (j : Nat) : Real := + (j + 1) * v ^ j / (2 * (j + 1) + 1) + +private def derivativeSeries (v : Real) : Real := + ∑' j : Nat, derivativeTerm v j + +theorem atanhSeries_summable {v : Real} (hv0 : 0 ≤ v) (hv1 : v < 1) : + Summable (fun j : Nat => v ^ j / (2 * j + 1)) := by + have hgeom := summable_geometric_of_lt_one hv0 hv1 + apply hgeom.of_norm_bounded + intro j + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (pow_nonneg hv0 _) (by positivity))] + have hj0 : (0 : Real) ≤ j := Nat.cast_nonneg j + exact div_le_self (pow_nonneg hv0 _) (by nlinarith) + +theorem atanhSeries_nonneg {v : Real} (hv0 : 0 ≤ v) : + 0 ≤ atanhSeries v := by + unfold atanhSeries + apply tsum_nonneg + intro j + exact div_nonneg (pow_nonneg hv0 _) (by positivity) + +theorem atanhSeries_mono {v w : Real} + (hv0 : 0 ≤ v) (hvw : v ≤ w) (hw1 : w < 1) : + atanhSeries v ≤ atanhSeries w := by + have hw0 : 0 ≤ w := hv0.trans hvw + have hv1 : v < 1 := hvw.trans_lt hw1 + unfold atanhSeries + apply (atanhSeries_summable hv0 hv1).tsum_le_tsum _ + (atanhSeries_summable hw0 hw1) + intro j + exact div_le_div_of_nonneg_right ((pow_le_pow_left₀ hv0 hvw j)) (by positivity) + +theorem crossLog_eq_atanhSeries {t : Real} (ht0 : 0 ≤ t) (ht1 : t < 1) : + crossLog t = 2 * t * atanhSeries (t ^ 2) := by + have htAbs : |t| < 1 := by simpa [abs_of_nonneg ht0] using ht1 + have hlog : HasSum (crossTerm t) (crossLog t) := by + convert Real.hasSum_log_sub_log_of_abs_lt_one htAbs using 1 + ext j + simp only [crossTerm] + ring + rw [← hlog.tsum_eq] + unfold atanhSeries + simpa only [crossTerm] using + (tsum_mul_left (a := 2 * t) + (f := fun j : Nat => (t ^ 2) ^ j / (2 * j + 1))) + +theorem crossLog_hasDerivAt {t : Real} (htm : -1 < t) (htp : t < 1) : + HasDerivAt crossLog (2 / (1 - t ^ 2)) t := by + have hp0 : (1 : Real) + t ≠ 0 := by nlinarith + have hm0 : (1 : Real) - t ≠ 0 := by nlinarith + have hp := (Real.hasDerivAt_log hp0).comp t + ((hasDerivAt_const t 1).add (hasDerivAt_id t)) + have hm := (Real.hasDerivAt_log hm0).comp t + ((hasDerivAt_const t 1).sub (hasDerivAt_id t)) + have hsq : 1 - t ^ 2 ≠ 0 := by nlinarith [sq_nonneg t] + unfold crossLog + convert hp.sub hm using 1 <;> field_simp [hp0, hm0, hsq] <;> ring_nf + +theorem crossLog_increment_le {a t T : Real} + (ha0 : 0 ≤ a) (hat : a ≤ t) (htT : t ≤ T) + (hT0 : 0 < T) (hT1 : T < 1) : + crossLog t - crossLog a ≤ (2 / (1 - T ^ 2)) * (t - a) := by + have hdiffOn : DifferentiableOn Real crossLog (Icc 0 T) := by + intro x hx + have hxm : -1 < x := by nlinarith [hx.1] + have hxp : x < 1 := by nlinarith [hx.2] + exact (crossLog_hasDerivAt hxm hxp).differentiableAt.differentiableWithinAt + apply (convex_Icc (0 : Real) T).image_sub_le_mul_sub_of_deriv_le + hdiffOn.continuousOn (hdiffOn.mono interior_subset) + · intro x hx + have hxI : x ∈ Icc (0 : Real) T := interior_subset hx + have hxm : -1 < x := by nlinarith [hxI.1] + have hxp : x < 1 := by nlinarith [hxI.2] + rw [(crossLog_hasDerivAt hxm hxp).deriv] + have hdx : 0 < 1 - x ^ 2 := by nlinarith [sq_nonneg x] + have hdT : 0 < 1 - T ^ 2 := by nlinarith [sq_nonneg T] + rw [div_le_div_iff₀ hdx hdT] + have hsq := (sq_le_sq₀ hxI.1 hT0.le).2 hxI.2 + nlinarith + · exact ⟨ha0, hat.trans htT⟩ + · exact ⟨ha0.trans hat, htT⟩ + · exact hat + +theorem pow_sub_pow_le_endpoint {v w V : Real} + (hv0 : 0 ≤ v) (hvw : v ≤ w) (hwV : w ≤ V) (n : Nat) : + w ^ (n + 1) - v ^ (n + 1) ≤ + (n + 1) * V ^ n * (w - v) := by + induction n with + | zero => norm_num + | succ n ih => + have hw0 : 0 ≤ w := hv0.trans hvw + have hV0 : 0 ≤ V := hw0.trans hwV + have hstep : + w ^ (n + 2) - v ^ (n + 2) = + w * (w ^ (n + 1) - v ^ (n + 1)) + v ^ (n + 1) * (w - v) := by + ring + rw [hstep] + have h1 := mul_le_mul_of_nonneg_left ih hw0 + have hwPow : w * V ^ n ≤ V ^ (n + 1) := by + simpa only [pow_succ, mul_comm] using + mul_le_mul_of_nonneg_right hwV (pow_nonneg hV0 n) + have hvPow : v ^ (n + 1) ≤ V ^ (n + 1) := by + exact pow_le_pow_left₀ hv0 (hvw.trans hwV) _ + have hdelta : 0 ≤ w - v := sub_nonneg.mpr hvw + have hcoef0 : (0 : Real) ≤ (n : Real) + 1 := by + exact add_nonneg (Nat.cast_nonneg n) zero_le_one + have hfirst : + w * (((n : Real) + 1) * V ^ n * (w - v)) ≤ + ((n : Real) + 1) * V ^ (n + 1) * (w - v) := by + calc + w * (((n : Real) + 1) * V ^ n * (w - v)) = + ((n : Real) + 1) * (w * V ^ n) * (w - v) := by ring + _ ≤ ((n : Real) + 1) * V ^ (n + 1) * (w - v) := + mul_le_mul_of_nonneg_right + (mul_le_mul_of_nonneg_left hwPow hcoef0) hdelta + have hsecond : + v ^ (n + 1) * (w - v) ≤ V ^ (n + 1) * (w - v) := + mul_le_mul_of_nonneg_right hvPow hdelta + have hsuccCast : (n : Real) + 2 = (((n + 1 : Nat) : Real) + 1) := by + rw [Nat.cast_add, Nat.cast_one] + ring + calc + w * (w ^ (n + 1) - v ^ (n + 1)) + v ^ (n + 1) * (w - v) ≤ + w * (((n : Real) + 1) * V ^ n * (w - v)) + + v ^ (n + 1) * (w - v) := add_le_add_right h1 _ + _ ≤ ((n : Real) + 1) * V ^ (n + 1) * (w - v) + + V ^ (n + 1) * (w - v) := add_le_add hfirst hsecond + _ = ((n : Real) + 2) * V ^ (n + 1) * (w - v) := by ring + _ = (((n + 1 : Nat) : Real) + 1) * V ^ (n + 1) * (w - v) := + congrArg (fun c : Real => c * V ^ (n + 1) * (w - v)) hsuccCast + +theorem derivativeSeries_summable {v : Real} (hv0 : 0 ≤ v) (hv1 : v < 1) : + Summable (derivativeTerm v) := by + have habs : ‖v‖ < 1 := by simpa [Real.norm_eq_abs, abs_of_nonneg hv0] using hv1 + have hweighted : Summable (fun j : Nat => (j + 1 : Real) * v ^ j) := by + have hlinear := summable_pow_mul_geometric_of_norm_lt_one 1 habs + have hgeom := summable_geometric_of_lt_one hv0 hv1 + convert hlinear.add hgeom using 1 + ext j + norm_num + ring + apply hweighted.of_norm_bounded + intro j + have hj0 : (0 : Real) ≤ j := Nat.cast_nonneg j + have hcoef0 : (0 : Real) ≤ (j : Real) + 1 := add_nonneg hj0 zero_le_one + have hnum0 : 0 ≤ ((j : Real) + 1) * v ^ j := + mul_nonneg hcoef0 (pow_nonneg hv0 j) + have hden0 : 0 ≤ 2 * ((j : Real) + 1) + 1 := by nlinarith + unfold derivativeTerm + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg hnum0 hden0)] + exact div_le_self hnum0 (by nlinarith) + +theorem atanhSeries_increment_le {v w V : Real} + (hv0 : 0 ≤ v) (hvw : v ≤ w) (hwV : w ≤ V) (hV1 : V < 1) : + atanhSeries w - atanhSeries v ≤ (w - v) * derivativeSeries V := by + have hw0 : 0 ≤ w := hv0.trans hvw + have hV0 : 0 ≤ V := hw0.trans hwV + have hw1 : w < 1 := hwV.trans_lt hV1 + have hv1 : v < 1 := hvw.trans_lt hw1 + have hsw := atanhSeries_summable hw0 hw1 + have hsv := atanhSeries_summable hv0 hv1 + have hdiff := hsw.sub hsv + have hderiv := derivativeSeries_summable hV0 hV1 + have htail : Summable (fun j : Nat => + (w ^ (j + 1) - v ^ (j + 1)) / (2 * (j + 1) + 1)) := by + have hs := (summable_nat_add_iff 1).2 hdiff + convert hs using 1 + ext j + push_cast + ring + have htailLe : + (∑' j : Nat, + (w ^ (j + 1) - v ^ (j + 1)) / (2 * (j + 1) + 1)) ≤ + ∑' j : Nat, (w - v) * derivativeTerm V j := by + apply htail.tsum_le_tsum _ (hderiv.mul_left (w - v)) + intro j + unfold derivativeTerm + have hpow := pow_sub_pow_le_endpoint hv0 hvw hwV j + have hj0 : (0 : Real) ≤ j := Nat.cast_nonneg j + have hden : (0 : Real) ≤ 2 * ((j : Real) + 1) + 1 := by nlinarith + calc + (w ^ (j + 1) - v ^ (j + 1)) / (2 * (j + 1) + 1) ≤ + (((j : Real) + 1) * V ^ j * (w - v)) / (2 * (j + 1) + 1) := + div_le_div_of_nonneg_right hpow hden + _ = (w - v) * ((j + 1) * V ^ j / (2 * (j + 1) + 1)) := by ring + have hshiftEq : + (∑' j : Nat, + (w ^ (j + 1) / (2 * (j + 1) + 1) - + v ^ (j + 1) / (2 * (j + 1) + 1))) = + ∑' j : Nat, + (w ^ (j + 1) - v ^ (j + 1)) / (2 * (j + 1) + 1) := by + apply tsum_congr + intro j + ring + unfold atanhSeries derivativeSeries + rw [← hsw.tsum_sub hsv, ← hdiff.sum_add_tsum_nat_add 1] + simp only [sum_range_succ, sum_range_zero, zero_add, pow_zero, sub_self] + simp only [Nat.cast_add, Nat.cast_one] + rw [hshiftEq, ← tsum_mul_left] + exact htailLe + +theorem derivativeSeries_endpoint_le : + derivativeSeries endpointV ≤ endpointDerivative := by + have hV0 : 0 ≤ endpointV := by unfold endpointV; positivity + have hV1 : endpointV < 1 := by + norm_num [endpointV, endpointZ, endpointZWord, wordQ100] + have hs := derivativeSeries_summable hV0 hV1 + have htail := (summable_nat_add_iff 48).2 hs + have hgeom : Summable (fun j : Nat => + endpointV ^ 48 / 2 * endpointV ^ j) := + (summable_geometric_of_lt_one hV0 hV1).mul_left (endpointV ^ 48 / 2) + have htailLe : + (∑' j : Nat, derivativeTerm endpointV (j + 48)) ≤ + ∑' j : Nat, endpointV ^ 48 / 2 * endpointV ^ j := by + apply htail.tsum_le_tsum _ hgeom + intro j + unfold derivativeTerm + have hj0 : (0 : Real) ≤ j := Nat.cast_nonneg j + have hcoef : ((j : Real) + 49) / (2 * ((j : Real) + 49) + 1) ≤ 1 / 2 := by + rw [div_le_iff₀ (by positivity)] + nlinarith + rw [pow_add] + push_cast + calc + ((j : Real) + 48 + 1) * (endpointV ^ j * endpointV ^ 48) / + (2 * ((j : Real) + 48 + 1) + 1) = + (((j : Real) + 49) / (2 * ((j : Real) + 49) + 1)) * + (endpointV ^ 48 * endpointV ^ j) := by ring + _ ≤ (1 / 2) * (endpointV ^ 48 * endpointV ^ j) := + mul_le_mul_of_nonneg_right hcoef (mul_nonneg (pow_nonneg hV0 _) (pow_nonneg hV0 _)) + _ = endpointV ^ 48 / 2 * endpointV ^ j := by ring + unfold derivativeSeries endpointDerivative + rw [← hs.sum_add_tsum_nat_add 48] + calc + (∑ j ∈ range 48, derivativeTerm endpointV j) + + ∑' j : Nat, derivativeTerm endpointV (j + 48) ≤ + (∑ j ∈ range 48, derivativeTerm endpointV j) + + ∑' j : Nat, endpointV ^ 48 / 2 * endpointV ^ j := + add_le_add_left htailLe _ + _ = (∑ j ∈ range 48, + (j + 1) * endpointV ^ j / (2 * (j + 1) + 1)) + + endpointV ^ 48 / (2 * (1 - endpointV)) := by + rw [tsum_mul_left, tsum_geometric_of_lt_one hV0 hV1] + simp only [derivativeTerm] + field_simp [show (1 : Real) - endpointV ≠ 0 by linarith] + +theorem endpointDerivative_nonneg : 0 ≤ endpointDerivative := by + have hV0 : 0 ≤ endpointV := by unfold endpointV; positivity + have hseries0 : 0 ≤ derivativeSeries endpointV := by + unfold derivativeSeries derivativeTerm + apply tsum_nonneg + intro j + exact div_nonneg + (mul_nonneg (add_nonneg (Nat.cast_nonneg j) zero_le_one) (pow_nonneg hV0 j)) + (by positivity) + exact hseries0.trans derivativeSeries_endpoint_le + +theorem low_log_error_lt_components {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + rayScale * (lowShadow m - Real.log ((m : Real) / Sc)) < + approximationTerm m + hornerTerm m + zFloorBudget + uFloorBudget + + closingDivisionBudget := by + let t := ((Sc : Real) - m) / ((Sc : Real) + m) + let a := normalizedZ m + let v := normalizedU m + have hm : 0 < m := (by norm_num : 0 < 2 ^ 95).trans_le hmlo + have hma := low_z_floor hmlo hmsc + have huv := low_u_floor hmlo hmsc + obtain ⟨ha0, haEnd, htEnd, hEnd1⟩ := low_endpoint_bounds hmlo hmsc + have hEnd0 : 0 < endpointT := by norm_num [endpointT, Sc] + have ht0 : 0 ≤ t := by + dsimp [t] + have hmSc : (m : Real) ≤ Sc := by exact_mod_cast Nat.le_of_lt hmsc + exact div_nonneg (sub_nonneg.mpr hmSc) + (add_nonneg (Nat.cast_nonneg Sc) (Nat.cast_nonneg m)) + have ha1 : a < 1 := haEnd.trans_lt (by + norm_num [endpointZ, endpointZWord, wordQ100]) + have hcrossZ := crossLog_increment_le ha0 hma.1 htEnd hEnd0 hEnd1 + have hmaUpper : t < a + 1 / wordQ100 := by + simpa only [t, a] using hma.2 + have hdeltaZ : t - a < 1 / wordQ100 := by + apply sub_lt_iff_lt_add.mpr + simpa only [add_comm] using hmaUpper + have hcoefZ : 0 < 2 / (1 - endpointT ^ 2) := by + have hsq : endpointT ^ 2 < 1 := by nlinarith [sq_nonneg endpointT] + exact div_pos (by norm_num) (sub_pos.mpr hsq) + have hcrossZStrict : + crossLog t < crossLog a + 2 / wordQ100 / (1 - endpointT ^ 2) := by + have hscaled := mul_lt_mul_of_pos_left hdeltaZ hcoefZ + have hcrossZ' : crossLog t - crossLog a ≤ + (2 / (1 - endpointT ^ 2)) * (t - a) := by + simpa only [t, a] using hcrossZ + have hcrossLe := sub_le_iff_le_add.mp hcrossZ' + calc + crossLog t ≤ crossLog a + (2 / (1 - endpointT ^ 2)) * (t - a) := + (by simpa only [add_comm] using hcrossLe) + _ < crossLog a + (2 / (1 - endpointT ^ 2)) * (1 / wordQ100) := + add_lt_add_left hscaled _ + _ = crossLog a + 2 / wordQ100 / (1 - endpointT ^ 2) := by ring + have hV0 : 0 ≤ endpointV := by + unfold endpointV + exact sq_nonneg endpointZ + have hV1 : endpointV < 1 := by + norm_num [endpointV, endpointZ, endpointZWord, wordQ100] + have haSqEnd : a ^ 2 ≤ endpointV := by + unfold endpointV + have hEndpointZ0 : 0 ≤ endpointZ := by + unfold endpointZ + exact div_nonneg (Nat.cast_nonneg endpointZWord) (Nat.cast_nonneg wordQ100) + exact (sq_le_sq₀ ha0 hEndpointZ0).2 haEnd + have hv0 : 0 ≤ v := by + dsimp [v] + unfold normalizedU + exact div_nonneg (Nat.cast_nonneg _) (Nat.cast_nonneg wordQ96) + have hseries := atanhSeries_increment_le hv0 huv.1 haSqEnd hV1 + have hseriesEnd := derivativeSeries_endpoint_le + have huvUpper : a ^ 2 < v + 1 / wordQ96 := by + simpa only [a, v] using huv.2 + have hdeltaU : a ^ 2 - v < 1 / wordQ96 := by + apply sub_lt_iff_lt_add.mpr + simpa only [add_comm] using huvUpper + have hseriesLe : + atanhSeries (a ^ 2) ≤ atanhSeries v + endpointDerivative / wordQ96 := by + have hscaled : (a ^ 2 - v) * derivativeSeries endpointV ≤ + (1 / wordQ96) * endpointDerivative := by + calc + (a ^ 2 - v) * derivativeSeries endpointV ≤ + (a ^ 2 - v) * endpointDerivative := + mul_le_mul_of_nonneg_left hseriesEnd (sub_nonneg.mpr huv.1) + _ ≤ (1 / wordQ96) * endpointDerivative := + mul_le_mul_of_nonneg_right hdeltaU.le endpointDerivative_nonneg + calc + atanhSeries (a ^ 2) ≤ + atanhSeries v + (a ^ 2 - v) * derivativeSeries endpointV := + (by + have hseries' : atanhSeries (a ^ 2) - atanhSeries v ≤ + (a ^ 2 - v) * derivativeSeries endpointV := by + simpa only [a] using hseries + have hseriesAdd := sub_le_iff_le_add.mp hseries' + simpa only [add_comm] using hseriesAdd) + _ ≤ atanhSeries v + (1 / wordQ96) * endpointDerivative := + add_le_add_left hscaled _ + _ = atanhSeries v + endpointDerivative / wordQ96 := by ring + have hcrossA := crossLog_eq_atanhSeries ha0 ha1 + have hlogCross : -Real.log ((m : Real) / (Sc : Real)) = crossLog t := by + simpa [t, crossLog] using neg_log_ratio_eq_log_sub_log + (m := (m : Real)) (S := (Sc : Real)) (by exact_mod_cast hm) + (by exact_mod_cast Nat.le_of_lt hmsc) + have hlog : + -Real.log ((m : Real) / (Sc : Real)) < + 2 * a * atanhSeries v + + 2 / wordQ100 / (1 - endpointT ^ 2) + + 2 * a * endpointDerivative / wordQ96 := by + rw [hlogCross] + calc + crossLog t < crossLog a + 2 / wordQ100 / (1 - endpointT ^ 2) := + hcrossZStrict + _ = 2 * a * atanhSeries (a ^ 2) + + 2 / wordQ100 / (1 - endpointT ^ 2) := by rw [hcrossA] + _ ≤ 2 * a * atanhSeries v + + 2 / wordQ100 / (1 - endpointT ^ 2) + + 2 * a * endpointDerivative / wordQ96 := by + have hfactor0 : (0 : Real) ≤ 2 * a := mul_nonneg (by norm_num) ha0 + have hmulSeries := mul_le_mul_of_nonneg_left hseriesLe hfactor0 + calc + 2 * a * atanhSeries (a ^ 2) + 2 / wordQ100 / (1 - endpointT ^ 2) ≤ + 2 * a * (atanhSeries v + endpointDerivative / wordQ96) + + 2 / wordQ100 / (1 - endpointT ^ 2) := + add_le_add_right hmulSeries _ + _ = 2 * a * atanhSeries v + 2 / wordQ100 / (1 - endpointT ^ 2) + + 2 * a * endpointDerivative / wordQ96 := by ring + have huBudget : + 2 * rayScale * a * endpointDerivative / wordQ96 ≤ uFloorBudget := by + unfold uFloorBudget + have hnonneg : 0 ≤ 2 * rayScale * endpointDerivative / wordQ96 := + div_nonneg + (mul_nonneg + (mul_nonneg (by norm_num) (Nat.cast_nonneg rayScale)) + endpointDerivative_nonneg) + (Nat.cast_nonneg wordQ96) + calc + 2 * rayScale * a * endpointDerivative / wordQ96 = + a * (2 * rayScale * endpointDerivative / wordQ96) := by ring + _ ≤ endpointZ * (2 * rayScale * endpointDerivative / wordQ96) := + mul_le_mul_of_nonneg_right haEnd hnonneg + _ = 2 * rayScale * endpointZ * endpointDerivative / wordQ96 := by ring + unfold lowShadow approximationTerm hornerTerm zFloorBudget closingDivisionBudget + dsimp [a, v] at hlog huBudget ⊢ + have hray : (0 : Real) < rayScale := by norm_num [rayScale] + have hscaledLog := mul_lt_mul_of_pos_left hlog hray + have hshiftedLog := add_lt_add_right hscaledLog + (-2 * rayScale * normalizedZ m * shadowRatio (uWord (zWord m)) + + 2 * rayScale / wordQ100) + calc + (rayScale : Real) * + (-2 * normalizedZ m * shadowRatio (uWord (zWord m)) + 2 / wordQ100 - + Real.log ((m : Real) / (Sc : Real))) < + 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + + 2 * rayScale * normalizedZ m * endpointDerivative / wordQ96 + + 2 * rayScale / wordQ100 := by + calc + (rayScale : Real) * + (-2 * normalizedZ m * shadowRatio (uWord (zWord m)) + 2 / wordQ100 - + Real.log ((m : Real) / (Sc : Real))) = + (rayScale : Real) * (-Real.log ((m : Real) / (Sc : Real))) + + (-2 * rayScale * normalizedZ m * shadowRatio (uWord (zWord m)) + + 2 * rayScale / wordQ100) := by ring + _ < (rayScale : Real) * + (2 * normalizedZ m * atanhSeries (normalizedU m) + + 2 / wordQ100 / (1 - endpointT ^ 2) + + 2 * normalizedZ m * endpointDerivative / wordQ96) + + (-2 * rayScale * normalizedZ m * shadowRatio (uWord (zWord m)) + + 2 * rayScale / wordQ100) := hshiftedLog + _ = 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + + 2 * rayScale * normalizedZ m * endpointDerivative / wordQ96 + + 2 * rayScale / wordQ100 := by ring + _ ≤ 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + + uFloorBudget + 2 * rayScale / wordQ100 := by + let common := + 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + + 2 * rayScale / wordQ100 + calc + 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + + 2 * rayScale * normalizedZ m * endpointDerivative / wordQ96 + + 2 * rayScale / wordQ100 = + common + 2 * rayScale * normalizedZ m * endpointDerivative / wordQ96 := by + dsimp [common] + ring + _ ≤ common + uFloorBudget := add_le_add_left huBudget common + _ = 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + + uFloorBudget + 2 * rayScale / wordQ100 := by + dsimp [common] + ring + +theorem lowShadow_core_bound {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) + (hApprox : approximationTerm m ≤ approximationBudget) + (hHorner : hornerTerm m ≤ hornerBudget) : + rayScale * (lowShadow m - Real.log ((m : Real) / Sc)) < coreErrorLimit := by + have hparts := low_log_error_lt_components hmlo hmsc + calc + rayScale * (lowShadow m - Real.log ((m : Real) / Sc)) < + approximationTerm m + hornerTerm m + zFloorBudget + uFloorBudget + + closingDivisionBudget := hparts + _ ≤ approximationBudget + hornerBudget + zFloorBudget + uFloorBudget + + closingDivisionBudget := by linarith + _ < coreErrorLimit := by + have htotal := totalBudget_lt_coreErrorLimit + linarith + +theorem high_log_error_le_approximationTerm {m : Nat} + (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + rayScale * (highShadow m - Real.log ((m : Real) / Sc)) ≤ + highApproximationTerm m := by + let t := ((m : Real) - Sc) / ((m : Real) + Sc) + let b := highNormalizedZ m + let v := normalizedU m + obtain ⟨hb0, hbt, ht1⟩ := high_endpoint_bounds hscm hmhi + have huv := high_u_floor hscm hmhi + have ht0 : 0 ≤ t := by + dsimp [t] + have hscmR : (Sc : Real) ≤ m := by exact_mod_cast hscm + exact div_nonneg (sub_nonneg.mpr hscmR) + (add_nonneg (Nat.cast_nonneg m) (Nat.cast_nonneg Sc)) + have hbtSq : b ^ 2 ≤ t ^ 2 := (sq_le_sq₀ hb0 ht0).2 hbt + have htSq1 : t ^ 2 < 1 := by nlinarith [sq_nonneg t] + have hv0 : 0 ≤ v := by + dsimp [v] + unfold normalizedU + exact div_nonneg (Nat.cast_nonneg _) (Nat.cast_nonneg wordQ96) + have hseries : atanhSeries v ≤ atanhSeries (t ^ 2) := + atanhSeries_mono hv0 (huv.1.trans hbtSq) htSq1 + have hseries0 : 0 ≤ atanhSeries v := atanhSeries_nonneg hv0 + have hmul : b * atanhSeries v ≤ t * atanhSeries (t ^ 2) := + mul_le_mul hbt hseries hseries0 ht0 + have hSc : (0 : Real) < Sc := by norm_num [Sc] + have hscmR : (Sc : Real) ≤ m := by exact_mod_cast hscm + have hlogCross : Real.log ((m : Real) / (Sc : Real)) = crossLog t := by + simpa [t, crossLog] using log_ratio_eq_log_sub_log + (m := (m : Real)) (S := (Sc : Real)) hSc hscmR + have hcrossT := crossLog_eq_atanhSeries ht0 ht1 + have hlog : 2 * b * atanhSeries v ≤ Real.log ((m : Real) / (Sc : Real)) := by + rw [hlogCross, hcrossT] + have htwice := mul_le_mul_of_nonneg_left hmul (by norm_num : (0 : Real) ≤ 2) + simpa only [mul_assoc] using htwice + have hbase : + 2 * b * exactRatio (uWord (zWord m)) - Real.log ((m : Real) / (Sc : Real)) ≤ + 2 * b * (exactRatio (uWord (zWord m)) - atanhSeries v) := by + calc + 2 * b * exactRatio (uWord (zWord m)) - Real.log ((m : Real) / (Sc : Real)) ≤ + 2 * b * exactRatio (uWord (zWord m)) - 2 * b * atanhSeries v := + sub_le_sub_left hlog _ + _ = 2 * b * (exactRatio (uWord (zWord m)) - atanhSeries v) := by ring + have hscaled := mul_le_mul_of_nonneg_left hbase + (Nat.cast_nonneg rayScale) + simpa [highShadow, highApproximationTerm, b, v, mul_assoc, mul_comm, mul_left_comm] + using hscaled + +theorem highShadow_core_bound {m : Nat} + (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) + (hApprox : highApproximationTerm m ≤ approximationBudget) : + rayScale * (highShadow m - Real.log ((m : Real) / Sc)) < coreErrorLimit := by + have herror := high_log_error_le_approximationTerm hscm hmhi + exact herror.trans_lt (hApprox.trans_lt approximationBudget_lt_coreErrorLimit) + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Approximation.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Approximation.lean new file mode 100644 index 000000000..73037c71a --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Approximation.lean @@ -0,0 +1,77 @@ +import LnProof.Model.Body + +namespace LnFloorCarry + +open Common.Poly LnYul + +def approximationScale : Nat := 2 ^ 96 +def approximationMaxU : Nat := Uc +def approximationTerms : Nat := 42 + +def approximationOddProduct : Int := + (List.range approximationTerms).foldl + (fun a (j : Nat) => a * (2 * (j : Int) + 1)) 1 + +def approximationTaylorDen : Int := + 85 * approximationOddProduct * + (approximationScale : Int) ^ (approximationTerms - 1) + +def approximationTaylorNum : List Int := + (List.range approximationTerms).map fun (j : Nat) => + 85 * (approximationOddProduct / (2 * (j : Int) + 1)) * + (approximationScale : Int) ^ (approximationTerms - 1 - j) + +def approximationTailPower : List Int := + List.replicate approximationTerms 0 ++ [1] + +def approximationOneMinus : List Int := [(approximationScale : Int), -1] +def approximationRationalDen : List Int := polyNeg QQc +def approximationRationalNum : List Int := polyScale (2 ^ 28) PPc + +def approximationUpperNum : List Int := + polyAdd + (polyMul approximationTaylorNum approximationOneMinus) + (polyScale approximationOddProduct approximationTailPower) + +def approximationUpperDen : List Int := + polyScale approximationTaylorDen approximationOneMinus + +def approximationLowGapNum : List Int := + polyAdd + (polyMul approximationUpperNum approximationRationalDen) + (polyScale (-1) + (polyMul approximationRationalNum approximationUpperDen)) + +def approximationLowGapDen : List Int := + polyMul approximationUpperDen approximationRationalDen + +def approximationHighGapNum : List Int := + polyAdd + (polyScale approximationTaylorDen approximationRationalNum) + (polyScale (-1) + (polyMul approximationTaylorNum approximationRationalDen)) + +def approximationHighGapDen : List Int := + polyScale approximationTaylorDen approximationRationalDen + +def approximationErrorNum : Nat := 323661607720025115242513 +def approximationErrorDen : Nat := 10 ^ 24 +def approximationEnvelopeDen : Nat := 10 ^ 60 + +def approximationEnvelopeSquareBudget : Nat := + approximationErrorNum ^ 2 * 10 ^ 18 * 2 ^ 94 + +def approximationEnvelopeCandidate (hi a : Nat) : Prop := + a ^ 2 * (hi + 1) ≤ approximationEnvelopeSquareBudget + +def approximationLowCert (a : Nat) : List Int := + polyAdd + (polyScale a approximationLowGapDen) + (polyScale (-(approximationEnvelopeDen : Int)) approximationLowGapNum) + +def approximationHighCert (a : Nat) : List Int := + polyAdd + (polyScale a approximationHighGapDen) + (polyScale (-(approximationEnvelopeDen : Int)) approximationHighGapNum) + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean new file mode 100644 index 000000000..cc6ece621 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean @@ -0,0 +1,304 @@ +import LnProof.Floor.CarryIndependent.ApproximationSound +import LnProof.Floor.CarryIndependent.Atanh +import LnProof.Mono.Certs +import Mathlib.Algebra.BigOperators.Field +import Mathlib.Algebra.BigOperators.Group.List.Lemmas + +open scoped BigOperators + +namespace LnFloorCarry + +open Finset Common.Poly LnYul + +set_option maxRecDepth 100000 + +noncomputable section + +private theorem evalPoly_append (p q : List Int) (x : Int) : + evalPoly (p ++ q) x = evalPoly p x + x ^ p.length * evalPoly q x := by + induction p with + | nil => simp [evalPoly] + | cons c p ih => + simp only [List.cons_append, evalPoly, List.length_cons, ih] + rw [pow_succ] + ring + +private theorem evalPoly_map_range (f : Nat → Int) (n : Nat) (x : Int) : + evalPoly ((List.range n).map f) x = + ∑ j ∈ range n, f j * x ^ j := by + induction n with + | zero => simp [evalPoly] + | succ n ih => + simp only [List.range_succ, List.map_append, List.map_singleton, + evalPoly_append, List.length_map, List.length_range, ih, evalPoly, + Finset.sum_range_succ] + ring + +private theorem evalPoly_replicate_zero (n : Nat) (x : Int) : + evalPoly (List.replicate n 0) x = 0 := by + induction n with + | zero => simp [evalPoly] + | succ n ih => + rw [List.replicate_succ, evalPoly, ih] + ring + +private theorem evalPoly_tailPower (n : Nat) (x : Int) : + evalPoly (List.replicate n 0 ++ [1]) x = x ^ n := by + rw [evalPoly_append, evalPoly_replicate_zero] + simp [evalPoly] + +private theorem evalPoly_oneMinus (x : Int) : + evalPoly approximationOneMinus x = (approximationScale : Int) - x := by + simp [approximationOneMinus, evalPoly, sub_eq_add_neg] + +private theorem approximationOddProduct_eq_prod : + approximationOddProduct = + ((List.range approximationTerms).map fun j : Nat => + 2 * (j : Int) + 1).prod := by + unfold approximationOddProduct + symm + rw [List.prod_eq_foldl, List.foldl_map] + +private theorem oddFactorList_pos (l : List Nat) : + 0 < (l.map fun j : Nat => 2 * (j : Int) + 1).prod := by + induction l with + | nil => simp + | cons j l ih => + simp only [List.map_cons, List.prod_cons] + exact mul_pos (by omega) ih + +private theorem approximationOddProduct_pos : 0 < approximationOddProduct := by + rw [approximationOddProduct_eq_prod] + exact oddFactorList_pos _ + +private theorem approximationOddFactor_dvd {j : Nat} + (hj : j < approximationTerms) : + 2 * (j : Int) + 1 ∣ approximationOddProduct := by + rw [approximationOddProduct_eq_prod] + apply List.dvd_prod + exact List.mem_map_of_mem (List.mem_range.mpr hj) + +private theorem approximationTaylor_term_identity + {q p scale value factor : Real} {a b j : Nat} + (hp : p ≠ 0) (hscale : scale ≠ 0) (hfactor : factor ≠ 0) + (hquotient : q * factor = p) (hexponent : a + j = b) : + (85 * q * scale ^ a * value ^ j) / (85 * p * scale ^ b) = + (value / scale) ^ j / factor := by + rw [div_pow, div_div] + apply (div_eq_div_iff + (mul_ne_zero (mul_ne_zero (by norm_num) hp) (pow_ne_zero _ hscale)) + (mul_ne_zero (pow_ne_zero _ hscale) hfactor)).2 + rw [← hexponent, pow_add, ← hquotient] + ring + +theorem approximationTaylor_eval (u : Nat) : + (evalPoly approximationTaylorNum (u : Int) : Real) / + approximationTaylorDen = + ∑ j ∈ range approximationTerms, + ((u : Real) / approximationScale) ^ j / (2 * j + 1) := by + rw [approximationTaylorNum, evalPoly_map_range, approximationTaylorDen] + push_cast + rw [Finset.sum_div] + apply Finset.sum_congr rfl + intro j hj + have hjlt : j < approximationTerms := Finset.mem_range.mp hj + have hquotientI : + (approximationOddProduct / (2 * (j : Int) + 1)) * + (2 * (j : Int) + 1) = approximationOddProduct := + Int.ediv_mul_cancel (approximationOddFactor_dvd hjlt) + have hquotientR : + ((approximationOddProduct / (2 * (j : Int) + 1) : Int) : Real) * + (2 * (j : Real) + 1) = approximationOddProduct := by + exact_mod_cast hquotientI + have hp : (approximationOddProduct : Real) ≠ 0 := by + exact_mod_cast approximationOddProduct_pos.ne' + have hscale : (approximationScale : Real) ≠ 0 := by + norm_num [approximationScale] + have hfactor : (2 * (j : Real) + 1) ≠ 0 := by positivity + have hexponent : + approximationTerms - 1 - j + j = approximationTerms - 1 := by + omega + exact approximationTaylor_term_identity hp hscale hfactor hquotientR hexponent + +theorem approximationUpper_eval (u : Nat) (hu : u < approximationScale) : + (evalPoly approximationUpperNum (u : Int) : Real) / + evalPoly approximationUpperDen (u : Int) = + (∑ j ∈ range approximationTerms, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) + + ((u : Real) / approximationScale) ^ approximationTerms / + ((2 * approximationTerms + 1) * + (1 - (u : Real) / approximationScale)) := by + have hTaylor := approximationTaylor_eval u + have hTaylorDen : (approximationTaylorDen : Real) ≠ 0 := by + exact_mod_cast (show approximationTaylorDen ≠ 0 by decide) + have hScale : (approximationScale : Real) ≠ 0 := by + norm_num [approximationScale] + have hGap : (approximationScale : Real) - u ≠ 0 := by + have huR : (u : Real) < approximationScale := by exact_mod_cast hu + linarith + simp only [approximationUpperNum, approximationUpperDen, + evalPoly_polyAdd, evalPoly_polyMul, evalPoly_polyScale, + evalPoly_oneMinus, approximationTailPower, evalPoly_tailPower] + push_cast + rw [← hTaylor] + field_simp [hTaylorDen, hScale, hGap] <;> + norm_num [approximationTaylorDen, approximationOddProduct, + approximationScale, approximationTerms] <;> ring + +theorem approximationUpperDen_pos {u : Nat} (hu : u ≤ approximationMaxU) : + 0 < evalPoly approximationUpperDen (u : Int) := by + have hTaylorDen : 0 < approximationTaylorDen := by decide + have huScale : u < approximationScale := + hu.trans_lt (by decide) + have huScaleI : (u : Int) < approximationScale := by exact_mod_cast huScale + simp only [approximationUpperDen, evalPoly_polyScale, + evalPoly_oneMinus] + exact Int.mul_pos hTaylorDen (by omega) + +theorem approximationRationalDen_pos {u : Nat} (hu : u ≤ approximationMaxU) : + 0 < evalPoly approximationRationalDen (u : Int) := by + have huCast : (u : Int) ≤ (approximationMaxU : Int) := by + exact_mod_cast hu + have huI : (u : Int) ≤ UcI := by + simpa [approximationMaxU, Uc, UcI] using huCast + have hq := certQ_all (v := (u : Int)) (by positivity) huI + have hslop : 0 < SLOPQc := by norm_num [SLOPQc] + simp only [approximationRationalDen, evalPoly_polyNeg] + omega + +theorem approximationRational_eval (u : Nat) (hu : u ≤ approximationMaxU) : + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) = + ((evalPoly PPc (u : Int) : Real) / 2 ^ 358) / + ((-evalPoly QQc (u : Int) : Int) / 2 ^ 386) := by + have hden := approximationRationalDen_pos hu + have hq : (0 : Real) < (-evalPoly QQc (u : Int) : Int) := by + rw [approximationRationalDen, evalPoly_polyNeg] at hden + exact_mod_cast hden + have h358 : (2 ^ 358 : Real) ≠ 0 := by positivity + have h386 : (2 ^ 386 : Real) ≠ 0 := by positivity + have hqScaled : ((-evalPoly QQc (u : Int) : Int) / (2 ^ 386 : Real)) ≠ 0 := + div_ne_zero hq.ne' h386 + simp only [approximationRationalNum, approximationRationalDen, + evalPoly_polyScale, evalPoly_polyNeg] + push_cast at hq hqScaled ⊢ + apply (div_eq_div_iff hq.ne' hqScaled).2 + field_simp [h358, h386] <;> norm_num <;> ring + +theorem approximationLowCell_implies_series_eval_bound {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) + (hu : u ≤ hi) (huMax : u ≤ approximationMaxU) + (hz : z ^ 2 < (u + 1) * 2 ^ 104) + (hcert : 0 ≤ evalPoly (approximationLowCert a) (u : Int)) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) - + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int)) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + have huScale : u < approximationScale := huMax.trans_lt (by decide) + have hv0 : (0 : Real) ≤ (u : Real) / approximationScale := by positivity + have hv1 : (u : Real) / approximationScale < 1 := by + rw [div_lt_one (by norm_num [approximationScale])] + exact_mod_cast huScale + have hseries := series_le_partial_geometric hv0 hv1 approximationTerms + have hupper := approximationUpper_eval u huScale + have hseriesUpper : + (∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) ≤ + (evalPoly approximationUpperNum (u : Int) : Real) / + evalPoly approximationUpperDen (u : Int) := by + rw [hupper] + exact hseries + have hbound := approximationLowCell_implies_weighted ha hu hz + (approximationUpperDen_pos huMax) (approximationRationalDen_pos huMax) hcert + calc + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) - + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int)) ≤ + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((evalPoly approximationUpperNum (u : Int) : Real) / + evalPoly approximationUpperDen (u : Int) - + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int)) := by + exact mul_le_mul_of_nonneg_left + (sub_le_sub_right hseriesUpper _) (by positivity) + _ ≤ (approximationErrorNum : Real) / approximationErrorDen := hbound + +theorem approximationHighCell_implies_series_eval_bound {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) + (hu : u ≤ hi) (huMax : u ≤ approximationMaxU) + (hz : z ^ 2 < (u + 1) * 2 ^ 104) + (hcert : 0 ≤ evalPoly (approximationHighCert a) (u : Int)) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) - + (∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1))) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + have huScale : u < approximationScale := huMax.trans_lt (by decide) + have hv0 : (0 : Real) ≤ (u : Real) / approximationScale := by positivity + have hv1 : (u : Real) / approximationScale < 1 := by + rw [div_lt_one (by norm_num [approximationScale])] + exact_mod_cast huScale + have hpartial := partial_le_series hv0 hv1 approximationTerms + have hbound := approximationHighCell_implies_weighted ha hu hz + (approximationRationalDen_pos huMax) hcert + rw [approximationTaylor_eval] at hbound + calc + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) - + (∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1))) ≤ + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) - + ∑ j ∈ range approximationTerms, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) := by + have hgap : + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) - + (∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) ≤ + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) - + ∑ j ∈ range approximationTerms, + ((u : Real) / approximationScale) ^ j / (2 * j + 1) := by + linarith + exact mul_le_mul_of_nonneg_left hgap (by positivity) + _ ≤ (approximationErrorNum : Real) / approximationErrorDen := hbound + +theorem approximationLowCell_implies_series_bound {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) + (hu : u ≤ hi) (huMax : u ≤ approximationMaxU) + (hz : z ^ 2 < (u + 1) * 2 ^ 104) + (hcert : 0 ≤ evalPoly (approximationLowCert a) (u : Int)) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1)) - + ((evalPoly PPc (u : Int) : Real) / 2 ^ 358) / + ((-evalPoly QQc (u : Int) : Int) / 2 ^ 386)) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + rw [← approximationRational_eval u huMax] + exact approximationLowCell_implies_series_eval_bound ha hu huMax hz hcert + +theorem approximationHighCell_implies_series_bound {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) + (hu : u ≤ hi) (huMax : u ≤ approximationMaxU) + (hz : z ^ 2 < (u + 1) * 2 ^ 104) + (hcert : 0 ≤ evalPoly (approximationHighCert a) (u : Int)) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + (((evalPoly PPc (u : Int) : Real) / 2 ^ 358) / + ((-evalPoly QQc (u : Int) : Int) / 2 ^ 386) - + (∑' j : Nat, + ((u : Real) / approximationScale) ^ j / (2 * j + 1))) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + rw [← approximationRational_eval u huMax] + exact approximationHighCell_implies_series_eval_bound ha hu huMax hz hcert + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationSound.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationSound.lean new file mode 100644 index 000000000..2c78f837a --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationSound.lean @@ -0,0 +1,233 @@ +import Mathlib.Data.Real.Basic +import LnProof.Floor.CarryIndependent.Approximation + +namespace LnFloorCarry + +open Common.Poly + +set_option maxRecDepth 100000 + +noncomputable section + +private theorem approximationEnvelopeSquareBudget_factor : + (2 * 10 ^ 27 * approximationErrorDen) ^ 2 * + approximationEnvelopeSquareBudget = + (approximationErrorNum * approximationEnvelopeDen) ^ 2 * + approximationScale := by + norm_num [approximationErrorNum, approximationErrorDen, + approximationEnvelopeDen, approximationEnvelopeSquareBudget, + approximationScale] + +theorem approximationEnvelope_scale_nat {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) (hu : u ≤ hi) + (hz : z ^ 2 < (u + 1) * 2 ^ 104) : + (2 * 10 ^ 27 * approximationErrorDen) * a * z ≤ + (approximationErrorNum * approximationEnvelopeDen) * 2 ^ 100 := by + let C := 2 * 10 ^ 27 * approximationErrorDen + let P := approximationErrorNum * approximationEnvelopeDen + have hscaled : a ^ 2 * (C ^ 2 * (hi + 1)) ≤ + P ^ 2 * approximationScale := by + calc + a ^ 2 * (C ^ 2 * (hi + 1)) = + C ^ 2 * (a ^ 2 * (hi + 1)) := by ring + _ ≤ C ^ 2 * approximationEnvelopeSquareBudget := + Nat.mul_le_mul_left _ ha + _ = P ^ 2 * approximationScale := by + simpa [C, P] using approximationEnvelopeSquareBudget_factor + have hzhi : z ^ 2 ≤ (hi + 1) * 2 ^ 104 := + (Nat.le_of_lt hz).trans + (Nat.mul_le_mul_right (2 ^ 104) (Nat.add_le_add_right hu 1)) + have h1 := Nat.mul_le_mul_left (a ^ 2 * C ^ 2) hzhi + have h2 := Nat.mul_le_mul_right (2 ^ 104) hscaled + have hsq : (C * a * z) ^ 2 ≤ (P * 2 ^ 100) ^ 2 := calc + (C * a * z) ^ 2 = a ^ 2 * C ^ 2 * z ^ 2 := by ring + _ ≤ a ^ 2 * C ^ 2 * ((hi + 1) * 2 ^ 104) := h1 + _ = (a ^ 2 * (C ^ 2 * (hi + 1))) * 2 ^ 104 := by ring + _ ≤ (P ^ 2 * approximationScale) * 2 ^ 104 := h2 + _ = (P * 2 ^ 100) ^ 2 := by simp [approximationScale]; ring + have hbase : C * a * z ≤ P * 2 ^ 100 := + (Nat.pow_le_pow_iff_left (by decide : (2 : Nat) ≠ 0)).1 hsq + simpa [C, P] + +theorem approximationEnvelope_scale_real {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) (hu : u ≤ hi) + (hz : z ^ 2 < (u + 1) * 2 ^ 104) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((a : Real) / approximationEnvelopeDen) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + let C := 2 * 10 ^ 27 * approximationErrorDen + let P := approximationErrorNum * approximationEnvelopeDen + have hbase := approximationEnvelope_scale_nat ha hu hz + have hbaseR : ((C * a * z : Nat) : Real) ≤ ((P * 2 ^ 100 : Nat) : Real) := by + dsimp [C, P] + exact_mod_cast hbase + let den : Real := approximationErrorDen * 2 ^ 100 * approximationEnvelopeDen + have herrorDen : (0 : Real) < approximationErrorDen := by + exact_mod_cast (show 0 < approximationErrorDen by + unfold approximationErrorDen + positivity) + have henvelopeDen : (0 : Real) < approximationEnvelopeDen := by + exact_mod_cast (show 0 < approximationEnvelopeDen by + unfold approximationEnvelopeDen + positivity) + have hden : 0 < den := by + dsimp [den] + positivity + calc + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((a : Real) / approximationEnvelopeDen) = + ((C * a * z : Nat) : Real) / den := by + dsimp [C, den] + push_cast + field_simp [henvelopeDen.ne'] + ring + _ ≤ ((P * 2 ^ 100 : Nat) : Real) / den := + (div_le_div_iff_of_pos_right hden).2 hbaseR + _ = (approximationErrorNum : Real) / approximationErrorDen := by + dsimp [P, den] + push_cast + field_simp [herrorDen.ne'] + ring + +theorem ratio_gap_le_of_cross {a e fn fd n d : Real} + (he : 0 < e) (hfd : 0 < fd) (hd : 0 < d) + (h : e * (fn * d - n * fd) ≤ a * (fd * d)) : + fn / fd - n / d ≤ a / e := by + rw [le_div_iff₀ he] + calc + (fn / fd - n / d) * e = e * (fn * d - n * fd) / (fd * d) := by + field_simp [hfd.ne', hd.ne'] + ring + _ ≤ a := (div_le_iff₀ (mul_pos hfd hd)).2 (by + simpa [mul_assoc] using h) + +theorem approximationLowCert_implies_real {a : Nat} {u : Int} + (hF : 0 < evalPoly approximationUpperDen u) + (hD : 0 < evalPoly approximationRationalDen u) + (hcert : 0 ≤ evalPoly (approximationLowCert a) u) : + (evalPoly approximationUpperNum u : Real) / + evalPoly approximationUpperDen u - + (evalPoly approximationRationalNum u : Real) / + evalPoly approximationRationalDen u ≤ + (a : Real) / approximationEnvelopeDen := by + have hc : (0 : Real) ≤ evalPoly (approximationLowCert a) u := by + exact_mod_cast hcert + simp only [approximationLowCert, approximationLowGapNum, + approximationLowGapDen, evalPoly_polyAdd, evalPoly_polyScale, + evalPoly_polyMul] at hc + push_cast at hc ⊢ + apply ratio_gap_le_of_cross + (he := by norm_num [approximationEnvelopeDen]) + (hfd := by exact_mod_cast hF) + (hd := by exact_mod_cast hD) + ring_nf at hc ⊢ + linarith + +theorem approximationHighCert_implies_real {a : Nat} {u : Int} + (hD : 0 < evalPoly approximationRationalDen u) + (hcert : 0 ≤ evalPoly (approximationHighCert a) u) : + (evalPoly approximationRationalNum u : Real) / + evalPoly approximationRationalDen u - + (evalPoly approximationTaylorNum u : Real) / approximationTaylorDen ≤ + (a : Real) / approximationEnvelopeDen := by + have hT : 0 < approximationTaylorDen := by decide + have hc : (0 : Real) ≤ evalPoly (approximationHighCert a) u := by + exact_mod_cast hcert + simp only [approximationHighCert, approximationHighGapNum, + approximationHighGapDen, evalPoly_polyAdd, evalPoly_polyScale, + evalPoly_polyMul] at hc + push_cast at hc ⊢ + apply ratio_gap_le_of_cross + (he := by norm_num [approximationEnvelopeDen]) + (hfd := by exact_mod_cast hD) + (hd := by exact_mod_cast hT) + ring_nf at hc ⊢ + linarith + +theorem approximationLowCert_implies_weighted {a : Nat} {u : Int} + {alpha : Real} (halpha : 0 ≤ alpha) + (hF : 0 < evalPoly approximationUpperDen u) + (hD : 0 < evalPoly approximationRationalDen u) + (hcert : 0 ≤ evalPoly (approximationLowCert a) u) + (hscale : + 2 * (10 ^ 27 : Real) * alpha * + ((a : Real) / approximationEnvelopeDen) ≤ + (approximationErrorNum : Real) / approximationErrorDen) : + 2 * (10 ^ 27 : Real) * alpha * + ((evalPoly approximationUpperNum u : Real) / + evalPoly approximationUpperDen u - + (evalPoly approximationRationalNum u : Real) / + evalPoly approximationRationalDen u) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + calc + 2 * (10 ^ 27 : Real) * alpha * + ((evalPoly approximationUpperNum u : Real) / + evalPoly approximationUpperDen u - + (evalPoly approximationRationalNum u : Real) / + evalPoly approximationRationalDen u) ≤ + 2 * (10 ^ 27 : Real) * alpha * + ((a : Real) / approximationEnvelopeDen) := by + gcongr + exact approximationLowCert_implies_real hF hD hcert + _ ≤ (approximationErrorNum : Real) / approximationErrorDen := hscale + +theorem approximationHighCert_implies_weighted {a : Nat} {u : Int} + {alpha : Real} (halpha : 0 ≤ alpha) + (hD : 0 < evalPoly approximationRationalDen u) + (hcert : 0 ≤ evalPoly (approximationHighCert a) u) + (hscale : + 2 * (10 ^ 27 : Real) * alpha * + ((a : Real) / approximationEnvelopeDen) ≤ + (approximationErrorNum : Real) / approximationErrorDen) : + 2 * (10 ^ 27 : Real) * alpha * + ((evalPoly approximationRationalNum u : Real) / + evalPoly approximationRationalDen u - + (evalPoly approximationTaylorNum u : Real) / + approximationTaylorDen) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + calc + 2 * (10 ^ 27 : Real) * alpha * + ((evalPoly approximationRationalNum u : Real) / + evalPoly approximationRationalDen u - + (evalPoly approximationTaylorNum u : Real) / + approximationTaylorDen) ≤ + 2 * (10 ^ 27 : Real) * alpha * + ((a : Real) / approximationEnvelopeDen) := by + gcongr + exact approximationHighCert_implies_real hD hcert + _ ≤ (approximationErrorNum : Real) / approximationErrorDen := hscale + +theorem approximationLowCell_implies_weighted {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) + (hu : u ≤ hi) (hz : z ^ 2 < (u + 1) * 2 ^ 104) + (hF : 0 < evalPoly approximationUpperDen (u : Int)) + (hD : 0 < evalPoly approximationRationalDen (u : Int)) + (hcert : 0 ≤ evalPoly (approximationLowCert a) (u : Int)) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((evalPoly approximationUpperNum (u : Int) : Real) / + evalPoly approximationUpperDen (u : Int) - + (evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int)) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + exact approximationLowCert_implies_weighted + (alpha := (z : Real) / 2 ^ 100) (by positivity) hF hD hcert + (approximationEnvelope_scale_real ha hu hz) + +theorem approximationHighCell_implies_weighted {hi u z a : Nat} + (ha : approximationEnvelopeCandidate hi a) + (hu : u ≤ hi) (hz : z ^ 2 < (u + 1) * 2 ^ 104) + (hD : 0 < evalPoly approximationRationalDen (u : Int)) + (hcert : 0 ≤ evalPoly (approximationHighCert a) (u : Int)) : + 2 * (10 ^ 27 : Real) * ((z : Real) / 2 ^ 100) * + ((evalPoly approximationRationalNum (u : Int) : Real) / + evalPoly approximationRationalDen (u : Int) - + (evalPoly approximationTaylorNum (u : Int) : Real) / + approximationTaylorDen) ≤ + (approximationErrorNum : Real) / approximationErrorDen := by + exact approximationHighCert_implies_weighted + (alpha := (z : Real) / 2 ^ 100) (by positivity) hD hcert + (approximationEnvelope_scale_real ha hu hz) + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Arithmetic.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Arithmetic.lean new file mode 100644 index 000000000..fb80d4903 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Arithmetic.lean @@ -0,0 +1,46 @@ +import Mathlib.Algebra.BigOperators.Field +import LnProof.Model.Body + +open scoped BigOperators +open LnYul Common.Poly + +namespace LnFloorCarry.Arithmetic + +def m0 : Nat := 2 ^ 95 +def q100 : Nat := 2 ^ 100 +def ray : Nat := 10 ^ 27 +def z0 : Nat := 217494458298375249691265569565 +def u0 : Nat := 2332259347626381040680638252 + +def a : ℚ := z0 / q100 +def vz : ℚ := a ^ 2 +def p : ℚ := evalPoly PPc u0 / 2 ^ 358 +def d : ℚ := -evalPoly QQc u0 / 2 ^ 386 +def pError (u : ℚ) : ℚ := + 1 + u / 2 ^ 87 * (1 + u / 2 ^ 97 * (1 + u / 2 ^ 90)) +def dError (u : ℚ) : ℚ := + 1 + u / 2 ^ 95 * (1 + u / 2 ^ 88 * (1 + u / 2 ^ 90)) + +def fpUpper : ℚ := + (∑ j ∈ Finset.range 48, (j + 1) * vz ^ j / (2 * (j + 1) + 1)) + + vz ^ 48 / (2 * (1 - vz)) + +def approximationBudget : ℚ := 323661607720025115242513 / 10 ^ 24 +def zBound : ℚ := + (2 * ray / q100) / (1 - (((Sc : ℚ) - m0) / ((Sc : ℚ) + m0)) ^ 2) +def uBound : ℚ := 2 * ray * a * fpUpper / 2 ^ 96 +def hornerBound : ℚ := + 2 * ray * a * + (p * dError u0 + pError u0 * d) / (d * (d + dError u0)) +def closingDivisionBound : ℚ := 2 * ray / q100 + +def total : ℚ := + approximationBudget + zBound + uBound + hornerBound + closingDivisionBound + +def coreNum : Nat := 32886404036042980977667 +def coreDen : Nat := 10 ^ 23 + +theorem total_lt_core : total < coreNum / coreDen := by + decide +kernel + +end LnFloorCarry.Arithmetic diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Atanh.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Atanh.lean new file mode 100644 index 000000000..5869c3899 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Atanh.lean @@ -0,0 +1,126 @@ +import Mathlib.Analysis.SpecialFunctions.Log.Deriv + +open scoped BigOperators + +namespace LnFloorCarry + +open Finset + +noncomputable section + +theorem series_le_partial_geometric {v : Real} (hv0 : 0 ≤ v) (hv1 : v < 1) + (N : Nat) : + (∑' j : Nat, v ^ j / (2 * j + 1)) ≤ + (∑ j ∈ range N, v ^ j / (2 * j + 1)) + + v ^ N / ((2 * N + 1) * (1 - v)) := by + have hgeom : Summable (fun j : Nat => v ^ j) := + summable_geometric_of_lt_one hv0 hv1 + have hseries : Summable (fun j : Nat => v ^ j / (2 * j + 1)) := + hgeom.of_nonneg_of_le + (fun j => div_nonneg (pow_nonneg hv0 j) (by positivity)) + (fun j => div_le_self (pow_nonneg hv0 j) (by + have hj : (0 : Real) ≤ j := Nat.cast_nonneg j + linarith)) + have htail : Summable (fun j : Nat => v ^ (j + N) / (2 * (j + N) + 1)) := + by simpa only [Nat.cast_add] using (summable_nat_add_iff N).2 hseries + have htailGeom : Summable (fun j : Nat => + (v ^ N / (2 * N + 1)) * v ^ j) := + hgeom.mul_left (v ^ N / (2 * N + 1)) + have htailLe : + (∑' j : Nat, v ^ (j + N) / (2 * (j + N) + 1)) ≤ + ∑' j : Nat, (v ^ N / (2 * N + 1)) * v ^ j := by + apply htail.tsum_le_tsum _ htailGeom + intro j + have hden : (0 : Real) < 2 * N + 1 := by positivity + have hdenLe : (2 * N + 1 : Real) ≤ 2 * (j + N) + 1 := by + have hj0 : (0 : Real) ≤ j := Nat.cast_nonneg j + linarith + have hpow : v ^ (j + N) = v ^ N * v ^ j := by + rw [pow_add, mul_comm] + rw [hpow] + have hnum : 0 ≤ v ^ N * v ^ j := + mul_nonneg (pow_nonneg hv0 _) (pow_nonneg hv0 _) + calc + _ ≤ v ^ N * v ^ j / (2 * N + 1) := + div_le_div_of_nonneg_left hnum hden hdenLe + _ = (v ^ N / (2 * N + 1)) * v ^ j := by ring + rw [← hseries.sum_add_tsum_nat_add N] + simp only [Nat.cast_add] + calc + (∑ j ∈ range N, v ^ j / (2 * j + 1)) + + ∑' j : Nat, v ^ (j + N) / (2 * (j + N) + 1) + ≤ (∑ j ∈ range N, v ^ j / (2 * j + 1)) + + ∑' j : Nat, (v ^ N / (2 * N + 1)) * v ^ j := + add_le_add_left htailLe _ + _ = (∑ j ∈ range N, v ^ j / (2 * j + 1)) + + v ^ N / ((2 * N + 1) * (1 - v)) := by + rw [tsum_mul_left, tsum_geometric_of_lt_one hv0 hv1] + field_simp [show (1 : Real) - v ≠ 0 by linarith] + +theorem partial_le_series {v : Real} (hv0 : 0 ≤ v) (hv1 : v < 1) (N : Nat) : + (∑ j ∈ range N, v ^ j / (2 * j + 1)) ≤ + ∑' j : Nat, v ^ j / (2 * j + 1) := by + have hgeom : Summable (fun j : Nat => v ^ j) := + summable_geometric_of_lt_one hv0 hv1 + have hseries : Summable (fun j : Nat => v ^ j / (2 * j + 1)) := + hgeom.of_nonneg_of_le + (fun j => div_nonneg (pow_nonneg hv0 j) (by positivity)) + (fun j => div_le_self (pow_nonneg hv0 j) (by + have hj : (0 : Real) ≤ j := Nat.cast_nonneg j + linarith)) + exact hseries.sum_le_tsum (range N) (fun j _ => by positivity) + +theorem neg_log_ratio_eq_log_sub_log {m S : Real} (hm : 0 < m) (hmS : m ≤ S) : + -Real.log (m / S) = + Real.log (1 + (S - m) / (S + m)) - Real.log (1 - (S - m) / (S + m)) := by + have hS : 0 < S := lt_of_lt_of_le hm hmS + have hden : 0 < S + m := add_pos hS hm + have hplus : 1 + (S - m) / (S + m) = 2 * S / (S + m) := by + field_simp [hden.ne'] + ring + have hminus : 1 - (S - m) / (S + m) = 2 * m / (S + m) := by + field_simp [hden.ne'] + ring + have hplus0 : 1 + (S - m) / (S + m) ≠ 0 := by rw [hplus]; positivity + have hminus0 : 1 - (S - m) / (S + m) ≠ 0 := by rw [hminus]; positivity + symm + calc + Real.log (1 + (S - m) / (S + m)) - Real.log (1 - (S - m) / (S + m)) = + Real.log ((1 + (S - m) / (S + m)) / (1 - (S - m) / (S + m))) := + (Real.log_div hplus0 hminus0).symm + _ = Real.log (S / m) := by + rw [hplus, hminus] + congr 1 + field_simp [hm.ne', hS.ne', hden.ne'] + ring + _ = Real.log ((m / S)⁻¹) := by + congr 1 + field_simp [hm.ne', hS.ne'] + _ = -Real.log (m / S) := Real.log_inv _ + +theorem log_ratio_eq_log_sub_log {m S : Real} (hS : 0 < S) (hSm : S ≤ m) : + Real.log (m / S) = + Real.log (1 + (m - S) / (m + S)) - Real.log (1 - (m - S) / (m + S)) := by + have hm : 0 < m := lt_of_lt_of_le hS hSm + have hden : 0 < m + S := add_pos hm hS + have hplus : 1 + (m - S) / (m + S) = 2 * m / (m + S) := by + field_simp [hden.ne'] + ring + have hminus : 1 - (m - S) / (m + S) = 2 * S / (m + S) := by + field_simp [hden.ne'] + ring + have hplus0 : 1 + (m - S) / (m + S) ≠ 0 := by rw [hplus]; positivity + have hminus0 : 1 - (m - S) / (m + S) ≠ 0 := by rw [hminus]; positivity + calc + Real.log (m / S) = + Real.log ((1 + (m - S) / (m + S)) / (1 - (m - S) / (m + S))) := by + congr 1 + rw [hplus, hminus] + field_simp [hm.ne', hS.ne', hden.ne'] + ring + _ = Real.log (1 + (m - S) / (m + S)) - Real.log (1 - (m - S) / (m + S)) := + Real.log_div hplus0 hminus0 + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Bounds.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Bounds.lean new file mode 100644 index 000000000..66838b5f8 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Bounds.lean @@ -0,0 +1,151 @@ +import Mathlib.Topology.Algebra.InfiniteSum.Basic +import Mathlib.Topology.Instances.Real.Lemmas +import Mathlib.Data.Rat.BigOperators +import LnProof.Floor.CarryIndependent.Arithmetic + +open scoped BigOperators +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open Finset LnYul Common.Poly + +noncomputable section + +def wordQ100 : Nat := 1267650600228229401496703205376 +def wordQ96 : Nat := 79228162514264337593543950336 +def rayScale : Nat := 1000000000000000000000000000 + +def pScale : Nat := + 587135645693458306972370149197334256843920637227079967676822742883052256278652110865924749596192175757983744 + +def qScale : Nat := + 157608024785577916849116160400574455220318957081861786671793173616982887085988842445657065019539662563226511961227264 + +def endpointZWord : Nat := 217494458298375249691265569565 +def endpointUWord : Nat := 2332259347626381040680638252 + +def normalizedZ (m : Nat) : Real := (int256 (zWord m) : Real) / wordQ100 +def normalizedU (m : Nat) : Real := (uWord (zWord m) : Real) / wordQ96 +def highNormalizedZ (m : Nat) : Real := (-int256 (zWord m) : Int) / wordQ100 + +def endpointZ : Real := (endpointZWord : Real) / wordQ100 +def endpointT : Real := ((Sc : Real) - 2 ^ 95) / ((Sc : Real) + 2 ^ 95) +def endpointV : Real := endpointZ ^ 2 + +def exactP (u : Nat) : Real := (evalPoly PPc (u : Int) : Real) / pScale +def exactD (u : Nat) : Real := (-evalPoly QQc (u : Int) : Int) / qScale + +def pError (u : Nat) : Real := + 1 + (u : Real) / 2 ^ 87 * + (1 + (u : Real) / 2 ^ 97 * (1 + (u : Real) / 2 ^ 90)) + +def dError (u : Nat) : Real := + 1 + (u : Real) / 2 ^ 95 * + (1 + (u : Real) / 2 ^ 88 * (1 + (u : Real) / 2 ^ 90)) + +def exactRatio (u : Nat) : Real := exactP u / exactD u + +def shadowRatio (u : Nat) : Real := + (exactP u - pError u) / (exactD u + dError u) + +def atanhSeries (v : Real) : Real := + ∑' j : Nat, v ^ j / (2 * j + 1) + +def endpointDerivative : Real := + (∑ j ∈ range 48, + (j + 1) * endpointV ^ j / (2 * (j + 1) + 1)) + + endpointV ^ 48 / (2 * (1 - endpointV)) + +def approximationBudget : Real := + (323661607720025115242513 : Real) / 10 ^ 24 + +def zFloorBudget : Real := + (2 * rayScale / wordQ100) / (1 - endpointT ^ 2) + +def uFloorBudget : Real := + 2 * rayScale * endpointZ * endpointDerivative / wordQ96 + +def hornerBudget : Real := + let P := exactP endpointUWord + let D := exactD endpointUWord + let ep := pError endpointUWord + let ed := dError endpointUWord + 2 * rayScale * endpointZ * + (P * ed + ep * D) / (D * (D + ed)) + +def closingDivisionBudget : Real := 2 * rayScale / wordQ100 + +def coreErrorLimit : Real := + (32886404036042980977667 : Real) / 10 ^ 23 + +def lowShadow (m : Nat) : Real := + -2 * normalizedZ m * shadowRatio (uWord (zWord m)) + 2 / wordQ100 + +def highShadow (m : Nat) : Real := + 2 * highNormalizedZ m * exactRatio (uWord (zWord m)) + +def approximationTerm (m : Nat) : Real := + 2 * rayScale * normalizedZ m * + (atanhSeries (normalizedU m) - exactRatio (uWord (zWord m))) + +def hornerTerm (m : Nat) : Real := + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - shadowRatio (uWord (zWord m))) + +def highApproximationTerm (m : Nat) : Real := + 2 * rayScale * highNormalizedZ m * + (exactRatio (uWord (zWord m)) - atanhSeries (normalizedU m)) + +theorem approximationBudget_lt_coreErrorLimit : + approximationBudget < coreErrorLimit := by + norm_num [approximationBudget, coreErrorLimit] + +private theorem approximationBudget_eq_cast : + approximationBudget = (Arithmetic.approximationBudget : Real) := by + norm_num [approximationBudget, Arithmetic.approximationBudget] + +private theorem zFloorBudget_eq_cast : + zFloorBudget = (Arithmetic.zBound : Real) := by + norm_num [zFloorBudget, Arithmetic.zBound, endpointT, Arithmetic.m0, + Arithmetic.q100, Arithmetic.ray, rayScale, wordQ100, Sc] + +private theorem uFloorBudget_eq_cast : + uFloorBudget = (Arithmetic.uBound : Real) := by + simp only [uFloorBudget, Arithmetic.uBound, endpointDerivative, + Arithmetic.fpUpper, endpointV, Arithmetic.vz, endpointZ, Arithmetic.a, + endpointZWord, Arithmetic.z0, Arithmetic.q100, Arithmetic.ray, rayScale, + wordQ100, wordQ96] + push_cast + norm_num + +private theorem hornerBudget_eq_cast : + hornerBudget = (Arithmetic.hornerBound : Real) := by + norm_num [hornerBudget, Arithmetic.hornerBound, exactP, Arithmetic.p, + exactD, Arithmetic.d, pError, Arithmetic.pError, dError, + Arithmetic.dError, endpointUWord, Arithmetic.u0, pScale, qScale, + Arithmetic.a, endpointZ, endpointZWord, Arithmetic.z0, wordQ100, + Arithmetic.q100, rayScale, Arithmetic.ray, PPc, QQc, + Common.Poly.evalPoly] + +private theorem closingDivisionBudget_eq_cast : + closingDivisionBudget = (Arithmetic.closingDivisionBound : Real) := by + norm_num [closingDivisionBudget, Arithmetic.closingDivisionBound, + rayScale, Arithmetic.ray, wordQ100, Arithmetic.q100] + +private theorem coreErrorLimit_eq_cast : + coreErrorLimit = + ((Arithmetic.coreNum / Arithmetic.coreDen : ℚ) : Real) := by + norm_num [coreErrorLimit, Arithmetic.coreNum, Arithmetic.coreDen] + +theorem totalBudget_lt_coreErrorLimit : + approximationBudget + zFloorBudget + uFloorBudget + hornerBudget + + closingDivisionBudget < coreErrorLimit := by + rw [approximationBudget_eq_cast, zFloorBudget_eq_cast, uFloorBudget_eq_cast, + hornerBudget_eq_cast, closingDivisionBudget_eq_cast, coreErrorLimit_eq_cast] + norm_cast + simpa only [Arithmetic.total] using Arithmetic.total_lt_core + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/CertificateRuntime.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/CertificateRuntime.lean new file mode 100644 index 000000000..9f79aa76a --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/CertificateRuntime.lean @@ -0,0 +1,96 @@ +import LnProof.Cert.Approximation +import LnProof.Floor.CarryIndependent.ApproximationReal +import LnProof.Floor.CarryIndependent.HornerCorrelation +import LnProof.Floor.CarryIndependent.Runtime + +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul + +noncomputable section + +private theorem approximationBudget_eq_error : + approximationBudget = + (approximationErrorNum : Real) / approximationErrorDen := by + norm_num [approximationBudget, approximationErrorNum, approximationErrorDen] + +theorem lowApproximationTerm_le_budget {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + approximationTerm m ≤ approximationBudget := by + let u := uWord (zWord m) + let z := (int256 (zWord m)).toNat + obtain ⟨huMax, _, hzSquareInt⟩ := low_u_facts hmlo hmsc + change u ≤ approximationMaxU at huMax + change int256 (zWord m) ^ 2 < ((u : Int) + 1) * 2 ^ 104 at hzSquareInt + obtain ⟨hi, a, hu, ha, hcert⟩ := approximationLowCover huMax + have hzNonneg : 0 ≤ int256 (zWord m) := (low_z_facts hmlo hmsc).1 + have hzCast : (z : Int) = int256 (zWord m) := by + exact Int.toNat_of_nonneg hzNonneg + have hzSquare : z ^ 2 < (u + 1) * 2 ^ 104 := by + rw [← hzCast] at hzSquareInt + exact_mod_cast hzSquareInt + have hbound := approximationLowCell_implies_series_bound + ha hu huMax hzSquare hcert + have hzCastReal : (z : Real) = (int256 (zWord m) : Real) := by + exact_mod_cast hzCast + rw [hzCastReal] at hbound + have hray : (rayScale : Real) = 10 ^ 27 := by norm_num [rayScale] + have hq100 : (wordQ100 : Real) = 2 ^ 100 := by norm_num [wordQ100] + have hq96 : (wordQ96 : Real) = approximationScale := by + norm_num [wordQ96, approximationScale] + have hp : (pScale : Real) = 2 ^ 358 := by norm_num [pScale] + have hq : (qScale : Real) = 2 ^ 386 := by norm_num [qScale] + simpa [approximationTerm, normalizedZ, normalizedU, exactRatio, exactP, + exactD, atanhSeries, approximationBudget_eq_error, hray, hq100, hq96, + hp, hq, u] using hbound + +theorem highApproximationTerm_le_budget {m : Nat} + (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + highApproximationTerm m ≤ approximationBudget := by + let u := uWord (zWord m) + let z := (-int256 (zWord m)).toNat + obtain ⟨huMax, _, hzSquareInt⟩ := high_u_facts hscm hmhi + change u ≤ approximationMaxU at huMax + change int256 (zWord m) ^ 2 < ((u : Int) + 1) * 2 ^ 104 at hzSquareInt + obtain ⟨hi, a, hu, ha, hcert⟩ := approximationHighCover huMax + have hzNonneg : 0 ≤ -int256 (zWord m) := + neg_nonneg.mpr (high_z_facts hscm hmhi).2 + have hzCast : (z : Int) = -int256 (zWord m) := by + exact Int.toNat_of_nonneg hzNonneg + have hzSquare : z ^ 2 < (u + 1) * 2 ^ 104 := by + have hzSquareCast : (z : Int) ^ 2 = int256 (zWord m) ^ 2 := by + rw [hzCast] + ring + rw [← hzSquareCast] at hzSquareInt + exact_mod_cast hzSquareInt + have hbound := approximationHighCell_implies_series_bound + ha hu huMax hzSquare hcert + have hzCastReal : (z : Real) = (-int256 (zWord m) : Int) := by + exact_mod_cast hzCast + rw [hzCastReal] at hbound + have hray : (rayScale : Real) = 10 ^ 27 := by norm_num [rayScale] + have hq100 : (wordQ100 : Real) = 2 ^ 100 := by norm_num [wordQ100] + have hq96 : (wordQ96 : Real) = approximationScale := by + norm_num [wordQ96, approximationScale] + have hp : (pScale : Real) = 2 ^ 358 := by norm_num [pScale] + have hq : (qScale : Real) = 2 ^ 386 := by norm_num [qScale] + simpa [highApproximationTerm, highNormalizedZ, normalizedU, exactRatio, + exactP, exactD, atanhSeries, approximationBudget_eq_error, hray, hq100, + hq96, hp, hq, u] using hbound + +theorem certified_mantissa_runtime_core_bound {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmhi : m < 2 ^ 96) : + rayScale * + ((int256 (x1W (zWord m)) : Real) / 2 ^ 99 - + Real.log ((m : Real) / Sc)) < + coreErrorLimit := by + exact mantissa_runtime_core_bound hmlo hmhi + (lowApproximationTerm_le_budget hmlo) + (lowHornerTerm_le_budget hmlo) + (fun hscm => highApproximationTerm_le_budget hscm hmhi) + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Cut.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Cut.lean new file mode 100644 index 000000000..d4baf4742 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Cut.lean @@ -0,0 +1,264 @@ +import LnProof.Floor.CarryIndependent.Phase +import LnProof.Floor.Model +import LnProof.Seam.RealLog + +open FormalYul +open FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul LnFloor LnFloorCert + +set_option maxRecDepth 8192 + +noncomputable section + +private theorem real_int_natCast (n : Nat) : (((n : Int) : Real)) = (n : Real) := by + norm_cast + +private theorem exp_natCast_mul_log_two (n : Nat) : + Real.exp ((n : Real) * Real.log 2) = (2 : Real) ^ n := by + rw [Real.exp_nat_mul, Real.exp_log (by norm_num : (0 : Real) < 2)] + +private theorem exp_neg_natCast_mul_log_two (n : Nat) : + Real.exp (-(n : Real) * Real.log 2) = ((2 : Real) ^ n)⁻¹ := by + rw [neg_mul, Real.exp_neg, exp_natCast_mul_log_two] + +def signedOctave (c : Nat) : Int := 160 - (c : Int) + +def coreErrorRay (m : Nat) (X : Int) : Real := + 10 ^ 27 * ((X : Real) / 2 ^ 99 - Real.log ((m : Real) / Sc)) + +def accumulatorI (X : Int) (c : Nat) : Int := + X * 7450580596923828125 + ln2kInt c + (BIASc : Int) + +theorem scaledAccumulator_eq (X : Int) (c : Nat) : + (accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27) = + (X : Real) / 2 ^ 99 + (signedOctave c : Real) * ln2Word + biasNatural := by + by_cases hc : c ≤ 160 + · have hcast : ((160 - c : Nat) : Real) = 160 - (c : Real) := by + rw [Nat.cast_sub hc] + norm_num + simp only [accumulatorI, Int.cast_add, Int.cast_mul, Int.cast_ofNat, + Int.cast_natCast] + rw [show ln2kInt c = (LN2c : Int) * ((160 - c : Nat) : Int) by + unfold ln2kInt; rw [if_pos hc]] + simp only [Int.cast_mul, Int.cast_natCast] + rw [hcast] + norm_num [signedOctave, ln2Word, biasNatural, LN2c, BIASc, QS] + ring + · have hct : 160 ≤ c := by omega + have hcast : ((c - 160 : Nat) : Real) = (c : Real) - 160 := by + rw [Nat.cast_sub hct] + norm_num + simp only [accumulatorI, Int.cast_add, Int.cast_mul, Int.cast_ofNat, + Int.cast_natCast] + rw [show ln2kInt c = -((LN2c : Int) * ((c - 160 : Nat) : Int)) by + unfold ln2kInt; rw [if_neg hc]] + simp only [Int.cast_neg, Int.cast_mul, Int.cast_natCast] + rw [hcast] + norm_num [signedOctave, ln2Word, biasNatural, LN2c, BIASc, QS] + ring + +theorem scaledAccumulator_error_decomposition (m : Nat) (X : Int) (c : Nat) : + (accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27) = + Real.log ((m : Real) / Sc) + + (signedOctave c : Real) * Real.log 2 + biasNatural + + (coreErrorRay m X + phaseErrorRay (signedOctave c)) / 10 ^ 27 := by + rw [scaledAccumulator_eq] + unfold coreErrorRay phaseErrorRay phaseDeltaRay + ring + +theorem accumulator_exp_lt_wadRatio_of_nonnegative_octave + {m c x : Nat} {X : Int} (hm : 0 < m) (hc1 : 1 ≤ c) (hc : c ≤ 160) + (hmx : m * 2 ^ (160 - c) ≤ x) + (hcore : coreErrorRay m X < (coreErrorNum : Real) / coreErrorDen) : + Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) < + (x : Real) / 10 ^ 18 := by + let k : Int := signedOctave c + let n : Nat := 160 - c + have hk : k = (n : Int) := by unfold k n signedOctave; omega + have hklo : -95 ≤ k := by rw [hk]; omega + have hkhi : k ≤ 159 := by rw [hk]; omega + have hextra := bias_add_core_phase_exp_lt hcore hklo hkhi + have hmR : 0 < (m : Real) := by exact_mod_cast hm + have hmratio : 0 < (m : Real) / (Sc : Real) := + div_pos hmR (by norm_num [Sc]) + have hpow : Real.exp ((k : Real) * Real.log 2) = (2 : Real) ^ n := by + have hkR : (k : Real) = (n : Real) := + (congrArg (fun z : Int => (z : Real)) hk).trans (real_int_natCast n) + exact (congrArg (fun z : Real => Real.exp (z * Real.log 2)) hkR).trans + (exp_natCast_mul_log_two n) + have hdecomp := scaledAccumulator_error_decomposition m X c + have hdecomp' : + (accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27) = + Real.log ((m : Real) / Sc) + (k : Real) * Real.log 2 + + (biasNatural + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + calc + (accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27) = + Real.log ((m : Real) / Sc) + + (signedOctave c : Real) * Real.log 2 + biasNatural + + (coreErrorRay m X + phaseErrorRay (signedOctave c)) / 10 ^ 27 := hdecomp + _ = Real.log ((m : Real) / Sc) + (k : Real) * Real.log 2 + + (biasNatural + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + dsimp [k] + ring + have hfactor : + Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) = + ((m : Real) / Sc) * (2 : Real) ^ n * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + calc + Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) = + Real.exp (Real.log ((m : Real) / Sc) + (k : Real) * Real.log 2 + + (biasNatural + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27)) := + congrArg Real.exp hdecomp' + _ = Real.exp (Real.log ((m : Real) / Sc)) * + Real.exp ((k : Real) * Real.log 2) * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + rw [Real.exp_add, Real.exp_add] + _ = ((m : Real) / Sc) * (2 : Real) ^ n * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + rw [Real.exp_log hmratio, hpow] + rw [hfactor] + have hleftPos : 0 < ((m : Real) / Sc) * (2 : Real) ^ n := + mul_pos hmratio (pow_pos (by norm_num) n) + have hstrict : + ((m : Real) / Sc) * (2 : Real) ^ n * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) < + ((m : Real) / Sc) * (2 : Real) ^ n * ((Sc : Real) / 10 ^ 18) := + mul_lt_mul_of_pos_left hextra hleftPos + have hcancel : + ((m : Real) / Sc) * (2 : Real) ^ n * ((Sc : Real) / 10 ^ 18) = + ((m : Real) * (2 : Real) ^ n) / 10 ^ 18 := by + norm_num [Sc] + ring + rw [hcancel] at hstrict + have hmxCast := (Nat.cast_le (α := Real)).mpr hmx + have hmxR : (m : Real) * (2 : Real) ^ n ≤ (x : Real) := by + simpa only [Nat.cast_mul, Nat.cast_pow, Nat.cast_ofNat, n] using hmxCast + exact hstrict.trans_le ((div_le_div_iff_of_pos_right (by positivity)).2 hmxR) + +theorem accumulator_exp_lt_wadRatio_of_negative_octave + {m c x : Nat} {X : Int} (hm : 0 < m) (hc : 160 < c) (hc255 : c ≤ 255) + (hmx : m = x * 2 ^ (c - 160)) + (hcore : coreErrorRay m X < (coreErrorNum : Real) / coreErrorDen) : + Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) < + (x : Real) / 10 ^ 18 := by + let k : Int := signedOctave c + let n : Nat := c - 160 + have hk : k = -(n : Int) := by unfold k n signedOctave; omega + have hklo : -95 ≤ k := by rw [hk]; omega + have hkhi : k ≤ 159 := by rw [hk]; omega + have hextra := bias_add_core_phase_exp_lt hcore hklo hkhi + have hmR : 0 < (m : Real) := by exact_mod_cast hm + have hmratio : 0 < (m : Real) / (Sc : Real) := + div_pos hmR (by norm_num [Sc]) + have hpow : Real.exp ((k : Real) * Real.log 2) = ((2 : Real) ^ n)⁻¹ := by + have hkR : (k : Real) = -(n : Real) := by + calc + (k : Real) = ((-(n : Int) : Int) : Real) := + congrArg (fun z : Int => (z : Real)) hk + _ = -(((n : Int) : Real)) := by rw [Int.cast_neg] + _ = -(n : Real) := congrArg Neg.neg (real_int_natCast n) + exact (congrArg (fun z : Real => Real.exp (z * Real.log 2)) hkR).trans + (exp_neg_natCast_mul_log_two n) + have hdecomp := scaledAccumulator_error_decomposition m X c + have hdecomp' : + (accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27) = + Real.log ((m : Real) / Sc) + (k : Real) * Real.log 2 + + (biasNatural + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + calc + (accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27) = + Real.log ((m : Real) / Sc) + + (signedOctave c : Real) * Real.log 2 + biasNatural + + (coreErrorRay m X + phaseErrorRay (signedOctave c)) / 10 ^ 27 := hdecomp + _ = Real.log ((m : Real) / Sc) + (k : Real) * Real.log 2 + + (biasNatural + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + dsimp [k] + ring + have hfactor : + Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) = + ((m : Real) / Sc) * ((2 : Real) ^ n)⁻¹ * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + calc + Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) = + Real.exp (Real.log ((m : Real) / Sc) + (k : Real) * Real.log 2 + + (biasNatural + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27)) := + congrArg Real.exp hdecomp' + _ = Real.exp (Real.log ((m : Real) / Sc)) * + Real.exp ((k : Real) * Real.log 2) * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + rw [Real.exp_add, Real.exp_add] + _ = ((m : Real) / Sc) * ((2 : Real) ^ n)⁻¹ * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) := by + rw [Real.exp_log hmratio, hpow] + rw [hfactor] + have hleftPos : 0 < ((m : Real) / Sc) * ((2 : Real) ^ n)⁻¹ := + mul_pos hmratio (inv_pos.mpr (pow_pos (by norm_num) n)) + have hstrict : + ((m : Real) / Sc) * ((2 : Real) ^ n)⁻¹ * + Real.exp (biasNatural + + (coreErrorRay m X + phaseErrorRay k) / 10 ^ 27) < + ((m : Real) / Sc) * ((2 : Real) ^ n)⁻¹ * ((Sc : Real) / 10 ^ 18) := + mul_lt_mul_of_pos_left hextra hleftPos + have hmxCast := congrArg (fun y : Nat => (y : Real)) hmx + have hmxR : (m : Real) = (x : Real) * (2 : Real) ^ n := by + simpa only [Nat.cast_mul, Nat.cast_pow, Nat.cast_ofNat, n] using hmxCast + have hcancel : + ((m : Real) / Sc) * ((2 : Real) ^ n)⁻¹ * ((Sc : Real) / 10 ^ 18) = + (x : Real) / 10 ^ 18 := by + rw [hmxR] + have hpowne : (2 : Real) ^ n ≠ 0 := by positivity + field_simp [Sc, hpowne] + ring + rw [hcancel] at hstrict + exact hstrict + +theorem cut_of_accumulator_bracket {r A : Int} {x : Nat} (hx : 0 < x) + (hbr : r * 2 ^ 72 ≤ A) + (hacc : Real.exp ((A : Real) / (2 ^ 72 * 10 ^ 27)) < + (x : Real) / 10 ^ 18) : + CutLeLogWadRay r x := by + have hbrR : (r : Real) * 2 ^ 72 ≤ (A : Real) := by exact_mod_cast hbr + have hscale : (r : Real) / 10 ^ 27 ≤ + (A : Real) / (2 ^ 72 * 10 ^ 27) := by + have hdiv := (div_le_div_iff_of_pos_right + (show (0 : Real) < 2 ^ 72 * 10 ^ 27 by positivity)).2 hbrR + have hcancel : (r : Real) / 10 ^ 27 = + ((r : Real) * 2 ^ 72) / (2 ^ 72 * 10 ^ 27) := by ring + rw [hcancel] + exact hdiv + have hratio : 0 < (x : Real) / 10 ^ 18 := by + exact div_pos (by exact_mod_cast hx) (by positivity) + have haccLog : (A : Real) / (2 ^ 72 * 10 ^ 27) < + Real.log ((x : Real) / 10 ^ 18) := + (Real.lt_log_iff_exp_lt hratio).2 hacc + have hlog := hscale.trans_lt haccLog + apply LnRealBridge.cutLeLogWadRay_of_lt hx + simpa only [Nat.cast_pow, Nat.cast_ofNat] using hlog + +theorem normalized_cut_of_core_bound + {m c x : Nat} {X r : Int} (hx : 0 < x) (hm : 0 < m) + (hc1 : 1 ≤ c) (hc255 : c ≤ 255) + (hwindow : (c ≤ 160 ∧ m * 2 ^ (160 - c) ≤ x) ∨ + (160 < c ∧ m = x * 2 ^ (c - 160))) + (hbr : r * 2 ^ 72 ≤ accumulatorI X c) + (hcore : coreErrorRay m X < (coreErrorNum : Real) / coreErrorDen) : + CutLeLogWadRay r x := by + have hacc : Real.exp ((accumulatorI X c : Real) / (2 ^ 72 * 10 ^ 27)) < + (x : Real) / 10 ^ 18 := by + rcases hwindow with ⟨hc, hmx⟩ | ⟨hc, hmx⟩ + · exact accumulator_exp_lt_wadRatio_of_nonnegative_octave hm hc1 hc hmx hcore + · exact accumulator_exp_lt_wadRatio_of_negative_octave hm hc hc255 hmx hcore + exact cut_of_accumulator_bracket hx hbr hacc + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Horner.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Horner.lean new file mode 100644 index 000000000..7deb93aa3 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Horner.lean @@ -0,0 +1,53 @@ +import LnProof.Floor.CarryIndependent.Bounds + +namespace LnFloorCarry + +open Common.Poly LnYul + +noncomputable section + +theorem hornerTerm_le_of_gap_le {m : Nat} {bound : Real} + (hz0 : 0 ≤ normalizedZ m) (hzEnd : normalizedZ m ≤ endpointZ) + (hbound : 0 ≤ bound) + (hgap : exactRatio (uWord (zWord m)) - + shadowRatio (uWord (zWord m)) ≤ bound) : + hornerTerm m ≤ 2 * rayScale * endpointZ * bound := by + have hscale : (0 : Real) ≤ 2 * rayScale := by norm_num [rayScale] + have hscaledZ : 0 ≤ 2 * rayScale * normalizedZ m := + mul_nonneg hscale hz0 + have hzScaled : 2 * rayScale * normalizedZ m ≤ + 2 * rayScale * endpointZ := + mul_le_mul_of_nonneg_left hzEnd hscale + unfold hornerTerm + calc + 2 * rayScale * normalizedZ m * + (exactRatio (uWord (zWord m)) - + shadowRatio (uWord (zWord m))) ≤ + 2 * rayScale * normalizedZ m * bound := by + exact mul_le_mul_of_nonneg_left hgap hscaledZ + _ ≤ 2 * rayScale * endpointZ * bound := by + exact mul_le_mul_of_nonneg_right hzScaled hbound + +theorem ratio_le_endpoint_of_cross_nonneg + {num den : List Int} {u endpoint : Int} + (hden : 0 < evalPoly den u) + (hEndpointDen : 0 < evalPoly den endpoint) + (hcross : + 0 ≤ evalPoly num endpoint * evalPoly den u - + evalPoly den endpoint * evalPoly num u) : + (evalPoly num u : Real) / evalPoly den u ≤ + (evalPoly num endpoint : Real) / evalPoly den endpoint := by + have hcrossInt : + evalPoly num u * evalPoly den endpoint ≤ + evalPoly num endpoint * evalPoly den u := by + simpa only [mul_comm] using sub_nonneg.mp hcross + have hcrossReal : + (evalPoly num u : Real) * evalPoly den endpoint ≤ + evalPoly num endpoint * evalPoly den u := by + exact_mod_cast hcrossInt + rw [div_le_div_iff₀ (by exact_mod_cast hden) (by exact_mod_cast hEndpointDen)] + exact hcrossReal + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/HornerCorrelation.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/HornerCorrelation.lean new file mode 100644 index 000000000..ee3d23c2c --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/HornerCorrelation.lean @@ -0,0 +1,170 @@ +import LnProof.Cert.HornerCorrelation +import LnProof.Floor.CarryIndependent.ApproximationReal +import LnProof.Floor.CarryIndependent.Horner +import LnProof.Floor.CarryIndependent.WordRuntime + +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul Common.Poly + +set_option maxRecDepth 8192 + +noncomputable section + +theorem hornerCorrelationPErrorNum_eval (u : Nat) : + evalPoly hornerCorrelationPErrorNum (u : Int) = pErrorNum u := by + simp only [hornerCorrelationPErrorNum, pErrorNum, evalPoly] + ring + +theorem hornerCorrelationDErrorNum_eval (u : Nat) : + evalPoly hornerCorrelationDErrorNum (u : Int) = dErrorNum u := by + simp only [hornerCorrelationDErrorNum, dErrorNum, evalPoly] + ring + +theorem hornerCorrelationDNum_eval (u : Nat) : + evalPoly hornerCorrelationDNum (u : Int) = -evalPoly QQc (u : Int) := by + simp only [hornerCorrelationDNum, evalPoly_polyNeg] + +theorem hornerCorrelationNum_eval (u : Nat) : + evalPoly hornerCorrelationNum (u : Int) = + 2 ^ 112 * + (2 ^ 29 * evalPoly PPc (u : Int) * dErrorNum u + + pErrorNum u * (-evalPoly QQc (u : Int))) := by + simp only [hornerCorrelationNum, evalPoly_polyScale, evalPoly_polyAdd, + evalPoly_polyMul, hornerCorrelationPErrorNum_eval, + hornerCorrelationDErrorNum_eval, hornerCorrelationDNum_eval] + ring + +theorem hornerCorrelationDen_eval (u : Nat) : + evalPoly hornerCorrelationDen (u : Int) = + (-evalPoly QQc (u : Int)) * + (-evalPoly QQc (u : Int) + 2 ^ 113 * dErrorNum u) := by + simp only [hornerCorrelationDen, evalPoly_polyMul, evalPoly_polyAdd, + evalPoly_polyScale, hornerCorrelationDNum_eval, + hornerCorrelationDErrorNum_eval] + +theorem dErrorNum_nonneg (u : Nat) : 0 ≤ dErrorNum u := by + unfold dErrorNum + positivity + +theorem hornerCorrelationDNum_pos {u : Nat} (hu : u ≤ Uc) : + 0 < evalPoly hornerCorrelationDNum (u : Int) := by + have h := approximationRationalDen_pos + (show u ≤ approximationMaxU by simpa [approximationMaxU] using hu) + simpa only [approximationRationalDen, hornerCorrelationDNum] using h + +theorem hornerCorrelationDen_pos {u : Nat} (hu : u ≤ Uc) : + 0 < evalPoly hornerCorrelationDen (u : Int) := by + rw [hornerCorrelationDen_eval] + have hD := hornerCorrelationDNum_pos hu + rw [hornerCorrelationDNum_eval] at hD + exact mul_pos hD (add_pos_of_pos_of_nonneg hD + (mul_nonneg (by norm_num) (dErrorNum_nonneg u))) + +theorem ratio_gap_eq (u : Nat) (hu : u ≤ Uc) : + exactRatio u - shadowRatio u = + (exactP u * dError u + pError u * exactD u) / + (exactD u * (exactD u + dError u)) := by + obtain ⟨_, _, _, _, hD, _⟩ := final_stage_sandwich_of_u hu + have hDE : 0 < exactD u + dError u := + add_pos_of_pos_of_nonneg hD (dError_nonneg u) + unfold exactRatio shadowRatio + field_simp [hD.ne', hDE.ne'] + ring + +theorem hornerCorrelation_fraction_eq (u : Nat) (hu : u ≤ Uc) : + (evalPoly hornerCorrelationNum (u : Int) : Real) / + evalPoly hornerCorrelationDen (u : Int) = + (exactP u * dError u + pError u * exactD u) / + (exactD u * (exactD u + dError u)) := by + have hD := hornerCorrelationDNum_pos hu + have hF : (0 : Int) ≤ dErrorNum u := dErrorNum_nonneg u + have hDF : (0 : Int) < + evalPoly hornerCorrelationDNum (u : Int) + 2 ^ 113 * dErrorNum u := + add_pos_of_pos_of_nonneg hD (mul_nonneg (by norm_num) hF) + rw [hornerCorrelationNum_eval, hornerCorrelationDen_eval, + pError_eq, dError_eq] + unfold exactP exactD + have hpScale : (pScale : Real) = 2 ^ 358 := by norm_num [pScale] + have hqScale : (qScale : Real) = 2 ^ 386 := by norm_num [qScale] + rw [hpScale, hqScale] + push_cast + rw [hornerCorrelationDNum_eval] at hD hDF + let A : Real := evalPoly PPc (u : Int) + let B : Real := -evalPoly QQc (u : Int) + let E : Real := pErrorNum u + let F : Real := dErrorNum u + have hBR : 0 < B := by + dsimp [B] + exact_mod_cast hD + have hBFR : 0 < B + 2 ^ 113 * F := by + dsimp [B, F] + exact_mod_cast hDF + change + 5192296858534827628530496329220096 * + (536870912 * A * F + E * B) / + (B * (B + 10384593717069655257060992658440192 * F)) = + (A / 2 ^ 358 * (F / 2 ^ 273) + + E / 2 ^ 274 * (B / 2 ^ 386)) / + (B / 2 ^ 386 * (B / 2 ^ 386 + F / 2 ^ 273)) + field_simp [hBR.ne', hBFR.ne'] + ring + +theorem hornerCorrelation_gap_eq (u : Nat) (hu : u ≤ Uc) : + exactRatio u - shadowRatio u = + (evalPoly hornerCorrelationNum (u : Int) : Real) / + evalPoly hornerCorrelationDen (u : Int) := by + rw [ratio_gap_eq u hu, hornerCorrelation_fraction_eq u hu] + +theorem hornerCorrelation_gap_le_endpoint {u : Nat} (hu : u ≤ Uc) : + exactRatio u - shadowRatio u ≤ + exactRatio Uc - shadowRatio Uc := by + have hcross := hornerCorrelation_nonneg (u := (u : Int)) + (Int.ofNat_zero_le u) (by exact_mod_cast hu) + rw [hornerCorrelationCert_eval] at hcross + have hratio := ratio_le_endpoint_of_cross_nonneg + (num := hornerCorrelationNum) (den := hornerCorrelationDen) + (u := (u : Int)) (endpoint := (Uc : Int)) + (hornerCorrelationDen_pos hu) (hornerCorrelationDen_pos (u := Uc) le_rfl) + (by simpa only [endpointNum, endpointDen] using hcross) + rw [hornerCorrelation_gap_eq u hu, + hornerCorrelation_gap_eq Uc le_rfl] + exact hratio + +theorem endpoint_gap_nonneg : + 0 ≤ exactRatio Uc - shadowRatio Uc := by + rw [ratio_gap_eq Uc le_rfl] + obtain ⟨_, hpHi, _, _, hD, _⟩ := final_stage_sandwich_of_u (u := Uc) le_rfl + have hpRuntime : (0 : Real) ≤ int256 (pS4 Uc) := by + exact_mod_cast + ((by norm_num : (0 : Int) ≤ 13131151825116561693704478250792).trans + (pS4_facts (u := Uc) le_rfl).2.1) + have hP : 0 ≤ exactP Uc := hpRuntime.trans hpHi + have hpError := pError_nonneg Uc + have hdError := dError_nonneg Uc + exact div_nonneg + (add_nonneg (mul_nonneg hP hdError) (mul_nonneg hpError hD.le)) + (mul_nonneg hD.le (add_nonneg hD.le hdError)) + +theorem lowHornerTerm_le_budget {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + hornerTerm m ≤ hornerBudget := by + obtain ⟨hz0, hzEnd, _, _⟩ := low_endpoint_bounds hmlo hmsc + have hu := (low_u_facts hmlo hmsc).1 + have hterm := hornerTerm_le_of_gap_le hz0 hzEnd endpoint_gap_nonneg + (hornerCorrelation_gap_le_endpoint hu) + rw [ratio_gap_eq Uc le_rfl] at hterm + calc + hornerTerm m ≤ + 2 * rayScale * endpointZ * + ((exactP Uc * dError Uc + pError Uc * exactD Uc) / + (exactD Uc * (exactD Uc + dError Uc))) := hterm + _ = hornerBudget := by + simp only [hornerBudget, endpointUWord, Uc] + ring + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean new file mode 100644 index 000000000..8c353ab89 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean @@ -0,0 +1,455 @@ +import LnProof.Mono.ZOctave +import LnProof.Floor.CarryIndependent.Bounds + +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul + +set_option maxRecDepth 8192 + +noncomputable section + +theorem real_cast_toNat {x : Int} (hx : 0 ≤ x) : + (((x.toNat : Nat) : Real)) = (x : Real) := by + norm_cast + exact Int.toNat_of_nonneg hx + +theorem z_at_low_endpoint : int256 (zWord (2 ^ 95)) = (Zc : Int) := by + decide +kernel + +theorem low_z_facts {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + 0 ≤ int256 (zWord m) ∧ int256 (zWord m) ≤ (Zc : Int) := by + have hr := zWord_range hmlo (by simp only [MHI, Sc] at *; omega) + have hz := zWord_antitone (m := 2 ^ 95) (m' := m) + (by simp only [MLO]; exact le_refl _) hmlo + (by simp only [MHI, Sc] at *; omega) + rw [z_at_low_endpoint] at hz + constructor + · obtain ⟨e2, e3⟩ := zWord_transport hmlo + (by simp only [MHI, Sc] at *; omega) + have hden : 0 < int256 (evmAdd m Sc) := by + rw [e3] + exact Int.add_pos_of_nonneg_of_pos (Int.ofNat_zero_le m) (by norm_num [Sc]) + have hnum : 0 ≤ int256 (evmShl 100 (evmSub Sc m)) := by + rw [e2] + exact Int.mul_nonneg + (sub_nonneg.mpr (Int.ofNat_le.mpr (Nat.le_of_lt hmsc))) (by norm_num) + unfold zWord + rw [evmSdiv_pos_pos (evmShl_lt _ _) (evmAdd_lt _ _) hnum hden] + exact Int.natCast_nonneg _ + · exact hz + +theorem low_u_eq {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + uWord (zWord m) = uVal (int256 (zWord m)) := by + have hr := zWord_range hmlo (by simp only [MHI, Sc] at *; omega) + have hword := uint256OfInt_int256 (w := zWord m) (evmSdiv_lt _ _) + calc + uWord (zWord m) = uWord (uint256OfInt (int256 (zWord m))) := + congrArg uWord hword.symm + _ = uVal (int256 (zWord m)) := uWord_eq _ hr.1 hr.2 + +theorem uVal_floor {z : Int} : + (uVal z : Int) * 2 ^ 104 ≤ z ^ 2 ∧ + z ^ 2 < ((uVal z : Int) + 1) * 2 ^ 104 := by + let n := (z * z).toNat + have hzsq : 0 ≤ z * z := mul_self_nonneg z + have hncast : (n : Int) = z * z := Int.toNat_of_nonneg hzsq + have hlo : (n / 2 ^ 104) * 2 ^ 104 ≤ n := Nat.div_mul_le_self _ _ + have hhi : n < (n / 2 ^ 104 + 1) * 2 ^ 104 := by + have hmod := Nat.mod_lt n (show 0 < 2 ^ 104 by positivity) + calc + n = (n / 2 ^ 104) * 2 ^ 104 + n % 2 ^ 104 := by + rw [mul_comm (n / 2 ^ 104)] + exact (Nat.div_add_mod _ _).symm + _ < (n / 2 ^ 104) * 2 ^ 104 + 2 ^ 104 := + Nat.add_lt_add_left hmod _ + _ = (n / 2 ^ 104 + 1) * 2 ^ 104 := by omega + have hloI := Int.ofNat_le.mpr hlo + have hhiI := Int.ofNat_lt.mpr hhi + simp only [Int.natCast_mul, Int.natCast_add, Int.natCast_one, + Int.natCast_pow] at hloI hhiI + unfold uVal + rw [show (z * z).toNat = n by rfl, pow_two, ← hncast] + exact ⟨hloI, hhiI⟩ + +theorem low_u_facts {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + uWord (zWord m) ≤ Uc ∧ + (uWord (zWord m) : Int) * 2 ^ 104 ≤ int256 (zWord m) ^ 2 ∧ + int256 (zWord m) ^ 2 < ((uWord (zWord m) : Int) + 1) * 2 ^ 104 := by + have hz := low_z_facts hmlo hmsc + have huEq := low_u_eq hmlo hmsc + have hu := uVal_le (int256 (zWord m)) (by simp only [Zc] at hz ⊢; omega) + (by simp only [Zc] at hz ⊢; omega) + have hf := uVal_floor (z := int256 (zWord m)) + rw [huEq] + exact ⟨hu, hf⟩ + +theorem nat_div_floor_bounds (n d : Nat) (hd : 0 < d) : + (n / d) * d ≤ n ∧ n < (n / d + 1) * d := by + constructor + · exact Nat.div_mul_le_self n d + · have hmod := Nat.mod_lt n hd + calc + n = (n / d) * d + n % d := by + rw [mul_comm (n / d)] + exact (Nat.div_add_mod _ _).symm + _ < (n / d) * d + d := Nat.add_lt_add_left hmod _ + _ = (n / d + 1) * d := by ring + +private theorem low_z_num_toNat {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + (int256 (evmShl 100 (evmSub Sc m))).toNat = + (Sc - m) * wordQ100 := by + obtain ⟨e2, _⟩ := zWord_transport hmlo + (by simp only [MHI, Sc] at *; omega) + have hsub : (0 : Int) ≤ (Sc : Int) - m := + sub_nonneg.mpr (Int.ofNat_le.mpr (Nat.le_of_lt hmsc)) + have hsubNat : ((Sc : Int) - m).toNat = Sc - m := by + simpa using Int.toNat_sub_of_le + (Int.ofNat_le.mpr (Nat.le_of_lt hmsc)) + have hscale : (0 : Int) ≤ 1267650600228229401496703205376 := by norm_num + have hscaleNat : (1267650600228229401496703205376 : Int).toNat = + wordQ100 := by + change ((1267650600228229401496703205376 : Nat) : Int).toNat = wordQ100 + rw [Int.toNat_natCast] + norm_num [wordQ100] + rw [e2, Int.toNat_mul hsub hscale, hsubNat, hscaleNat] + +private theorem z_den_toNat {m : Nat} (hmlo : MLO ≤ m) (hmhi : m < MHI) : + (int256 (evmAdd m Sc)).toNat = m + Sc := by + obtain ⟨_, e3⟩ := zWord_transport hmlo hmhi + rw [e3] + exact_mod_cast Int.toNat_of_nonneg + (Int.add_nonneg (Int.ofNat_zero_le m) (Int.ofNat_zero_le Sc)) + +set_option maxRecDepth 12000 in +private theorem low_z_int_eq {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + int256 (zWord m) = + Int.ofNat ((Sc - m) * wordQ100 / (m + Sc)) := by + obtain ⟨e2, e3⟩ := zWord_transport hmlo + (by simp only [MHI, Sc] at *; omega) + have hnum : 0 ≤ int256 (evmShl 100 (evmSub Sc m)) := by + rw [e2] + exact Int.mul_nonneg + (sub_nonneg.mpr (Int.ofNat_le.mpr (Nat.le_of_lt hmsc))) (by norm_num) + have hden : 0 < int256 (evmAdd m Sc) := by + rw [e3] + exact Int.add_pos_of_nonneg_of_pos (Int.ofNat_zero_le m) (by norm_num [Sc]) + have hz := evmSdiv_pos_pos (evmShl_lt _ _) (evmAdd_lt _ _) hnum hden + rw [low_z_num_toNat hmlo hmsc, + z_den_toNat hmlo (by simp only [MHI, Sc] at *; omega)] at hz + exact hz + +set_option maxRecDepth 32000 in +theorem low_z_nat_eq {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + (int256 (zWord m)).toNat = (Sc - m) * wordQ100 / (m + Sc) := by + exact Eq.trans (congrArg Int.toNat (low_z_int_eq hmlo hmsc)) + (Int.toNat_natCast _) + +set_option maxRecDepth 16000 in +theorem low_z_floor {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + let t := ((Sc : Real) - m) / ((Sc : Real) + m) + normalizedZ m ≤ t ∧ t < normalizedZ m + 1 / wordQ100 := by + dsimp + have hzNat := low_z_nat_eq hmlo hmsc + let n := (Sc - m) * wordQ100 + let d := m + Sc + have hd : 0 < d := by dsimp [d]; norm_num [Sc] + obtain ⟨hloNat, hhiNat⟩ := nat_div_floor_bounds n d hd + dsimp [n, d] at hloNat hhiNat + rw [← hzNat] at hloNat hhiNat + have hz0 := (low_z_facts hmlo hmsc).1 + have hloR0 : (((int256 (zWord m)).toNat : Nat) : Real) * (m + Sc) ≤ + ((Sc : Real) - m) * wordQ100 := by + have h := (Nat.cast_le (α := Real)).mpr hloNat + push_cast at h + rw [Nat.cast_sub (Nat.le_of_lt hmsc)] at h + exact h + have hhiR0 : ((Sc : Real) - m) * wordQ100 < + ((((int256 (zWord m)).toNat : Nat) : Real) + 1) * (m + Sc) := by + have h := (Nat.cast_lt (α := Real)).mpr hhiNat + push_cast at h + rw [Nat.cast_sub (Nat.le_of_lt hmsc)] at h + exact h + rw [real_cast_toNat hz0] at hloR0 hhiR0 + have hsum : (0 : Real) < (Sc : Real) + m := by + exact add_pos_of_pos_of_nonneg (by norm_num [Sc]) (Nat.cast_nonneg m) + have hq : (0 : Real) < wordQ100 := by norm_num [wordQ100] + constructor + · unfold normalizedZ + rw [div_le_div_iff₀ hq hsum] + simpa [add_comm] using hloR0 + · unfold normalizedZ + rw [div_lt_iff₀ hsum] + calc + (Sc : Real) - m < + ((int256 (zWord m) : Real) + 1) * (m + Sc) / wordQ100 := by + rw [lt_div_iff₀ hq] + simpa [mul_comm, mul_left_comm, mul_assoc] using hhiR0 + _ = ((int256 (zWord m) : Real) / wordQ100 + 1 / wordQ100) * + ((Sc : Real) + m) := by ring + +theorem low_u_floor {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + normalizedU m ≤ normalizedZ m ^ 2 ∧ + normalizedZ m ^ 2 < normalizedU m + 1 / wordQ96 := by + obtain ⟨_, hlo, hhi⟩ := low_u_facts hmlo hmsc + have hloR : ((uWord (zWord m) : Int) : Real) * 2 ^ 104 ≤ + (int256 (zWord m) : Real) ^ 2 := by exact_mod_cast hlo + have hhiR : (int256 (zWord m) : Real) ^ 2 < + (((uWord (zWord m) : Int) : Real) + 1) * 2 ^ 104 := by exact_mod_cast hhi + constructor + · unfold normalizedU normalizedZ + calc + (uWord (zWord m) : Real) / wordQ96 = + ((uWord (zWord m) : Real) * 2 ^ 104) / 2 ^ 200 := by + norm_num [wordQ96] + ring + _ ≤ (int256 (zWord m) : Real) ^ 2 / 2 ^ 200 := + div_le_div_of_nonneg_right hloR (by positivity) + _ = ((int256 (zWord m) : Real) / wordQ100) ^ 2 := by + norm_num [wordQ100] + ring + · unfold normalizedU normalizedZ + calc + ((int256 (zWord m) : Real) / wordQ100) ^ 2 = + (int256 (zWord m) : Real) ^ 2 / 2 ^ 200 := by + norm_num [wordQ100] + ring + _ < (((uWord (zWord m) : Real) + 1) * 2 ^ 104) / 2 ^ 200 := + div_lt_div_of_pos_right hhiR (by positivity) + _ = (uWord (zWord m) : Real) / wordQ96 + 1 / wordQ96 := by + norm_num [wordQ96] + ring + +theorem low_endpoint_bounds {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + let t := ((Sc : Real) - m) / ((Sc : Real) + m) + 0 ≤ normalizedZ m ∧ normalizedZ m ≤ endpointZ ∧ + t ≤ endpointT ∧ endpointT < 1 := by + dsimp + have hz := low_z_facts hmlo hmsc + have hq : (0 : Real) < wordQ100 := by norm_num [wordQ100] + refine ⟨div_nonneg (by exact_mod_cast hz.1) hq.le, ?_, ?_, ?_⟩ + · unfold normalizedZ endpointZ endpointZWord + rw [div_le_div_iff_of_pos_right hq] + simpa only [Zc] using (show (int256 (zWord m) : Real) ≤ + (217494458298375249691265569565 : Real) by exact_mod_cast hz.2) + · unfold endpointT + have hd1 : (0 : Real) < (Sc : Real) + m := by + exact add_pos_of_pos_of_nonneg (by norm_num [Sc]) (Nat.cast_nonneg m) + have hd2 : (0 : Real) < (Sc : Real) + 2 ^ 95 := by norm_num [Sc] + have hmloR : ((2 ^ 95 : Nat) : Real) ≤ m := by exact_mod_cast hmlo + have hdelta : (0 : Real) ≤ (m : Real) - 2 ^ 95 := by + rw [show (2 : Real) ^ 95 = ((2 ^ 95 : Nat) : Real) by norm_num] + exact sub_nonneg.mpr hmloR + rw [div_le_div_iff₀ hd1 hd2] + have hdiff : + 0 ≤ ((Sc : Real) - 2 ^ 95) * ((Sc : Real) + m) - + ((Sc : Real) - m) * ((Sc : Real) + 2 ^ 95) := by + rw [show + ((Sc : Real) - 2 ^ 95) * ((Sc : Real) + m) - + ((Sc : Real) - m) * ((Sc : Real) + 2 ^ 95) = + 2 * Sc * (m - 2 ^ 95) by ring] + exact mul_nonneg (mul_nonneg (by norm_num) (by norm_num [Sc])) + hdelta + exact sub_nonneg.mp hdiff + · unfold endpointT + rw [div_lt_one (by norm_num [Sc] : (0 : Real) < (Sc : Real) + 2 ^ 95)] + norm_num [Sc] + +theorem z_at_scale : int256 (zWord Sc) = 0 := by + decide +kernel + +theorem high_z_facts {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + -(217494458298375249691265569570 : Int) ≤ int256 (zWord m) ∧ + int256 (zWord m) ≤ 0 := by + have hr := zWord_range (m := m) (by simp only [MLO, Sc] at *; omega) + (by simpa only [MHI] using hmhi) + have hz := zWord_antitone (m := Sc) (m' := m) + (by simp only [MLO, Sc]; omega) hscm (by simpa only [MHI] using hmhi) + rw [z_at_scale] at hz + exact ⟨hr.1, hz⟩ + +theorem high_u_eq {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + uWord (zWord m) = uVal (int256 (zWord m)) := by + have hr := zWord_range (m := m) (by simp only [MLO, Sc] at *; omega) + (by simpa only [MHI] using hmhi) + have hword := uint256OfInt_int256 (w := zWord m) (evmSdiv_lt _ _) + calc + uWord (zWord m) = uWord (uint256OfInt (int256 (zWord m))) := + congrArg uWord hword.symm + _ = uVal (int256 (zWord m)) := uWord_eq _ hr.1 hr.2 + +theorem high_u_facts {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + uWord (zWord m) ≤ Uc ∧ + (uWord (zWord m) : Int) * 2 ^ 104 ≤ int256 (zWord m) ^ 2 ∧ + int256 (zWord m) ^ 2 < ((uWord (zWord m) : Int) + 1) * 2 ^ 104 := by + have hz := high_z_facts hscm hmhi + have huEq := high_u_eq hscm hmhi + have hu := uVal_le (int256 (zWord m)) (by omega) (by omega) + have hf := uVal_floor (z := int256 (zWord m)) + rw [huEq] + exact ⟨hu, hf⟩ + +private theorem high_z_num_toNat {m : Nat} + (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + (-int256 (evmShl 100 (evmSub Sc m))).toNat = + (m - Sc) * wordQ100 := by + obtain ⟨e2, _⟩ := zWord_transport + (m := m) (by simp only [MLO, Sc] at *; omega) + (by simpa only [MHI] using hmhi) + rw [e2] + have he : -(((Sc : Int) - m) * 1267650600228229401496703205376) = + ((m : Int) - Sc) * 1267650600228229401496703205376 := by ring + have hsub : (0 : Int) ≤ (m : Int) - Sc := + sub_nonneg.mpr (Int.ofNat_le.mpr hscm) + have hsubNat : ((m : Int) - Sc).toNat = m - Sc := by + simpa using Int.toNat_sub_of_le (Int.ofNat_le.mpr hscm) + have hscale : (0 : Int) ≤ 1267650600228229401496703205376 := by norm_num + have hscaleNat : (1267650600228229401496703205376 : Int).toNat = + wordQ100 := by + change ((1267650600228229401496703205376 : Nat) : Int).toNat = wordQ100 + rw [Int.toNat_natCast] + norm_num [wordQ100] + rw [he, Int.toNat_mul hsub hscale, hsubNat, hscaleNat] + +set_option maxRecDepth 12000 in +private theorem high_z_int_eq {m : Nat} + (hscm : Sc < m) (hmhi : m < 2 ^ 96) : + int256 (zWord m) = + -Int.ofNat ((m - Sc) * wordQ100 / (m + Sc)) := by + obtain ⟨e2, e3⟩ := zWord_transport + (m := m) (by simp only [MLO, Sc] at *; omega) + (by simpa only [MHI] using hmhi) + have hnum : int256 (evmShl 100 (evmSub Sc m)) < 0 := by + rw [e2] + have hsubNeg : (Sc : Int) - m < 0 := sub_neg.mpr (Int.ofNat_lt.mpr hscm) + exact Int.mul_neg_of_neg_of_pos hsubNeg (by norm_num) + have hnumMin : -(2 ^ 255) < int256 (evmShl 100 (evmSub Sc m)) := by + rw [e2] + simp only [Sc, ipow255] at * + omega + have hden : 0 < int256 (evmAdd m Sc) := by + rw [e3] + exact Int.add_pos_of_nonneg_of_pos (Int.ofNat_zero_le m) (by norm_num [Sc]) + have hz := evmSdiv_neg_pos (evmShl_lt _ _) (evmAdd_lt _ _) + hnum hnumMin hden + have hMloSc : MLO ≤ Sc := by + simp only [MLO, Sc] + omega + have hMloM : MLO ≤ m := hMloSc.trans (Nat.le_of_lt hscm) + rw [high_z_num_toNat (Nat.le_of_lt hscm) hmhi, + z_den_toNat hMloM + (by simpa only [MHI] using hmhi)] at hz + exact hz + +private theorem neg_neg_toNat_natCast (n : Nat) : + (-(-(n : Int))).toNat = n := by + rw [neg_neg] + exact Int.toNat_natCast n + +set_option maxRecDepth 32000 in +theorem high_z_nat_eq {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + (-int256 (zWord m)).toNat = (m - Sc) * wordQ100 / (m + Sc) := by + rcases hscm.eq_or_lt with rfl | hscm' + · rw [z_at_scale] + simp + · exact Eq.trans + (congrArg (fun z : Int => (-z).toNat) (high_z_int_eq hscm' hmhi)) + (neg_neg_toNat_natCast _) + +set_option maxRecDepth 16000 in +theorem high_z_floor {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + let t := ((m : Real) - Sc) / ((m : Real) + Sc) + highNormalizedZ m ≤ t ∧ t < highNormalizedZ m + 1 / wordQ100 := by + dsimp + rcases hscm.eq_or_lt with rfl | hscm' + · unfold highNormalizedZ + rw [z_at_scale] + norm_num [highNormalizedZ, wordQ100] + · have hzNat := high_z_nat_eq hscm hmhi + let n := (m - Sc) * wordQ100 + let d := m + Sc + have hd : 0 < d := by dsimp [d]; norm_num [Sc] + obtain ⟨hloNat, hhiNat⟩ := nat_div_floor_bounds n d hd + dsimp [n, d] at hloNat hhiNat + rw [← hzNat] at hloNat hhiNat + have hz0 : 0 ≤ -int256 (zWord m) := neg_nonneg.mpr (high_z_facts hscm hmhi).2 + have hloR0 : (((-int256 (zWord m)).toNat : Nat) : Real) * (m + Sc) ≤ + ((m : Real) - Sc) * wordQ100 := by + have h := (Nat.cast_le (α := Real)).mpr hloNat + push_cast at h + rw [Nat.cast_sub hscm] at h + exact h + have hhiR0 : ((m : Real) - Sc) * wordQ100 < + ((((-int256 (zWord m)).toNat : Nat) : Real) + 1) * (m + Sc) := by + have h := (Nat.cast_lt (α := Real)).mpr hhiNat + push_cast at h + rw [Nat.cast_sub hscm] at h + exact h + rw [real_cast_toNat hz0] at hloR0 hhiR0 + have hsum : (0 : Real) < (m : Real) + Sc := + add_pos_of_nonneg_of_pos (Nat.cast_nonneg m) (by norm_num [Sc]) + have hq : (0 : Real) < wordQ100 := by norm_num [wordQ100] + constructor + · unfold highNormalizedZ + rw [div_le_div_iff₀ hq hsum] + simpa using hloR0 + · unfold highNormalizedZ + rw [div_lt_iff₀ hsum] + calc + (m : Real) - Sc < + ((-int256 (zWord m) : Int) + 1) * (m + Sc) / wordQ100 := by + rw [lt_div_iff₀ hq] + simpa [mul_comm, mul_left_comm, mul_assoc] using hhiR0 + _ = (((-int256 (zWord m) : Int) : Real) / wordQ100 + 1 / wordQ100) * + ((m : Real) + Sc) := by ring + +theorem high_u_floor {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + normalizedU m ≤ highNormalizedZ m ^ 2 ∧ + highNormalizedZ m ^ 2 < normalizedU m + 1 / wordQ96 := by + obtain ⟨_, hlo, hhi⟩ := high_u_facts hscm hmhi + have hloR : ((uWord (zWord m) : Int) : Real) * 2 ^ 104 ≤ + (int256 (zWord m) : Real) ^ 2 := by exact_mod_cast hlo + have hhiR : (int256 (zWord m) : Real) ^ 2 < + (((uWord (zWord m) : Int) : Real) + 1) * 2 ^ 104 := by exact_mod_cast hhi + constructor + · unfold normalizedU highNormalizedZ + calc + (uWord (zWord m) : Real) / wordQ96 = + ((uWord (zWord m) : Real) * 2 ^ 104) / 2 ^ 200 := by + norm_num [wordQ96] + ring + _ ≤ (int256 (zWord m) : Real) ^ 2 / 2 ^ 200 := + div_le_div_of_nonneg_right hloR (by positivity) + _ = (((-int256 (zWord m) : Int) : Real) / wordQ100) ^ 2 := by + norm_num [wordQ100] + ring + · unfold normalizedU highNormalizedZ + calc + (((-int256 (zWord m) : Int) : Real) / wordQ100) ^ 2 = + (int256 (zWord m) : Real) ^ 2 / 2 ^ 200 := by + norm_num [wordQ100] + ring + _ < (((uWord (zWord m) : Real) + 1) * 2 ^ 104) / 2 ^ 200 := + div_lt_div_of_pos_right hhiR (by positivity) + _ = (uWord (zWord m) : Real) / wordQ96 + 1 / wordQ96 := by + norm_num [wordQ96] + ring + +theorem high_endpoint_bounds {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + let t := ((m : Real) - Sc) / ((m : Real) + Sc) + 0 ≤ highNormalizedZ m ∧ highNormalizedZ m ≤ t ∧ t < 1 := by + dsimp + have hz := high_z_facts hscm hmhi + have hq : (0 : Real) < wordQ100 := by norm_num [wordQ100] + refine ⟨div_nonneg (by exact_mod_cast neg_nonneg.mpr hz.2) hq.le, + (high_z_floor hscm hmhi).1, ?_⟩ + rw [div_lt_one (add_pos_of_nonneg_of_pos (Nat.cast_nonneg m) + (by norm_num [Sc]) : (0 : Real) < (m : Real) + Sc)] + linarith [show (0 : Real) < Sc by norm_num [Sc]] + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean new file mode 100644 index 000000000..7dcbf4fdd --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean @@ -0,0 +1,150 @@ +import Common.Seam.RealExpBridge +import LnProof.Model.Body +import LnProof.Spec.Cut + +namespace LnFloorCarry + +open Common.Exp Common.RealExpBridge LnFloor LnYul + +set_option maxRecDepth 100000 + +noncomputable section + +def phaseErrorNum : Nat := 24536250781840436 +def phaseErrorDen : Nat := 10 ^ 39 +def coreErrorNum : Nat := 32886404036042980977667 +def coreErrorDen : Nat := 10 ^ 23 +def globalErrorNum : Nat := 3288640403604298097806 +def globalErrorDen : Nat := 10 ^ 22 + +def ln2Word : Real := (LN2c : Real) * 2 ^ 27 / QS +def phaseDeltaRay : Real := 10 ^ 27 * (ln2Word - Real.log 2) +def phaseErrorRay (k : Int) : Real := (k : Real) * phaseDeltaRay +def biasNatural : Real := (BIASc : Real) / (10 ^ 27 * 2 ^ 72) + +theorem ln2WordAboveExactCap : capLB (LN2c * 2 ^ 27) QS 2 1 := by + refine ⟨40, ?_⟩ + decide + +theorem ln2WordMinusPhaseCap : + capUB + (LN2c * 2 ^ 27 * phaseErrorDen - phaseErrorNum * 2 ^ 99) + (QS * phaseErrorDen) 2 1 := by + refine capUB_of_partial (K := 130) + (by unfold phaseErrorDen QS; decide) (by decide) ?_ + decide + +theorem phaseDeltaRay_nonneg : 0 ≤ phaseDeltaRay := by + have hexp := le_exp_of_capLB + (p := LN2c * 2 ^ 27) (q := QS) (y := 2) (w := 1) + QS_pos (by decide) ln2WordAboveExactCap + have hlog : Real.log 2 ≤ ln2Word := by + apply (Real.log_le_iff_le_exp (by norm_num : (0 : Real) < 2)).2 + norm_num [ln2Word] at hexp ⊢ + exact hexp + unfold phaseDeltaRay + exact mul_nonneg (by positivity) (sub_nonneg.mpr hlog) + +theorem phaseDeltaRay_le : + phaseDeltaRay ≤ (phaseErrorNum : Real) / phaseErrorDen := by + have hexp := exp_le_of_capUB + (p := LN2c * 2 ^ 27 * phaseErrorDen - phaseErrorNum * 2 ^ 99) + (q := QS * phaseErrorDen) (y := 2) (w := 1) + (by unfold phaseErrorDen QS; decide) (by decide) ln2WordMinusPhaseCap + have harg : + ((LN2c * 2 ^ 27 * phaseErrorDen - phaseErrorNum * 2 ^ 99 : Nat) : Real) / + ((QS * phaseErrorDen : Nat) : Real) ≤ Real.log 2 := by + apply (Real.le_log_iff_exp_le (by norm_num : (0 : Real) < 2)).2 + simpa using hexp + have heq : + ((LN2c * 2 ^ 27 * phaseErrorDen - phaseErrorNum * 2 ^ 99 : Nat) : Real) / + ((QS * phaseErrorDen : Nat) : Real) = + ln2Word - (phaseErrorNum : Real) / (10 ^ 27 * phaseErrorDen) := by + norm_num [ln2Word, LN2c, QS, phaseErrorNum, phaseErrorDen] + rw [heq] at harg + unfold phaseDeltaRay + have hden : (0 : Real) < (phaseErrorDen : Real) := by + norm_num [phaseErrorDen] + have hscale : (0 : Real) < 10 ^ 27 := by positivity + have hsmall : ln2Word - Real.log 2 ≤ + (phaseErrorNum : Real) / (10 ^ 27 * phaseErrorDen) := by + linarith + calc + 10 ^ 27 * (ln2Word - Real.log 2) ≤ + 10 ^ 27 * ((phaseErrorNum : Real) / (10 ^ 27 * phaseErrorDen)) := + mul_le_mul_of_nonneg_left hsmall hscale.le + _ = (phaseErrorNum : Real) / phaseErrorDen := by + field_simp [hden.ne', hscale.ne'] + <;> ring + +theorem phaseErrorRay_le {k : Int} (hlo : -95 ≤ k) (hhi : k ≤ 159) : + phaseErrorRay k ≤ (159 : Real) * phaseErrorNum / phaseErrorDen := by + by_cases hk : k ≤ 0 + · have hkR : (k : Real) ≤ 0 := by exact_mod_cast hk + have herr : phaseErrorRay k ≤ 0 := by + unfold phaseErrorRay + exact mul_nonpos_of_nonpos_of_nonneg hkR phaseDeltaRay_nonneg + exact herr.trans (by positivity) + · have hkR : (k : Real) ≤ 159 := by exact_mod_cast hhi + have hk0R : (0 : Real) ≤ k := by exact_mod_cast (show 0 ≤ k by omega) + unfold phaseErrorRay + calc + (k : Real) * phaseDeltaRay + ≤ (k : Real) * ((phaseErrorNum : Real) / phaseErrorDen) := + mul_le_mul_of_nonneg_left phaseDeltaRay_le hk0R + _ ≤ (159 : Real) * ((phaseErrorNum : Real) / phaseErrorDen) := + mul_le_mul_of_nonneg_right hkR (by positivity) + _ = (159 : Real) * phaseErrorNum / phaseErrorDen := by ring + +theorem core_add_phase_lt_global {e : Real} {k : Int} + (he : e < (coreErrorNum : Real) / coreErrorDen) + (hlo : -95 ≤ k) (hhi : k ≤ 159) : + e + phaseErrorRay k < (globalErrorNum : Real) / globalErrorDen := by + calc + e + phaseErrorRay k < + (coreErrorNum : Real) / coreErrorDen + + (159 : Real) * phaseErrorNum / phaseErrorDen := + add_lt_add_of_lt_of_le he (phaseErrorRay_le hlo hhi) + _ < (globalErrorNum : Real) / globalErrorDen := by + norm_num [coreErrorNum, coreErrorDen, phaseErrorNum, phaseErrorDen, + globalErrorNum, globalErrorDen] + +theorem biasPlusGlobalErrorCap : + capUB + (BIASc * 2 ^ 27 * globalErrorDen + globalErrorNum * 2 ^ 99) + (QS * globalErrorDen) Sc (10 ^ 18) := by + refine capUB_of_partial (K := 130) + (by unfold globalErrorDen QS; decide) (by decide) ?_ + decide + +theorem biasPlusGlobalErrorExpLe : + Real.exp (biasNatural + + ((globalErrorNum : Real) / globalErrorDen) / 10 ^ 27) ≤ + (Sc : Real) / 10 ^ 18 := by + have hexp := exp_le_of_capUB + (p := BIASc * 2 ^ 27 * globalErrorDen + globalErrorNum * 2 ^ 99) + (q := QS * globalErrorDen) (y := Sc) (w := 10 ^ 18) + (by unfold globalErrorDen QS; decide) (by decide) biasPlusGlobalErrorCap + have heq : + (((BIASc * 2 ^ 27 * globalErrorDen + globalErrorNum * 2 ^ 99 : Nat) : Real) / + ((QS * globalErrorDen : Nat) : Real)) = + biasNatural + ((globalErrorNum : Real) / globalErrorDen) / 10 ^ 27 := by + norm_num [biasNatural, BIASc, globalErrorNum, globalErrorDen, QS] + rw [← heq] + norm_num at hexp ⊢ + exact hexp + +theorem bias_add_core_phase_exp_lt {e : Real} {k : Int} + (he : e < (coreErrorNum : Real) / coreErrorDen) + (hlo : -95 ≤ k) (hhi : k ≤ 159) : + Real.exp (biasNatural + (e + phaseErrorRay k) / 10 ^ 27) < + (Sc : Real) / 10 ^ 18 := by + have herr := core_add_phase_lt_global he hlo hhi + have harg : biasNatural + (e + phaseErrorRay k) / 10 ^ 27 < + biasNatural + ((globalErrorNum : Real) / globalErrorDen) / 10 ^ 27 := by + exact add_lt_add_left (div_lt_div_of_pos_right herr (by positivity)) _ + exact (Real.exp_lt_exp.mpr harg).trans_le biasPlusGlobalErrorExpLe + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Runtime.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Runtime.lean new file mode 100644 index 000000000..6e74b251f --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Runtime.lean @@ -0,0 +1,62 @@ +import LnProof.Floor.CarryIndependent.AnalyticRuntime +import LnProof.Floor.CarryIndependent.WordRuntime + +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul + +noncomputable section + +theorem low_runtime_core_bound {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) + (hApprox : approximationTerm m ≤ approximationBudget) + (hHorner : hornerTerm m ≤ hornerBudget) : + rayScale * + ((int256 (x1W (zWord m)) : Real) / 2 ^ 99 - + Real.log ((m : Real) / Sc)) < + coreErrorLimit := by + have hword := runtime_le_lowShadow hmlo hmsc + have hanalytic := lowShadow_core_bound hmlo hmsc hApprox hHorner + have hscaled : + rayScale * + ((int256 (x1W (zWord m)) : Real) / 2 ^ 99 - + Real.log ((m : Real) / Sc)) ≤ + rayScale * (lowShadow m - Real.log ((m : Real) / Sc)) := + mul_le_mul_of_nonneg_left (sub_le_sub_right hword _) (by positivity) + exact hscaled.trans_lt hanalytic + +theorem high_runtime_core_bound {m : Nat} + (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) + (hApprox : highApproximationTerm m ≤ approximationBudget) : + rayScale * + ((int256 (x1W (zWord m)) : Real) / 2 ^ 99 - + Real.log ((m : Real) / Sc)) < + coreErrorLimit := by + have hword := runtime_le_highShadow hscm hmhi + have hanalytic := highShadow_core_bound hscm hmhi hApprox + have hscaled : + rayScale * + ((int256 (x1W (zWord m)) : Real) / 2 ^ 99 - + Real.log ((m : Real) / Sc)) ≤ + rayScale * (highShadow m - Real.log ((m : Real) / Sc)) := + mul_le_mul_of_nonneg_left (sub_le_sub_right hword _) (by positivity) + exact hscaled.trans_lt hanalytic + +theorem mantissa_runtime_core_bound {m : Nat} + (hmlo : 2 ^ 95 ≤ m) (hmhi : m < 2 ^ 96) + (hLowApprox : m < Sc → approximationTerm m ≤ approximationBudget) + (hLowHorner : m < Sc → hornerTerm m ≤ hornerBudget) + (hHighApprox : Sc ≤ m → highApproximationTerm m ≤ approximationBudget) : + rayScale * + ((int256 (x1W (zWord m)) : Real) / 2 ^ 99 - + Real.log ((m : Real) / Sc)) < + coreErrorLimit := by + rcases lt_or_ge m Sc with hmsc | hscm + · exact low_runtime_core_bound hmlo hmsc (hLowApprox hmsc) (hLowHorner hmsc) + · exact high_runtime_core_bound hscm hmhi (hHighApprox hscm) + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/StageErrors.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/StageErrors.lean new file mode 100644 index 000000000..4b0e067a1 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/StageErrors.lean @@ -0,0 +1,467 @@ +import LnProof.Floor.CarryIndependent.Bounds + +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul Common.Poly + +set_option maxRecDepth 8192 + +noncomputable section + +def pErrorNum (u : Nat) : Int := + 2 ^ 274 + 2 ^ 187 * (u : Int) + 2 ^ 90 * (u : Int) ^ 2 + (u : Int) ^ 3 + +def dErrorNum (u : Nat) : Int := + 2 ^ 273 + 2 ^ 178 * (u : Int) + 2 ^ 90 * (u : Int) ^ 2 + (u : Int) ^ 3 + +theorem pError_eq (u : Nat) : + pError u = (pErrorNum u : Real) / 2 ^ 274 := by + norm_num [pError, pErrorNum] + ring + +theorem dError_eq (u : Nat) : + dError u = (dErrorNum u : Real) / 2 ^ 273 := by + norm_num [dError, dErrorNum] + ring + +theorem pError_eq_scaled (u : Nat) : + pError u = ((pErrorNum u * 2 ^ 84 : Int) : Real) / pScale := by + rw [pError_eq] + norm_num [pScale] + ring + +theorem dError_eq_scaled (u : Nat) : + dError u = ((dErrorNum u * 2 ^ 113 : Int) : Real) / qScale := by + rw [dError_eq] + norm_num [qScale] + ring + +theorem pError_nonneg (u : Nat) : 0 ≤ pError u := by + unfold pError + positivity + +theorem dError_nonneg (u : Nat) : 0 ≤ dError u := by + unfold dError + positivity + +private theorem scaled_error_step {ideal runtime shifted u scale radix error : Int} + (herror : ideal - runtime * scale ≤ error) + (hu0 : 0 ≤ u) (hscale : 0 ≤ scale) + (hshift : runtime * u < shifted * radix + radix) : + ideal * u - shifted * (scale * radix) ≤ + error * u + scale * radix := by + have hresidue : runtime * u - shifted * radix ≤ radix := by omega + calc + ideal * u - shifted * (scale * radix) = + (ideal - runtime * scale) * u + + scale * (runtime * u - shifted * radix) := by ring + _ ≤ error * u + scale * radix := + add_le_add (mul_le_mul_of_nonneg_right herror hu0) + (mul_le_mul_of_nonneg_left hresidue hscale) + +private theorem pS1_error {u : Nat} (hu : u ≤ Uc) : + evalPoly PP1c (u : Int) - int256 (pS1 u) * 2 ^ 84 ≤ 2 ^ 84 := by + have h := (pS1_facts hu).2.2.2.1 + simp only [SLOPP1] at h + omega + +private theorem pS2_error {u : Nat} (hu : u ≤ Uc) : + evalPoly PP2c (u : Int) - int256 (pS2 u) * 2 ^ 174 ≤ + 2 ^ 84 * ((u : Int) + 2 ^ 90) := by + obtain ⟨hw, hlo, hhi, _, _⟩ := pS1_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (pS1 u) u) = int256 (pS1 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_90 (evmMul_lt (pS1 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (-(541794612910710781063899171 : Int)) ≤ + int256 (evmSar 90 (evmMul (pS1 u) u)) ∧ + int256 (evmSar 90 (evmMul (pS1 u) u)) ≤ 0 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (pS1 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 90 (evmMul (pS1 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 P2c = (75095323053466847604974837616 : Int) := + toInt_of_lt (by norm_num [P2c]) + have hT : int256 (pS2 u) = + int256 (evmSar 90 (evmMul (pS1 u) u)) + + (75095323053466847604974837616 : Int) := by + unfold pS2 + rw [← hcT] + refine evmAdd_transport hwm (by norm_num [P2c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ + -541794612910710781063899171 + 75095323053466847604974837616 := by norm_num + _ ≤ int256 (evmSar 90 (evmMul (pS1 u) u)) + + 75095323053466847604974837616 := + add_le_add_right hshiftRange.1 _ + · rw [hcT] + exact (add_le_add_right hshiftRange.2 75095323053466847604974837616).trans_lt + (by norm_num) + have heval : evalPoly PP2c (u : Int) = + (1798175745614395766239082622521528960720477616324792863638563111730471590055378944 : Int) + + evalPoly PP1c (u : Int) * (u : Int) := by + show (1798175745614395766239082622521528960720477616324792863638563111730471590055378944 : Int) + + (u : Int) * evalPoly PP1c (u : Int) = _ + rw [Int.mul_comm] + have hstep := scaled_error_step (pS1_error hu) hu0 (by norm_num : (0 : Int) ≤ 2 ^ 84) hs2 + rw [hT, heval] + generalize hshift : int256 (evmSar 90 (evmMul (pS1 u) u)) = shift at hstep ⊢ + norm_num at hstep ⊢ + linarith + +private theorem pS3_error {u : Nat} (hu : u ≤ Uc) : + evalPoly PP3c (u : Int) - int256 (pS3 u) * 2 ^ 271 ≤ + 2 ^ 84 * (((u : Int) + 2 ^ 90) * (u : Int) + 2 ^ 187) := by + obtain ⟨hw, hlo, hhi, _, _⟩ := pS2_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (pS2 u) u) = int256 (pS2 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_97 (evmMul_lt (pS2 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (0 : Int) ≤ int256 (evmSar 97 (evmMul (pS2 u) u)) ∧ + int256 (evmSar 97 (evmMul (pS2 u) u)) ≤ + 1105299956457643323759552745 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (pS2 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 97 (evmMul (pS2 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 P1c = (55801080067338082314461576444 : Int) := + toInt_of_lt (by norm_num [P1c]) + have hT : int256 (pS3 u) = + int256 (evmSar 97 (evmMul (pS2 u) u)) - + (55801080067338082314461576444 : Int) := by + unfold pS3 + rw [← hcT] + refine evmSub_transport hwm (by norm_num [P1c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ 0 - 55801080067338082314461576444 := by norm_num + _ ≤ int256 (evmSar 97 (evmMul (pS2 u) u)) - + 55801080067338082314461576444 := + sub_le_sub_right hshiftRange.1 _ + · rw [hcT] + exact (sub_le_sub_right hshiftRange.2 55801080067338082314461576444).trans_lt + (by norm_num) + have heval : evalPoly PP3c (u : Int) = + (-(211724653123857194763950383720687822670307458715746667734762451892717657012841722322962591250252321890880192512 : Int)) + + evalPoly PP2c (u : Int) * (u : Int) := by + show (-(211724653123857194763950383720687822670307458715746667734762451892717657012841722322962591250252321890880192512 : Int)) + + (u : Int) * evalPoly PP2c (u : Int) = _ + rw [Int.mul_comm] + have hstep := scaled_error_step (pS2_error hu) hu0 (by norm_num : (0 : Int) ≤ 2 ^ 174) hs2 + rw [hT, heval] + generalize hshift : int256 (evmSar 97 (evmMul (pS2 u) u)) = shift at hstep ⊢ + norm_num at hstep ⊢ + linarith + +private theorem pS4_error {u : Nat} (hu : u ≤ Uc) : + evalPoly PPc (u : Int) - int256 (pS4 u) * pScale ≤ + pErrorNum u * 2 ^ 84 := by + obtain ⟨hw, hlo, hhi, _, _⟩ := pS3_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (pS3 u) u) = int256 (pS3 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_87 (evmMul_lt (pS3 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (-(841026779744997415277863435595 : Int)) ≤ + int256 (evmSar 87 (evmMul (pS3 u) u)) ∧ + int256 (evmSar 87 (evmMul (pS3 u) u)) ≤ 0 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (pS3 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 87 (evmMul (pS3 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 C0c = (13972178604861559108982341686387 : Int) := + toInt_of_lt (by norm_num [C0c]) + have hT : int256 (pS4 u) = + int256 (evmSar 87 (evmMul (pS3 u) u)) + + (13972178604861559108982341686387 : Int) := by + unfold pS4 + rw [← hcT] + refine evmAdd_transport hwm (by norm_num [C0c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ + -841026779744997415277863435595 + 13972178604861559108982341686387 := by norm_num + _ ≤ int256 (evmSar 87 (evmMul (pS3 u) u)) + + 13972178604861559108982341686387 := + add_le_add_right hshiftRange.1 _ + · rw [hcT] + exact (add_le_add_right hshiftRange.2 13972178604861559108982341686387).trans_lt + (by norm_num) + have heval : evalPoly PPc (u : Int) = + (8203564106909714963200842018502018851024462725819431901516251320229929630934299039494945066816553616430456446611805193566972803059892092928 : Int) + + evalPoly PP3c (u : Int) * (u : Int) := by + show (8203564106909714963200842018502018851024462725819431901516251320229929630934299039494945066816553616430456446611805193566972803059892092928 : Int) + + (u : Int) * evalPoly PP3c (u : Int) = _ + rw [Int.mul_comm] + have hstep := scaled_error_step (pS3_error hu) hu0 (by norm_num : (0 : Int) ≤ 2 ^ 271) hs2 + rw [hT, heval] + generalize hshift : int256 (evmSar 87 (evmMul (pS3 u) u)) = shift at hstep ⊢ + norm_num [pScale, pErrorNum] at hstep ⊢ + nlinarith + +private theorem qS1_error {u : Nat} (hu : u ≤ Uc) : + evalPoly QQ1c (u : Int) - int256 (qS1 u) * (1 : Int) ≤ 0 := by + have h := (qS1_facts hu).2.2.2.1 + simp only [SLOPQ1, sub_zero] at h + omega + +private theorem qS2_error {u : Nat} (hu : u ≤ Uc) : + evalPoly QQ2c (u : Int) - int256 (qS2 u) * 2 ^ 113 ≤ 2 ^ 113 := by + obtain ⟨hw, hlo, hhi, _, _⟩ := qS1_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (qS1 u) u) = int256 (qS1 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_113 (evmMul_lt (qS1 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (-(965694431563962025332668 : Int)) ≤ + int256 (evmSar 113 (evmMul (qS1 u) u)) ∧ + int256 (evmSar 113 (evmMul (qS1 u) u)) ≤ 0 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (qS1 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 113 (evmMul (qS1 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 Q3c = (281702237671157106654810095 : Int) := + toInt_of_lt (by norm_num [Q3c]) + have hT : int256 (qS2 u) = + int256 (evmSar 113 (evmMul (qS1 u) u)) + + (281702237671157106654810095 : Int) := by + unfold qS2 + rw [← hcT] + refine evmAdd_transport hwm (by norm_num [Q3c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ + -965694431563962025332668 + 281702237671157106654810095 := by norm_num + _ ≤ int256 (evmSar 113 (evmMul (qS1 u) u)) + + 281702237671157106654810095 := add_le_add_right hshiftRange.1 _ + · rw [hcT] + exact (add_le_add_right hshiftRange.2 281702237671157106654810095).trans_lt + (by norm_num) + have heval : evalPoly QQ2c (u : Int) = + (2925363287404360843667081098480704995728827760271876675338240 : Int) + + evalPoly QQ1c (u : Int) * (u : Int) := by + show (2925363287404360843667081098480704995728827760271876675338240 : Int) + + (u : Int) * evalPoly QQ1c (u : Int) = _ + rw [Int.mul_comm] + have hprevious := qS1_error hu + have hscale : (0 : Int) ≤ 1 := zero_le_one + generalize hruntime : int256 (qS1 u) = runtime at hprevious hs2 + generalize hshift : int256 (evmSar 113 (evmMul (qS1 u) u)) = shift at hs2 + have hstep := scaled_error_step hprevious hu0 hscale hs2 + rw [hT, heval] + rw [hshift] + norm_num at hstep ⊢ + linarith + +private theorem qS3_error {u : Nat} (hu : u ≤ Uc) : + evalPoly QQ3c (u : Int) - int256 (qS3 u) * 2 ^ 203 ≤ + 2 ^ 113 * ((u : Int) + 2 ^ 90) := by + obtain ⟨hw, hlo, hhi, _, _⟩ := qS2_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (qS2 u) u) = int256 (qS2 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_90 (evmMul_lt (qS2 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (0 : Int) ≤ int256 (evmSar 90 (evmMul (qS2 u) u)) ∧ + int256 (evmSar 90 (evmMul (qS2 u) u)) ≤ 530722535992203150542952384 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (qS2 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 90 (evmMul (qS2 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 Q2c = (53722296096946541673620529149 : Int) := + toInt_of_lt (by norm_num [Q2c]) + have hT : int256 (qS3 u) = + int256 (evmSar 90 (evmMul (qS2 u) u)) - + (53722296096946541673620529149 : Int) := by + unfold qS3 + rw [← hcT] + refine evmSub_transport hwm (by norm_num [Q2c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ 0 - 53722296096946541673620529149 := by norm_num + _ ≤ int256 (evmSar 90 (evmMul (qS2 u) u)) - + 53722296096946541673620529149 := sub_le_sub_right hshiftRange.1 _ + · rw [hcT] + exact (sub_le_sub_right hshiftRange.2 53722296096946541673620529149).trans_lt + (by norm_num) + have heval : evalPoly QQ3c (u : Int) = + (-(690627211385037298547738551962892852267586075469791719173459072596031701017399264062472192 : Int)) + + evalPoly QQ2c (u : Int) * (u : Int) := by + show (-(690627211385037298547738551962892852267586075469791719173459072596031701017399264062472192 : Int)) + + (u : Int) * evalPoly QQ2c (u : Int) = _ + rw [Int.mul_comm] + have hprevious := qS2_error hu + have hscale : (0 : Int) ≤ 2 ^ 113 := by norm_num + generalize hruntime : int256 (qS2 u) = runtime at hprevious hs2 + generalize hshift : int256 (evmSar 90 (evmMul (qS2 u) u)) = shift at hs2 + have hstep := scaled_error_step hprevious hu0 hscale hs2 + rw [hT, heval] + rw [hshift] + norm_num at hstep ⊢ + linarith + +private theorem qS4_error {u : Nat} (hu : u ≤ Uc) : + evalPoly QQ4c (u : Int) - int256 (qS4 u) * 2 ^ 291 ≤ + 2 ^ 113 * (((u : Int) + 2 ^ 90) * (u : Int) + 2 ^ 178) := by + obtain ⟨hw, hlo, hhi, _, _⟩ := qS3_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (qS3 u) u) = int256 (qS3 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_88 (evmMul_lt (qS3 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (-(404847806103384053046409292281 : Int)) ≤ + int256 (evmSar 88 (evmMul (qS3 u) u)) ∧ + int256 (evmSar 88 (evmMul (qS3 u) u)) ≤ 0 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (qS3 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 88 (evmMul (qS3 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 Q1c = (16613772931382142257332678212554 : Int) := + toInt_of_lt (by norm_num [Q1c]) + have hT : int256 (qS4 u) = + int256 (evmSar 88 (evmMul (qS3 u) u)) + + (16613772931382142257332678212554 : Int) := by + unfold qS4 + rw [← hcT] + refine evmAdd_transport hwm (by norm_num [Q1c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ + -404847806103384053046409292281 + 16613772931382142257332678212554 := by norm_num + _ ≤ int256 (evmSar 88 (evmMul (qS3 u) u)) + + 16613772931382142257332678212554 := add_le_add_right hshiftRange.1 _ + · rw [hcT] + exact (add_le_add_right hshiftRange.2 16613772931382142257332678212554).trans_lt + (by norm_num) + have heval : evalPoly QQ4c (u : Int) = + (66099322585698201304896817119133314370855648754593283446756353822335972946493244703677923116935407234039976856169480192 : Int) + + evalPoly QQ3c (u : Int) * (u : Int) := by + show (66099322585698201304896817119133314370855648754593283446756353822335972946493244703677923116935407234039976856169480192 : Int) + + (u : Int) * evalPoly QQ3c (u : Int) = _ + rw [Int.mul_comm] + have hprevious := qS3_error hu + have hscale : (0 : Int) ≤ 2 ^ 203 := by norm_num + generalize hruntime : int256 (qS3 u) = runtime at hprevious hs2 + generalize hshift : int256 (evmSar 88 (evmMul (qS3 u) u)) = shift at hs2 + have hstep := scaled_error_step hprevious hu0 hscale hs2 + rw [hT, heval] + rw [hshift] + norm_num at hstep ⊢ + linarith + +theorem qS5_error {u : Nat} (hu : u ≤ Uc) : + evalPoly QQc (u : Int) - int256 (qS5 u) * qScale ≤ + dErrorNum u * 2 ^ 113 := by + obtain ⟨hw, hlo, hhi, _, _⟩ := qS4_facts hu + have htu : int256 u = (u : Int) := toInt_u hu + have hu256 : u < 2 ^ 256 := hu.trans_lt (by norm_num [Uc]) + have hu0 : (0 : Int) ≤ (u : Int) := Int.ofNat_zero_le u + have huU : (u : Int) ≤ Uc := by exact_mod_cast hu + have hrange := mul_range hlo hhi hu0 huU + have hmT : int256 (evmMul (qS4 u) u) = int256 (qS4 u) * (u : Int) := by + rw [← htu] + refine evmMul_transport hw hu256 ?_ ?_ <;> rw [htu] <;> + simp only [ipow255, Uc] at hrange ⊢ <;> omega + obtain ⟨hwm, hs1, hs2⟩ := evmSar_sandwich_95 (evmMul_lt (qS4 u) u) + rw [hmT] at hs1 hs2 + have hshiftRange : + (0 : Int) ≤ int256 (evmSar 95 (evmMul (qS4 u) u)) ∧ + int256 (evmSar 95 (evmMul (qS4 u) u)) ≤ 978127625049538968174347910714 := by + simp only [Uc] at huU hrange + clear hw hlo hhi hu htu hu256 hmT hwm + generalize hmul : int256 (evmMul (qS4 u) u) = mul at hs1 hs2 hrange + generalize hshift : int256 (evmSar 95 (evmMul (qS4 u) u)) = shift at hs1 hs2 ⊢ + omega + have hcT : int256 C0c = (13972178604861559108982341686387 : Int) := + toInt_of_lt (by norm_num [C0c]) + have hT : int256 (qS5 u) = + int256 (evmSar 95 (evmMul (qS4 u) u)) - + (13972178604861559108982341686387 : Int) := by + unfold qS5 + rw [← hcT] + refine evmSub_transport hwm (by norm_num [C0c]) ?_ ?_ + · rw [hcT] + calc + -(2 ^ 255 : Int) ≤ 0 - 13972178604861559108982341686387 := by norm_num + _ ≤ int256 (evmSar 95 (evmMul (qS4 u) u)) - + 13972178604861559108982341686387 := sub_le_sub_right hshiftRange.1 _ + · rw [hcT] + exact (sub_le_sub_right hshiftRange.2 13972178604861559108982341686387).trans_lt + (by norm_num) + have heval : evalPoly QQc (u : Int) = + (-(2202127471863542086976841246820549867195347718960342176144462014556523185327760268707187588705852038374958668534379582118318610928980329275922055168 : Int)) + + evalPoly QQ4c (u : Int) * (u : Int) := by + show (-(2202127471863542086976841246820549867195347718960342176144462014556523185327760268707187588705852038374958668534379582118318610928980329275922055168 : Int)) + + (u : Int) * evalPoly QQ4c (u : Int) = _ + rw [Int.mul_comm] + have hprevious := qS4_error hu + have hscale : (0 : Int) ≤ 2 ^ 291 := by norm_num + generalize hruntime : int256 (qS4 u) = runtime at hprevious hs2 + generalize hshift : int256 (evmSar 95 (evmMul (qS4 u) u)) = shift at hs2 + have hstep := scaled_error_step hprevious hu0 hscale hs2 + rw [hT, heval] + rw [hshift] + norm_num [qScale, dErrorNum] at hstep ⊢ + nlinarith + +theorem pS4_error_bound {u : Nat} (hu : u ≤ Uc) : + evalPoly PPc (u : Int) - int256 (pS4 u) * pScale ≤ + pErrorNum u * 2 ^ 84 := + pS4_error hu + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Upper.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Upper.lean new file mode 100644 index 000000000..038ca755d --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Upper.lean @@ -0,0 +1,46 @@ +import LnProof.Floor.CarryIndependent.Cut + +open FormalYul FormalYul.Preservation + +set_option maxRecDepth 4096 + +namespace LnFloorCarry + +open LnYul LnFloor LnFloorCert + +noncomputable section + +attribute [local irreducible] coreErrorRay zWord x1W lnWadToRayBody CutLeLogWadRay + +private theorem body_mant_pos {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : + 0 < mant x := by + obtain ⟨me, hmlo, _⟩ := mant_facts h1 h2 + have hmlo' : 2 ^ 95 ≤ mant x := by + unfold mant + rw [me] + exact hmlo + exact lt_of_lt_of_le (by positivity : 0 < 2 ^ 95) hmlo' + +theorem lnWadToRayBody_cut_of_core_bound {x : Nat} + (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 1000000000000000000) + (hcore : coreErrorRay (mant x) (int256 (x1W (zWord (mant x)))) < + (coreErrorNum : Real) / coreErrorDen) : + CutLeLogWadRay (int256 (lnWadToRayBody x)) x := by + have hm := body_mant_pos h1 h2 + obtain ⟨hc1, hc255⟩ := clz_bounds h1 h2 + have hwindow : + (evmClz x ≤ 160 ∧ mant x * 2 ^ (160 - evmClz x) ≤ x) ∨ + (160 < evmClz x ∧ mant x = x * 2 ^ (evmClz x - 160)) := by + by_cases hc : evmClz x ≤ 160 + · exact Or.inl ⟨hc, (mant_window_le h1 h2 hc).1⟩ + · exact Or.inr ⟨by omega, mant_window_gt h1 h2 (by omega)⟩ + obtain ⟨hbr, _⟩ := lnWadToRayBody_floor_bracket h1 h2 hne + have hbr' : + int256 (lnWadToRayBody x) * 2 ^ 72 ≤ + accumulatorI (int256 (x1W (zWord (mant x)))) (evmClz x) := by + simpa [accumulatorI, BIASc] using hbr + exact normalized_cut_of_core_bound (by omega) hm hc1 hc255 hwindow hbr' hcore + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/WordRuntime.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/WordRuntime.lean new file mode 100644 index 000000000..e08e2ab84 --- /dev/null +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/WordRuntime.lean @@ -0,0 +1,388 @@ +import LnProof.Floor.CarryIndependent.Normalization +import LnProof.Floor.CarryIndependent.StageErrors + +open FormalYul FormalYul.Preservation + +namespace LnFloorCarry + +open LnYul Common.Poly + +set_option maxRecDepth 8192 + +noncomputable section + +private theorem int_mul_le_mul_of_bounds {a b c d : Int} + (hac : a ≤ c) (hbd : b ≤ d) (hb0 : 0 ≤ b) (ha0 : 0 ≤ a) : + a * b ≤ c * d := + Int.mul_le_mul hac hbd hb0 (ha0.trans hac) + +private theorem int_toNat_pos_of_pos {x : Int} (hx : 0 < x) : 0 < x.toNat := + Int.pos_iff_toNat_pos.mp hx + +private theorem real_int_natCast (n : Nat) : (((n : Int) : Real)) = (n : Real) := by + norm_cast + +theorem x1_floor_eq {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + let z := int256 (zWord m) + let u := uWord (zWord m) + let p := int256 (pS4 u) + let d := -int256 (qS5 u) + int256 (x1W (zWord m)) = -((p.toNat * z.toNat / d.toNat : Nat) : Int) := by + dsimp + have hz := low_z_facts hmlo hmsc + have hu := low_u_facts hmlo hmsc + obtain ⟨hpw, hp0, hp1, _, _⟩ := pS4_facts hu.1 + obtain ⟨hqw, _, hq1, _, _⟩ := qS5_facts hu.1 + have hpnonneg : 0 ≤ int256 (pS4 (uWord (zWord m))) := + (by norm_num : (0 : Int) ≤ 13131151825116561693704478250792).trans hp0 + have hzw : zWord m < 2 ^ 256 := evmSdiv_lt _ _ + have hprod0 : 0 ≤ int256 (pS4 (uWord (zWord m))) * int256 (zWord m) := + Int.mul_nonneg hpnonneg hz.1 + have hprodHi : int256 (pS4 (uWord (zWord m))) * int256 (zWord m) < 2 ^ 255 := by + calc + int256 (pS4 (uWord (zWord m))) * int256 (zWord m) ≤ + (13972178604861559108982341686387 : Int) * Zc := + int_mul_le_mul_of_bounds hp1 hz.2 hz.1 hpnonneg + _ < 2 ^ 255 := by norm_num [Zc] + have hmul : int256 (evmMul (pS4 (uWord (zWord m))) (zWord m)) = + int256 (pS4 (uWord (zWord m))) * int256 (zWord m) := by + apply evmMul_transport hpw hzw + · exact (by norm_num : -(2 ^ 255 : Int) ≤ 0).trans hprod0 + · exact hprodHi + have hmul0 : 0 ≤ int256 (evmMul (pS4 (uWord (zWord m))) (zWord m)) := by + rw [hmul] + exact hprod0 + have hqneg : int256 (qS5 (uWord (zWord m))) < 0 := + hq1.trans_lt (by norm_num) + unfold x1W + rw [evmSdiv_pos_neg (evmMul_lt _ _) hqw hmul0 hqneg, hmul] + exact congrArg + (fun n : Nat => + -((n / (-int256 (qS5 (uWord (zWord m)))).toNat : Nat) : Int)) + (Int.toNat_mul hpnonneg hz.1) + +theorem final_stage_sandwich_of_u {u : Nat} (hu : u ≤ Uc) : + let p := (int256 (pS4 u) : Real) + let d := (-int256 (qS5 u) : Int) + exactP u - pError u ≤ p ∧ p ≤ exactP u ∧ + exactD u ≤ (d : Real) ∧ (d : Real) ≤ exactD u + dError u ∧ + 0 < exactD u ∧ 0 < d := by + dsimp + obtain ⟨_, _, _, _, hpHi⟩ := pS4_facts hu + obtain ⟨_, _, hq1, _, hqHi⟩ := qS5_facts hu + have huI : (u : Int) ≤ UcI := by + simp only [UcI] + exact_mod_cast hu + have hcertQ := certQ_all (Int.ofNat_zero_le u) huI + have hpError := pS4_error_bound hu + have hqError := qS5_error hu + have hpLoI : + evalPoly PPc (u : Int) - pErrorNum u * 2 ^ 84 ≤ + int256 (pS4 u) * pScale := by + linarith + have hpLoR : + ((evalPoly PPc (u : Int) - pErrorNum u * 2 ^ 84 : Int) : Real) ≤ + (int256 (pS4 u) : Real) * pScale := by + exact_mod_cast hpLoI + have hpHiR : (int256 (pS4 u) : Real) * pScale ≤ + (evalPoly PPc (u : Int) : Real) := by + exact_mod_cast hpHi + have hqHiR : (int256 (qS5 u) : Real) * qScale ≤ + (evalPoly QQc (u : Int) : Real) := by + exact_mod_cast hqHi + have hdHiI : + (-int256 (qS5 u)) * qScale ≤ + -evalPoly QQc (u : Int) + dErrorNum u * 2 ^ 113 := by + linarith + have hdHiR : + ((-int256 (qS5 u) : Int) : Real) * qScale ≤ + ((-evalPoly QQc (u : Int) : Int) : Real) + + ((dErrorNum u * 2 ^ 113 : Int) : Real) := by + exact_mod_cast hdHiI + have hpScalePos : (0 : Real) < pScale := by norm_num [pScale] + have hqScalePos : (0 : Real) < qScale := by norm_num [qScale] + constructor + · rw [exactP, pError_eq_scaled, ← sub_div] + rw [div_le_iff₀ hpScalePos] + simpa only [Int.cast_sub, Int.cast_mul, Int.cast_pow, Int.cast_ofNat] using hpLoR + constructor + · simp only [exactP] + rw [le_div_iff₀ hpScalePos] + exact hpHiR + constructor + · simp only [exactD] + rw [div_le_iff₀ hqScalePos] + calc + ((-evalPoly QQc (u : Int) : Int) : Real) = + -(evalPoly QQc (u : Int) : Real) := by rw [Int.cast_neg] + _ ≤ -((int256 (qS5 u) : Real) * qScale) := neg_le_neg hqHiR + _ = ((-int256 (qS5 u) : Int) : Real) * qScale := by + rw [Int.cast_neg] + ring + constructor + · rw [exactD, dError_eq_scaled, ← add_div, le_div_iff₀ hqScalePos] + simpa only [Int.cast_add, Int.cast_neg] using hdHiR + constructor + · simp only [exactD] + apply div_pos + · have : (0 : Int) < -evalPoly QQc (u : Int) := + (by norm_num [SLOPQc] : (0 : Int) < SLOPQc).trans_le hcertQ + exact_mod_cast this + · exact hqScalePos + · have hdPos : (0 : Int) < -int256 (qS5 u) := + neg_pos.mpr (hq1.trans_lt (by norm_num)) + exact_mod_cast hdPos + +theorem runtimeRatio_ge_shadow_of_u {u : Nat} (hu : u ≤ Uc) : + shadowRatio u ≤ + (int256 (pS4 u) : Real) / (-int256 (qS5 u) : Int) := by + obtain ⟨hpLo, _, _, hdHi, hD0, hd0⟩ := final_stage_sandwich_of_u hu + have hden0 : 0 < exactD u + dError u := + add_pos_of_pos_of_nonneg hD0 (dError_nonneg u) + have hd0R : (0 : Real) < (-int256 (qS5 u) : Int) := by + exact_mod_cast hd0 + have hp0R : (0 : Real) ≤ int256 (pS4 u) := by + have hp0 := (pS4_facts hu).2.1 + have hp0I : (0 : Int) ≤ int256 (pS4 u) := + (by norm_num : (0 : Int) ≤ 13131151825116561693704478250792).trans hp0 + exact_mod_cast hp0I + unfold shadowRatio + rw [div_le_div_iff₀ hden0 hd0R] + exact mul_le_mul hpLo hdHi hd0R.le hp0R + +theorem runtimeRatio_ge_shadow {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + shadowRatio (uWord (zWord m)) ≤ + (int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int) := by + exact runtimeRatio_ge_shadow_of_u (low_u_facts hmlo hmsc).1 + +theorem runtimeRatio_le_exact_of_u {u : Nat} (hu : u ≤ Uc) : + (int256 (pS4 u) : Real) / (-int256 (qS5 u) : Int) ≤ exactRatio u := by + obtain ⟨_, hpHi, hdLo, _, hD0, hd0⟩ := final_stage_sandwich_of_u hu + have hp0 : (0 : Real) ≤ int256 (pS4 u) := by + have hpFacts := (pS4_facts hu).2.1 + have hp0I : (0 : Int) ≤ int256 (pS4 u) := + (by norm_num : (0 : Int) ≤ 13131151825116561693704478250792).trans hpFacts + exact_mod_cast hp0I + have hd0R : (0 : Real) < (-int256 (qS5 u) : Int) := by exact_mod_cast hd0 + have hP0 : (0 : Real) ≤ exactP u := hp0.trans hpHi + unfold exactRatio + rw [div_le_div_iff₀ hd0R hD0] + exact mul_le_mul hpHi hdLo hD0.le hP0 + +theorem nat_div_real_lt_add_one {n d : Nat} (hd : 0 < d) : + (n : Real) / d < (n / d : Nat) + 1 := by + have hmod := Nat.mod_lt n hd + have hNat : n < (n / d + 1) * d := by + calc + n = (n / d) * d + n % d := by + rw [mul_comm (n / d)] + exact (Nat.div_add_mod _ _).symm + _ < (n / d) * d + d := Nat.add_lt_add_left hmod _ + _ = (n / d + 1) * d := by rw [Nat.add_mul, one_mul] + rw [div_lt_iff₀ (by exact_mod_cast hd : (0 : Real) < d)] + exact_mod_cast hNat + +theorem nat_div_real_le {n d : Nat} (hd : 0 < d) : + ((n / d : Nat) : Real) ≤ (n : Real) / d := by + rw [le_div_iff₀ (by exact_mod_cast hd : (0 : Real) < d)] + exact_mod_cast Nat.div_mul_le_self n d + +theorem high_x1_floor_eq {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + let z := int256 (zWord m) + let u := uWord (zWord m) + let p := int256 (pS4 u) + let d := -int256 (qS5 u) + int256 (x1W (zWord m)) = (((-(p * z)).toNat / d.toNat : Nat) : Int) := by + dsimp + have hz := high_z_facts hscm hmhi + have hu := high_u_facts hscm hmhi + obtain ⟨hpw, hp0, hp1, _, _⟩ := pS4_facts hu.1 + obtain ⟨hqw, _, hq1, _, _⟩ := qS5_facts hu.1 + have hpPos : 0 < int256 (pS4 (uWord (zWord m))) := + (by norm_num : (0 : Int) < 13131151825116561693704478250792).trans_le hp0 + have hzw : zWord m < 2 ^ 256 := evmSdiv_lt _ _ + have hpz := pz_bound hp0 hp1 hz.1 + (hz.2.trans (by norm_num)) + have hmul : int256 (evmMul (pS4 (uWord (zWord m))) (zWord m)) = + int256 (pS4 (uWord (zWord m))) * int256 (zWord m) := + evmMul_transport hpw hzw hpz.1.le hpz.2 + have hqneg : int256 (qS5 (uWord (zWord m))) < 0 := + hq1.trans_lt (by norm_num) + unfold x1W + rcases eq_or_lt_of_le hz.2 with hzEq | hzNeg + · have hmul0 : 0 ≤ + int256 (evmMul (pS4 (uWord (zWord m))) (zWord m)) := by + rw [hmul, hzEq, mul_zero] + calc + int256 (evmSdiv (evmMul (pS4 (uWord (zWord m))) (zWord m)) + (qS5 (uWord (zWord m)))) = + -(((int256 (evmMul (pS4 (uWord (zWord m))) (zWord m))).toNat / + (-int256 (qS5 (uWord (zWord m)))).toNat : Nat) : Int) := + evmSdiv_pos_neg (evmMul_lt _ _) hqw hmul0 hqneg + _ = 0 := by + rw [hmul, hzEq, mul_zero, Int.toNat_zero, Nat.zero_div] + simp only [Int.ofNat_zero, neg_zero] + _ = (((-(int256 (pS4 (uWord (zWord m))) * int256 (zWord m))).toNat / + (-int256 (qS5 (uWord (zWord m)))).toNat : Nat) : Int) := by + rw [hzEq, mul_zero, neg_zero, Int.toNat_zero, Nat.zero_div] + simp only [Int.ofNat_zero] + · have hmulNeg : int256 (evmMul (pS4 (uWord (zWord m))) (zWord m)) < 0 := by + rw [hmul] + exact Int.mul_neg_of_pos_of_neg hpPos hzNeg + have hmulMin : -(2 ^ 255) < + int256 (evmMul (pS4 (uWord (zWord m))) (zWord m)) := by + rw [hmul] + exact hpz.1 + calc + int256 (evmSdiv (evmMul (pS4 (uWord (zWord m))) (zWord m)) + (qS5 (uWord (zWord m)))) = + (((-int256 (evmMul (pS4 (uWord (zWord m))) (zWord m))).toNat / + (-int256 (qS5 (uWord (zWord m)))).toNat : Nat) : Int) := + evmSdiv_neg_neg (evmMul_lt _ _) hqw hmulNeg hmulMin hqneg + _ = (((-(int256 (pS4 (uWord (zWord m))) * int256 (zWord m))).toNat / + (-int256 (qS5 (uWord (zWord m)))).toNat : Nat) : Int) := by + exact congrArg + (fun n : Nat => + ((n / (-int256 (qS5 (uWord (zWord m)))).toNat : Nat) : Int)) + (congrArg (fun x : Int => (-x).toNat) hmul) + +theorem highClosingDivision_le {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + (int256 (x1W (zWord m)) : Real) / 2 ^ 99 ≤ + 2 * highNormalizedZ m * + ((int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int)) := by + have hz := high_z_facts hscm hmhi + have hu := high_u_facts hscm hmhi + have hp0 := (pS4_facts hu.1).2.1 + have hq1 := (qS5_facts hu.1).2.2.1 + let p := int256 (pS4 (uWord (zWord m))) + let z := int256 (zWord m) + let d := -int256 (qS5 (uWord (zWord m))) + have hp : 0 ≤ p := by + dsimp [p] + exact (by norm_num : (0 : Int) ≤ 13131151825116561693704478250792).trans hp0 + have hz0 : z ≤ 0 := by exact hz.2 + have hn : 0 ≤ -(p * z) := by + rw [neg_nonneg] + exact Int.mul_nonpos_of_nonneg_of_nonpos hp hz0 + have hd : 0 < d := by + dsimp [d] + exact neg_pos.mpr (hq1.trans_lt (by norm_num)) + have hdNat : 0 < d.toNat := @int_toNat_pos_of_pos d hd + have hfloor := nat_div_real_le + (n := (-(p * z)).toNat) (d := d.toNat) hdNat + rw [real_cast_toNat hn, real_cast_toNat hd.le] at hfloor + have hnegMulCast : ((-(p * z) : Int) : Real) = -(p : Real) * (z : Real) := by + rw [Int.cast_neg, Int.cast_mul] + ring + rw [hnegMulCast] at hfloor + have hx : int256 (x1W (zWord m)) = + (((-(p * z)).toNat / d.toNat : Nat) : Int) := by + simpa only [p, z, d] using high_x1_floor_eq hscm hmhi + have hxR : (int256 (x1W (zWord m)) : Real) = + (((-(p * z)).toNat / d.toNat : Nat) : Real) := + Eq.trans (congrArg (fun x : Int => (x : Real)) hx) (real_int_natCast _) + rw [hxR] + calc + (((-(p * z)).toNat / d.toNat : Nat) : Real) / 2 ^ 99 ≤ + (-(p : Real) * z / d) / 2 ^ 99 := + div_le_div_of_nonneg_right hfloor (by positivity) + _ = 2 * highNormalizedZ m * + ((int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int)) := by + unfold highNormalizedZ p z d + norm_num [wordQ100] + ring + +theorem neg_floor_div_le {p z d : Int} (hp : 0 ≤ p) (hz : 0 ≤ z) (hd : 0 < d) : + -(((p.toNat * z.toNat / d.toNat : Nat) : Real)) ≤ + -(p : Real) * (z : Real) / (d : Real) + 1 := by + have hdNat : 0 < d.toNat := @int_toNat_pos_of_pos d hd + have hfloor := nat_div_real_lt_add_one (n := p.toNat * z.toNat) (d := d.toNat) hdNat + simp only [Nat.cast_mul] at hfloor + rw [real_cast_toNat hp, real_cast_toNat hz, real_cast_toNat hd.le] at hfloor + have hsub : (p : Real) * z / d - 1 < + ((p.toNat * z.toNat / d.toNat : Nat) : Real) := + (sub_lt_iff_lt_add).2 hfloor + have hneg := neg_lt_neg hsub + exact le_of_lt (by + calc + -(((p.toNat * z.toNat / d.toNat : Nat) : Real)) < + -((p : Real) * z / d - 1) := hneg + _ = -(p : Real) * z / d + 1 := by ring) + +theorem closingDivision_le {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + (int256 (x1W (zWord m)) : Real) / 2 ^ 99 ≤ + -2 * normalizedZ m * + ((int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int)) + + 2 / wordQ100 := by + have hz := low_z_facts hmlo hmsc + have hu := low_u_facts hmlo hmsc + have hp0 := (pS4_facts hu.1).2.1 + have hq1 := (qS5_facts hu.1).2.2.1 + let p := int256 (pS4 (uWord (zWord m))) + let z := int256 (zWord m) + let d := -int256 (qS5 (uWord (zWord m))) + have hp : 0 ≤ p := by + dsimp [p] + exact (by norm_num : (0 : Int) ≤ 13131151825116561693704478250792).trans hp0 + have hz0 : 0 ≤ z := by exact hz.1 + have hd : 0 < d := by + dsimp [d] + exact neg_pos.mpr (hq1.trans_lt (by norm_num)) + have hfloor := neg_floor_div_le hp hz0 hd + have hx : int256 (x1W (zWord m)) = + -((p.toNat * z.toNat / d.toNat : Nat) : Int) := by + simpa only [p, z, d] using x1_floor_eq hmlo hmsc + have hxR : (int256 (x1W (zWord m)) : Real) = + -(((p.toNat * z.toNat / d.toNat : Nat) : Real)) := by exact_mod_cast hx + rw [hxR] + calc + -(((p.toNat * z.toNat / d.toNat : Nat) : Real)) / 2 ^ 99 ≤ + (-(p : Real) * z / d + 1) / 2 ^ 99 := + div_le_div_of_nonneg_right hfloor (by positivity) + _ = -2 * normalizedZ m * + ((int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int)) + + 2 / wordQ100 := by + unfold normalizedZ p z d + norm_num [wordQ100] + ring + +theorem runtime_le_lowShadow {m : Nat} (hmlo : 2 ^ 95 ≤ m) (hmsc : m < Sc) : + (int256 (x1W (zWord m)) : Real) / 2 ^ 99 ≤ lowShadow m := by + have hclose := closingDivision_le hmlo hmsc + have hratio := runtimeRatio_ge_shadow hmlo hmsc + have ha0 := (low_endpoint_bounds hmlo hmsc).1 + have hscaledNonpos : (0 : Real) ≥ -2 * normalizedZ m := + mul_nonpos_of_nonpos_of_nonneg (by norm_num) ha0 + have hscaled : + -2 * normalizedZ m * + ((int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int)) ≤ + -2 * normalizedZ m * shadowRatio (uWord (zWord m)) := + mul_le_mul_of_nonpos_left hratio hscaledNonpos + unfold lowShadow + exact hclose.trans (add_le_add_right hscaled _) + +theorem runtime_le_highShadow {m : Nat} (hscm : Sc ≤ m) (hmhi : m < 2 ^ 96) : + (int256 (x1W (zWord m)) : Real) / 2 ^ 99 ≤ highShadow m := by + have hclose := highClosingDivision_le hscm hmhi + have hratio := runtimeRatio_le_exact_of_u (high_u_facts hscm hmhi).1 + have hb0 := (high_endpoint_bounds hscm hmhi).1 + have hscaledNonneg : (0 : Real) ≤ 2 * highNormalizedZ m := + mul_nonneg (by norm_num) hb0 + have hscaled : + 2 * highNormalizedZ m * + ((int256 (pS4 (uWord (zWord m))) : Real) / + (-int256 (qS5 (uWord (zWord m))) : Int)) ≤ + 2 * highNormalizedZ m * exactRatio (uWord (zWord m)) := + mul_le_mul_of_nonneg_left hratio hscaledNonneg + unfold highShadow + exact hclose.trans hscaled + +end + +end LnFloorCarry diff --git a/formal/ln/LnProof/LnProof/Floor/CertAux.lean b/formal/ln/LnProof/LnProof/Floor/CertAux.lean index 3ffbad005..0a050d821 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertAux.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertAux.lean @@ -5,14 +5,6 @@ open Common.Poly set_option maxRecDepth 100000 -theorem geH_check : checkCover certGeH 56022770974786139918731938273 79228162514264337593543950335 - [23205391539478197674812012062] = true := by - decide +kernel - -theorem geH_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m ≤ 79228162514264337593543950335) : - 0 ≤ evalPoly certGeH m := - checkCover_sound _ _ _ _ geH_check m h1 h2 - theorem ltH_check : checkCover certLtH 39614081257132168796771975168 56022770974786139918731938181 [16408689717653971121959963013] = true := by decide +kernel @@ -21,14 +13,6 @@ theorem ltH_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) (h2 : m 0 ≤ evalPoly certLtH m := checkCover_sound _ _ _ _ ltH_check m h1 h2 -theorem geTD_check : checkCover certGeTD 56022770974786139918731938273 79228162514264337593543950335 - [23205391539478197674812012062] = true := by - decide +kernel - -theorem geTD_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m ≤ 79228162514264337593543950335) : - 0 ≤ evalPoly certGeTD m := - checkCover_sound _ _ _ _ geTD_check m h1 h2 - theorem geTD2_check : checkCover certGeTD2 56022770974786139918731938273 79228162514264337593543950335 [23205391539478197674812012062] = true := by decide +kernel @@ -53,14 +37,6 @@ theorem ltTD2_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) (h2 : 0 ≤ evalPoly certLtTD2 m := checkCover_sound _ _ _ _ ltTD2_check m h1 h2 -theorem geTN_check : checkCover geTN 56022770974786139918731938273 79228162514264337593543950335 - [23205391539478197674812012062] = true := by - decide +kernel - -theorem geTN_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) (h2 : m ≤ 79228162514264337593543950335) : - 0 ≤ evalPoly geTN m := - checkCover_sound _ _ _ _ geTN_check m h1 h2 - theorem geTN2_check : checkCover geTN2b 56022770974786139918731938273 79228162514264337593543950335 [23205391539478197674812012062] = true := by decide +kernel diff --git a/formal/ln/LnProof/LnProof/Floor/CertDefs.lean b/formal/ln/LnProof/LnProof/Floor/CertDefs.lean index b392235e2..dbbe436a1 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertDefs.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertDefs.lean @@ -16,8 +16,6 @@ namespace LnFloorCert open Common.Poly LnYul -def WINDOW : Nat := 46 - def geA : List Int := [-(Sc : Int), 1] def geB : List Int := [(Sc : Int), 1] def geA2 : List Int := polyMul geA geA @@ -25,12 +23,8 @@ def geB2 : List Int := polyMul geB geB def geWLO : List Int := polyAdd (polyAdd (polyScale (2 ^ 99) geA2) (polyNeg (polyMul geA geB))) (polyScale (-8) geB2) def geD8 : List Int := polyScale 8 geB2 def geA96 : List Int := polyScale (2 ^ 96) geA2 -def gePPHwlo : List Int := homPoly PPc geWLO geD8 def gePPHws : List Int := homPoly PPc geA96 geB2 -def geQQHws : List Int := homPoly QQc geA96 geB2 def geQQHwlo : List Int := homPoly QQc geWLO geD8 -def geTN : List Int := polyScale (2 ^ 17) (polyMul (polyMul geA geB) gePPHwlo) -def geTD : List Int := polyNeg geQQHws def gePLOP : List Int := polyAdd gePPHws (polyScale (-SLOPPc) (polyPow geB2 4)) def geDLO : List Int := polyAdd (polyNeg geQQHwlo) (polyScale SLOPQc (polyPow geD8 5)) def geAZ : List Int := polyAdd (polyScale (2 ^ 100) geA) (polyNeg geB) @@ -62,30 +56,20 @@ def ltTD2b : List Int := polyScale (2 ^ 99) ltTD2 def KF : Int := 1124000727777607680000 def KF1 : Int := 25852016738884976640000 -/-- Never-overshoot margin floor for the +form certificates. -/ -def EUN : Int := 3382 /-- Not-too-low margin ceiling for the −form certificates. -/ def EUNl : Int := 3385 def EUD : Int := 10 ^ 31 -def certGeUp : List Int := - polyAdd (polyScale ((EUD + EUN) * KF1) (polyMul [0, 1] (polyPow geTD 23))) - (polyScale (-(Sc : Int) * EUD) (polyAdd (polyScale 23 (polyMul (expPolyNum geTN geTD 22) geTD)) (polyScale 2 (polyPow geTN 23)))) def certGeLo : List Int := polyAdd (polyScale (EUD * (Sc : Int)) (expPolyNum geTN2b geTD2b 22)) (polyScale (-(EUD - EUNl) * KF) (polyMul [0, 1] (polyPow geTD2b 22))) -def certLtUp : List Int := - polyAdd (polyScale (EUD + EUN) (polyMul [0, 1] (expPolyNum ltTN2b ltTD2b 22))) - (polyScale (-EUD * (Sc : Int) * KF) (polyPow ltTD2b 22)) def certLtLo : List Int := polyAdd (polyScale ((Sc : Int) * EUD * KF1) (polyPow ltTD 23)) (polyScale (-(EUD - EUNl)) (polyMul [0, 1] (polyAdd (polyScale 23 (polyMul (expPolyNum ltTN ltTD 22) ltTD)) (polyScale 2 (polyPow ltTN 23))))) def UB : Int := 2333000000000000000000000000 def certGeWS : List Int := polyAdd (polyScale UB geB2) (polyScale (-(2 ^ 96)) geA2) def certLtWS : List Int := polyAdd (polyScale UB ltB2) (polyScale (-(2 ^ 96)) ltA2) -def certGeH : List Int := polyAdd (polyScale 24 geTD) (polyScale (-2) geTN) def certLtH : List Int := polyAdd (polyScale 24 ltTD) (polyScale (-2) ltTN) -def certGeTD : List Int := polyAdd geTD [-1] def certGeTD2 : List Int := polyAdd geTD2b [-1] def certLtTD : List Int := polyAdd ltTD [-1] def certLtTD2 : List Int := polyAdd ltTD2b [-1] diff --git a/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean b/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean index 2ec63568c..174d2088d 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertGeLo.lean @@ -1,22 +1,7 @@ import LnProof.Floor.CertDefs import LnProof.Cert.FloorCertGeLoLit import Common.Foundation.Kronecker -import LnProof.Cert.FloorCertGeLoC00 -import LnProof.Cert.FloorCertGeLoC01 -import LnProof.Cert.FloorCertGeLoC02 -import LnProof.Cert.FloorCertGeLoC03 -import LnProof.Cert.FloorCertGeLoC04 -import LnProof.Cert.FloorCertGeLoC05 -import LnProof.Cert.FloorCertGeLoC06 -import LnProof.Cert.FloorCertGeLoC07 -import LnProof.Cert.FloorCertGeLoC08 -import LnProof.Cert.FloorCertGeLoC09 -import LnProof.Cert.FloorCertGeLoC10 -import LnProof.Cert.FloorCertGeLoC11 -import LnProof.Cert.FloorCertGeLoC12 -import LnProof.Cert.FloorCertGeLoC13 -import LnProof.Cert.FloorCertGeLoC14 -import LnProof.Cert.FloorCertGeLoC15 +import LnProof.Cert.FloorCertGeLoCover namespace LnFloorCert open LnYul Common.Poly @@ -80,42 +65,7 @@ theorem geLo_eval_eq : ∀ x : Int, evalPoly certGeLo x = evalPoly certGeLoLit x theorem geLo_nonnegOn : NonnegOn certGeLo 56022770974786139918731938273 79228162514264337593543950335 := by intro m h1 h2 - have hev := geLo_eval_eq m - rw [hev] - rcases Int.lt_or_le m (62244752178564837341413711044 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell00 m (by omega) (by omega) - rcases Int.lt_or_le m (63021047966864144477302463709 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell01 m (by omega) (by omega) - rcases Int.lt_or_le m (63732504204331280578284050406 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell02 m (by omega) (by omega) - rcases Int.lt_or_le m (68555078677578616072739796057 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell03 m (by omega) (by omega) - rcases Int.lt_or_le m (69188950000471302436179690222 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell04 m (by omega) (by omega) - rcases Int.lt_or_le m (69421653762451729097000721095 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell05 m (by omega) (by omega) - rcases Int.lt_or_le m (73730556485602365085160742340 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell06 m (by omega) (by omega) - rcases Int.lt_or_le m (74329863996105955191718353701 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell07 m (by omega) (by omega) - rcases Int.lt_or_le m (74464216934146832631101548902 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell08 m (by omega) (by omega) - rcases Int.lt_or_le m (74624338318165849272995850728 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell09 m (by omega) (by omega) - rcases Int.lt_or_le m (77449142725659361688692863981 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell10 m (by omega) (by omega) - rcases Int.lt_or_le m (77854395661672196008615607277 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell11 m (by omega) (by omega) - rcases Int.lt_or_le m (77938896631029212070537782373 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell12 m (by omega) (by omega) - rcases Int.lt_or_le m (77976060836007440768847374767 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell13 m (by omega) (by omega) - rcases Int.lt_or_le m (78012383942778533660629771928 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geLo_cell14 m (by omega) (by omega) - exact checkCoverK_sound _ _ _ _ _ geLo_cell15 m (by omega) h2 - -theorem geLo_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) - (h2 : m ≤ 79228162514264337593543950335) : 0 ≤ evalPoly certGeLo m := - geLo_nonnegOn m h1 h2 + rw [geLo_eval_eq m] + exact certGeLoLit_nonnegOn m h1 h2 end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean b/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean deleted file mode 100644 index 0d1938d70..000000000 --- a/formal/ln/LnProof/LnProof/Floor/CertGeUp.lean +++ /dev/null @@ -1,129 +0,0 @@ -import LnProof.Floor.CertDefs -import LnProof.Cert.FloorCertGeUpLit -import Common.Foundation.Kronecker -import LnProof.Cert.FloorCertGeUpC00 -import LnProof.Cert.FloorCertGeUpC01 -import LnProof.Cert.FloorCertGeUpC02 -import LnProof.Cert.FloorCertGeUpC03 -import LnProof.Cert.FloorCertGeUpC04 -import LnProof.Cert.FloorCertGeUpC05 -import LnProof.Cert.FloorCertGeUpC06 -import LnProof.Cert.FloorCertGeUpC07 -import LnProof.Cert.FloorCertGeUpC08 -import LnProof.Cert.FloorCertGeUpC09 -import LnProof.Cert.FloorCertGeUpC10 -import LnProof.Cert.FloorCertGeUpC11 -import LnProof.Cert.FloorCertGeUpC12 -import LnProof.Cert.FloorCertGeUpC13 -import LnProof.Cert.FloorCertGeUpC14 - -namespace LnFloorCert -open LnYul Common.Poly - -set_option maxRecDepth 100000 - -theorem geTN_eq_lit : geTN = geTNLit := by - unfold geTN gePPHwlo geWLO geD8 geB2 geA2 - decide +kernel - -theorem geTD_eq_lit : geTD = geTDLit := by - unfold geTD geQQHws geA96 geB2 geA2 - decide +kernel - -theorem geUp_eval_eq : ∀ x : Int, evalPoly certGeUp x = evalPoly certGeUpLit x := by - refine evalPoly_ext (B := kB) certGeUp certGeUpLit ?_ ?_ ?_ - · -- Bound `polyL1 certGeUp` through the ℓ1 homomorphism lemmas applied to the - -- (literal-coefficient) summands, then close by `exact` through the definitional - -- equality `certGeUp ≡ polyAdd …`. Avoiding `unfold certGeUp` here is essential: - -- the `unfold` tactic forces the kernel to reduce the degree-276 construction - -- (minutes), whereas the defeq the final `exact` performs is lazy congruence - -- bottoming out at `geTD ≡ geTDLit` / `geTN ≡ geTNLit` (milliseconds). - show polyL1 certGeUp * 2 < 2 ^ kB - have h1 := polyL1_polyAdd - (polyScale ((EUD + EUN) * KF1) (polyMul [0, 1] (polyPow geTDLit 23))) - (polyScale (-(Sc : Int) * EUD) (polyAdd (polyScale 23 (polyMul (expPolyNum geTNLit geTDLit 22) geTDLit)) (polyScale 2 (polyPow geTNLit 23)))) - have h2 := polyL1_polyScale ((EUD + EUN) * KF1) (polyMul [0, 1] (polyPow geTDLit 23)) - have h3 := polyL1_polyMul ([0, 1] : List Int) (polyPow geTDLit 23) - have h4 := polyL1_polyPow geTDLit 23 - have h5 : polyL1 ([0, 1] : List Int) * polyL1 (polyPow geTDLit 23) ≤ - polyL1 ([0, 1] : List Int) * polyL1 geTDLit ^ 23 := Nat.mul_le_mul_left _ h4 - have h6 : ((EUD + EUN) * KF1).natAbs * polyL1 (polyMul ([0, 1] : List Int) (polyPow geTDLit 23)) ≤ - ((EUD + EUN) * KF1).natAbs * (polyL1 ([0, 1] : List Int) * polyL1 geTDLit ^ 23) := - Nat.mul_le_mul_left _ (Nat.le_trans h3 h5) - have h7 := polyL1_polyScale (-(Sc : Int) * EUD) (polyAdd (polyScale 23 (polyMul (expPolyNum geTNLit geTDLit 22) geTDLit)) (polyScale 2 (polyPow geTNLit 23))) - have h8 := polyL1_polyAdd (polyScale 23 (polyMul (expPolyNum geTNLit geTDLit 22) geTDLit)) (polyScale 2 (polyPow geTNLit 23)) - have h9 := polyL1_polyScale (23 : Int) (polyMul (expPolyNum geTNLit geTDLit 22) geTDLit) - have h10 := polyL1_polyMul (expPolyNum geTNLit geTDLit 22) geTDLit - have h11 := polyL1_expPolyNum geTNLit geTDLit 22 - have h12 : polyL1 (expPolyNum geTNLit geTDLit 22) * polyL1 geTDLit ≤ - Common.Exp.expNum 22 (polyL1 geTNLit) (polyL1 geTDLit) * polyL1 geTDLit := - Nat.mul_le_mul_right _ h11 - have h13 : (23 : Int).natAbs * polyL1 (polyMul (expPolyNum geTNLit geTDLit 22) geTDLit) ≤ - (23 : Int).natAbs * (Common.Exp.expNum 22 (polyL1 geTNLit) (polyL1 geTDLit) * polyL1 geTDLit) := - Nat.mul_le_mul_left _ (Nat.le_trans h10 h12) - have h14 := polyL1_polyScale (2 : Int) (polyPow geTNLit 23) - have h15 := polyL1_polyPow geTNLit 23 - have h16 : (2 : Int).natAbs * polyL1 (polyPow geTNLit 23) ≤ - (2 : Int).natAbs * polyL1 geTNLit ^ 23 := Nat.mul_le_mul_left _ h15 - have h17 : (-(Sc : Int) * EUD).natAbs * polyL1 (polyAdd (polyScale 23 (polyMul (expPolyNum geTNLit geTDLit 22) geTDLit)) (polyScale 2 (polyPow geTNLit 23))) ≤ - (-(Sc : Int) * EUD).natAbs * ((23 : Int).natAbs * (Common.Exp.expNum 22 (polyL1 geTNLit) (polyL1 geTDLit) * polyL1 geTDLit) + (2 : Int).natAbs * polyL1 geTNLit ^ 23) := by - refine Nat.mul_le_mul_left _ ?_ - have := Nat.le_trans h9 h13 - have h14' := Nat.le_trans h14 h16 - omega - have hfin : (((EUD + EUN) * KF1).natAbs * (polyL1 ([0, 1] : List Int) * polyL1 geTDLit ^ 23) + - (-(Sc : Int) * EUD).natAbs * ((23 : Int).natAbs * (Common.Exp.expNum 22 (polyL1 geTNLit) (polyL1 geTDLit) * polyL1 geTDLit) + (2 : Int).natAbs * polyL1 geTNLit ^ 23)) * 2 < 2 ^ kB := by - decide +kernel - have hA := Nat.le_trans h2 h6 - have hB := Nat.le_trans h7 h17 - exact Nat.lt_of_le_of_lt (Nat.mul_le_mul_right 2 (Nat.le_trans h1 (Nat.add_le_add hA hB))) hfin - · show polyL1 certGeUpLit * 2 < 2 ^ kB - decide +kernel - · show evalPoly certGeUp ((2 : Int) ^ kB) = evalPoly certGeUpLit ((2 : Int) ^ kB) - rw [int_two_pow kB] - unfold certGeUp - rw [geTN_eq_lit, geTD_eq_lit] - simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, - evalPoly_polyPow, evalPoly_expPolyNum, eval01] - decide +kernel - -theorem geUp_nonnegOn : - NonnegOn certGeUp 56022770974786139918731938273 79228162514264337593543950335 := by - intro m h1 h2 - have hev := geUp_eval_eq m - rw [hev] - rcases Int.lt_or_le m (59266081817351235913474286845 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell00 m (by omega) (by omega) - rcases Int.lt_or_le m (60261195396300777138610597146 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell01 m (by omega) (by omega) - rcases Int.lt_or_le m (65565966845362846449121124691 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell02 m (by omega) (by omega) - rcases Int.lt_or_le m (66268224935948723932208112262 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell03 m (by omega) (by omega) - rcases Int.lt_or_le m (71273341474262273478494121528 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell04 m (by omega) (by omega) - rcases Int.lt_or_le m (71949306592399438020188468464 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell05 m (by omega) (by omega) - rcases Int.lt_or_le m (72253963783645493179901998777 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell06 m (by omega) (by omega) - rcases Int.lt_or_le m (75848344205939394473959398558 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell07 m (by omega) (by omega) - rcases Int.lt_or_le m (76368615273267926498199066888 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell08 m (by omega) (by omega) - rcases Int.lt_or_le m (76512522319826533298339061377 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell09 m (by omega) (by omega) - rcases Int.lt_or_le m (78595188666574508701639272524 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell10 m (by omega) (by omega) - rcases Int.lt_or_le m (78835627367648889913153387938 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell11 m (by omega) (by omega) - rcases Int.lt_or_le m (78893863486352981843045626396 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell12 m (by omega) (by omega) - rcases Int.lt_or_le m (78941888558111820679980811876 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ geUp_cell13 m (by omega) (by omega) - exact checkCoverK_sound _ _ _ _ _ geUp_cell14 m (by omega) h2 - -theorem geUp_nonneg {m : Int} (h1 : 56022770974786139918731938273 ≤ m) - (h2 : m ≤ 79228162514264337593543950335) : 0 ≤ evalPoly certGeUp m := - geUp_nonnegOn m h1 h2 - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean b/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean index 4909c6ff2..686aba37f 100644 --- a/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean +++ b/formal/ln/LnProof/LnProof/Floor/CertLtLo.lean @@ -1,22 +1,7 @@ import LnProof.Floor.CertDefs import LnProof.Cert.FloorCertLtLoLit import Common.Foundation.Kronecker -import LnProof.Cert.FloorCertLtLoC00 -import LnProof.Cert.FloorCertLtLoC01 -import LnProof.Cert.FloorCertLtLoC02 -import LnProof.Cert.FloorCertLtLoC03 -import LnProof.Cert.FloorCertLtLoC04 -import LnProof.Cert.FloorCertLtLoC05 -import LnProof.Cert.FloorCertLtLoC06 -import LnProof.Cert.FloorCertLtLoC07 -import LnProof.Cert.FloorCertLtLoC08 -import LnProof.Cert.FloorCertLtLoC09 -import LnProof.Cert.FloorCertLtLoC10 -import LnProof.Cert.FloorCertLtLoC11 -import LnProof.Cert.FloorCertLtLoC12 -import LnProof.Cert.FloorCertLtLoC13 -import LnProof.Cert.FloorCertLtLoC14 -import LnProof.Cert.FloorCertLtLoC15 +import LnProof.Cert.FloorCertLtLoCover namespace LnFloorCert open LnYul Common.Poly @@ -91,42 +76,7 @@ theorem ltLo_eval_eq : ∀ x : Int, evalPoly certLtLo x = evalPoly certLtLoLit x theorem ltLo_nonnegOn : NonnegOn certLtLo 39614081257132168796771975168 56022770974786139918731938181 := by intro m h1 h2 - have hev := ltLo_eval_eq m - rw [hev] - rcases Int.lt_or_le m (39691340757316876069324712922 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell00 m (by omega) (by omega) - rcases Int.lt_or_le m (39732444922577553617482767860 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell01 m (by omega) (by omega) - rcases Int.lt_or_le m (39756001564454929649831775393 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell02 m (by omega) (by omega) - rcases Int.lt_or_le m (39775810836879769148708517055 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell03 m (by omega) (by omega) - rcases Int.lt_or_le m (40681837264845746378138783533 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell04 m (by omega) (by omega) - rcases Int.lt_or_le m (40930227933353587876109008873 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell05 m (by omega) (by omega) - rcases Int.lt_or_le m (41011130847228556948232053376 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell06 m (by omega) (by omega) - rcases Int.lt_or_le m (41193980475986553311038374013 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell07 m (by omega) (by omega) - rcases Int.lt_or_le m (43109808225948037345826844487 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell08 m (by omega) (by omega) - rcases Int.lt_or_le m (43461196674852073537873737449 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell09 m (by omega) (by omega) - rcases Int.lt_or_le m (43629975768989603972780827922 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell10 m (by omega) (by omega) - rcases Int.lt_or_le m (46784481610765814240449867875 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell11 m (by omega) (by omega) - rcases Int.lt_or_le m (47282531113563457243010691206 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell12 m (by omega) (by omega) - rcases Int.lt_or_le m (51672663982950937922364563652 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell13 m (by omega) (by omega) - rcases Int.lt_or_le m (52579881301127525176107597773 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltLo_cell14 m (by omega) (by omega) - exact checkCoverK_sound _ _ _ _ _ ltLo_cell15 m (by omega) h2 - -theorem ltLo_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) - (h2 : m ≤ 56022770974786139918731938181) : 0 ≤ evalPoly certLtLo m := - ltLo_nonnegOn m h1 h2 + rw [ltLo_eval_eq m] + exact certLtLoLit_nonnegOn m h1 h2 end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean b/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean deleted file mode 100644 index bf04e5e23..000000000 --- a/formal/ln/LnProof/LnProof/Floor/CertLtUp.lean +++ /dev/null @@ -1,119 +0,0 @@ -import LnProof.Floor.CertDefs -import LnProof.Cert.FloorCertLtUpLit -import Common.Foundation.Kronecker -import LnProof.Cert.FloorCertLtUpC00 -import LnProof.Cert.FloorCertLtUpC01 -import LnProof.Cert.FloorCertLtUpC02 -import LnProof.Cert.FloorCertLtUpC03 -import LnProof.Cert.FloorCertLtUpC04 -import LnProof.Cert.FloorCertLtUpC05 -import LnProof.Cert.FloorCertLtUpC06 -import LnProof.Cert.FloorCertLtUpC07 -import LnProof.Cert.FloorCertLtUpC08 -import LnProof.Cert.FloorCertLtUpC09 -import LnProof.Cert.FloorCertLtUpC10 -import LnProof.Cert.FloorCertLtUpC11 -import LnProof.Cert.FloorCertLtUpC12 -import LnProof.Cert.FloorCertLtUpC13 -import LnProof.Cert.FloorCertLtUpC14 -import LnProof.Cert.FloorCertLtUpC15 -import LnProof.Cert.FloorCertLtUpC16 - -namespace LnFloorCert -open LnYul Common.Poly - -set_option maxRecDepth 100000 - -theorem ltTN2b_eq_lit : ltTN2b = ltTN2bLit := by - unfold ltTN2b ltTN2 ltTD2 ltPLOP ltDLO ltAZ ltPPHws ltQQHwlo ltA96 ltWLO ltD8 ltB2 ltA2 - decide +kernel - -theorem ltTD2b_eq_lit : ltTD2b = ltTD2bLit := by - unfold ltTD2b ltTD2 ltDLO ltQQHwlo ltWLO ltD8 ltB2 ltA2 - decide +kernel - -theorem ltUp_eval_eq : ∀ x : Int, evalPoly certLtUp x = evalPoly certLtUpLit x := by - refine evalPoly_ext (B := kB) certLtUp certLtUpLit ?_ ?_ ?_ - · -- Bound `polyL1 certLtUp` via the ℓ1 homomorphism lemmas on the literal - -- summands, closing by `exact` through the definitional equality - -- `certLtUp ≡ polyAdd …`. `unfold certLtUp` is avoided: it forces the kernel - -- to reduce the full construction (minutes); the `exact` defeq is lazy - -- congruence bottoming out at `ltTD2b ≡ ltTD2bLit` (milliseconds). - show polyL1 certLtUp * 2 < 2 ^ kB - have h1 := polyL1_polyAdd - (polyScale (EUD + EUN) (polyMul [0, 1] (expPolyNum ltTN2bLit ltTD2bLit 22))) - (polyScale (-EUD * (Sc : Int) * KF) (polyPow ltTD2bLit 22)) - have h2 := polyL1_polyScale (EUD + EUN) (polyMul [0, 1] (expPolyNum ltTN2bLit ltTD2bLit 22)) - have h3 := polyL1_polyMul ([0, 1] : List Int) (expPolyNum ltTN2bLit ltTD2bLit 22) - have h4 := polyL1_expPolyNum ltTN2bLit ltTD2bLit 22 - have h5 : polyL1 ([0, 1] : List Int) * polyL1 (expPolyNum ltTN2bLit ltTD2bLit 22) ≤ - polyL1 ([0, 1] : List Int) * Common.Exp.expNum 22 (polyL1 ltTN2bLit) (polyL1 ltTD2bLit) := - Nat.mul_le_mul_left _ h4 - have h6 : (EUD + EUN).natAbs * polyL1 (polyMul ([0, 1] : List Int) (expPolyNum ltTN2bLit ltTD2bLit 22)) ≤ - (EUD + EUN).natAbs * (polyL1 ([0, 1] : List Int) * Common.Exp.expNum 22 (polyL1 ltTN2bLit) (polyL1 ltTD2bLit)) := - Nat.mul_le_mul_left _ (Nat.le_trans h3 h5) - have h7 := polyL1_polyScale (-EUD * (Sc : Int) * KF) (polyPow ltTD2bLit 22) - have h8 := polyL1_polyPow ltTD2bLit 22 - have h9 : (-EUD * (Sc : Int) * KF).natAbs * polyL1 (polyPow ltTD2bLit 22) ≤ - (-EUD * (Sc : Int) * KF).natAbs * polyL1 ltTD2bLit ^ 22 := - Nat.mul_le_mul_left _ h8 - have hfin : ((EUD + EUN).natAbs * (polyL1 ([0, 1] : List Int) * Common.Exp.expNum 22 (polyL1 ltTN2bLit) (polyL1 ltTD2bLit)) + - (-EUD * (Sc : Int) * KF).natAbs * polyL1 ltTD2bLit ^ 22) * 2 < 2 ^ kB := by - decide +kernel - have hA := Nat.le_trans h2 h6 - have hB := Nat.le_trans h7 h9 - exact Nat.lt_of_le_of_lt (Nat.mul_le_mul_right 2 (Nat.le_trans h1 (Nat.add_le_add hA hB))) hfin - · show polyL1 certLtUpLit * 2 < 2 ^ kB - decide +kernel - · show evalPoly certLtUp ((2 : Int) ^ kB) = evalPoly certLtUpLit ((2 : Int) ^ kB) - rw [int_two_pow kB] - unfold certLtUp - rw [ltTN2b_eq_lit, ltTD2b_eq_lit] - simp only [evalPoly_polyAdd, evalPoly_polyScale, evalPoly_polyMul, - evalPoly_polyPow, evalPoly_expPolyNum, eval01] - decide +kernel - -theorem ltUp_nonnegOn : - NonnegOn certLtUp 39614081257132168796771975168 56022770974786139918731938181 := by - intro m h1 h2 - have hev := ltUp_eval_eq m - rw [hev] - rcases Int.lt_or_le m (39982094489912265292386939330 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell00 m (by omega) (by omega) - rcases Int.lt_or_le m (40149298654143480131116927797 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell01 m (by omega) (by omega) - rcases Int.lt_or_le m (40201343509165054248704163767 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell02 m (by omega) (by omega) - rcases Int.lt_or_le m (40224348129155411324248597878 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell03 m (by omega) (by omega) - rcases Int.lt_or_le m (40237671635020882839496520159 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell04 m (by omega) (by omega) - rcases Int.lt_or_le m (40258748239835768207775715658 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell05 m (by omega) (by omega) - rcases Int.lt_or_le m (41686814657515192596739173673 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell06 m (by omega) (by omega) - rcases Int.lt_or_le m (42010208390739198067655462807 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell07 m (by omega) (by omega) - rcases Int.lt_or_le m (42091380544708413934368876661 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell08 m (by omega) (by omega) - rcases Int.lt_or_le m (42146662162229712555615056322 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell09 m (by omega) (by omega) - rcases Int.lt_or_le m (44752276460150783290898176684 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell10 m (by omega) (by omega) - rcases Int.lt_or_le m (45171106034455008017766705000 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell11 m (by omega) (by omega) - rcases Int.lt_or_le m (45304867147592323391712272578 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell12 m (by omega) (by omega) - rcases Int.lt_or_le m (49088688274983454610883926975 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell13 m (by omega) (by omega) - rcases Int.lt_or_le m (49644314882674105514797500243 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell14 m (by omega) (by omega) - rcases Int.lt_or_le m (50222365124295153396878600218 + 1) with h | h - · exact checkCoverK_sound _ _ _ _ _ ltUp_cell15 m (by omega) (by omega) - exact checkCoverK_sound _ _ _ _ _ ltUp_cell16 m (by omega) h2 - -theorem ltUp_nonneg {m : Int} (h1 : 39614081257132168796771975168 ≤ m) - (h2 : m ≤ 56022770974786139918731938181) : 0 ≤ evalPoly certLtUp m := - ltUp_nonnegOn m h1 h2 - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean b/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean deleted file mode 100644 index 03a7f65ef..000000000 --- a/formal/ln/LnProof/LnProof/Floor/CertTightLit.lean +++ /dev/null @@ -1,470 +0,0 @@ -/-! -Generated tightened floor-certificate literals used by the exact ln error-bound proof. -The lists are materialized so Kronecker cell checks do not rebuild the source -polynomials during kernel reduction. --/ - -namespace LnFloorCert - - -def certGeLo3292Lit : List Int := [20591975491863213224956816409364994333176812100296626733497437064219257135271929990622395109571377128575677632549317357172281255536768879044346159880287608285158454081216816925482641413117413180239796294487459765614569877013690695141142990574793292712956737491625397243437211731131082249267515050037262100178539597902775645988605007711177646789798318287254956434357607368543524479686546566292486015792704588900765947031312859333059908689587317389094254117861522238555878928720792757698222753319636212845379260985196571929501659132382564891996885146602308869093398420779702754184492687552540100038054553486505702716623689139263134041860886769579847903664394878826342274192663150395573988681987139964481060269363359769200761600200178880921998688617243715370240541870109668834971752245217620106579293894238052031704746216146373425828269659041568949025517066739472255837472221923835772531267657810645875695237561974854108691292399487114729849496579491555080324829698837773003422887445227568424613696788662109502316032395675694130537711379793402129682483692936852544225048320199572487290421874896905016409884207232308780684222410672967107735388086543242707065475631960730711687074159785691113932480271213023815793186950339746592086877387956922540147653486203537138127512625858714936001874587998125191005726203385069721424031730580932137290522858037423666760326588358701403226247112991939540435234551158214468294141416529710846740686143105625869981405448658482603450313935247534677664520532895724035767010347125230806197580762469414460440890852655666774470446335118100760745207407503554833368786465437458100019225596382225172145692515335005940706331681034833873745290775964146820459817527285006386526274741578956308151014720408604001042675951128039270363039791288261978243319258800511585222687064872903174502877327518322540399057929739396604901321893511509090219600140088156258091931857072866256154399352197876496263717115600571527552952009893239589481964174953784860808129621707106575364718601439889878712106358994153409941197406241754503626717793842409964209687994513612637146256399608351364950492154058177180713975404641014976146785361316240624364916082125836264461865152731839225598388583308889632656130523511507822098661702611091290119405883697555022567903145346555221976528191338259210121051934339072222188187663648207356863895009936370140837459706887928668153806249422642194829621269879624094042266540990357964907044066013265460603404905098851453015905721612690096760219789865763076500367059250167736022932253746779410937021913193803469099610901956236408870591306355036156552313708455917881218975300928128898769837218097088912584759427475313450623319970722152356997884732526083858462083311761407344244332739854501252557240985397137733267492046678431540618043633409759990833023005647048225365686628996441071658908707651559019070780029487843686161036870168118608126768392022099147149160267672197956017883493604924473887616200036855402972324799099355830224588067894746498965085936510767821581288490381599789918528334940288451278591779388752942021834605145623362993278731606892856176235931770165756100507326486003753424842427311215049534383092378123061452039928531773162421386016546168114094023545307647594740676916074257498905170697267230375551967647678389978968879761489333876620428232596307998356544855132243421296128770179692158182396777449476357055005413834716481994309905446431557680652436486032555496661641111253197223851465565579454708506724358475684959134909383618503953863936397887891377957339452059551764167230711082094531136007729736461961543873982809870704230129431949590393630343587612721116514339220652904838992165174678293863471533107938440716951173944029197724382016116491428796706733761380072820791525581495604818894762720651191279683214068127521678500075595831562658848982533933399319876612514584194384267467004908644062461951179378782573399436566409026505582240607429641299795118528092698148665097751950113541401338342374680071001674230876394132967195162963931256884454702876443205402112138112280553918928598166419564690408905555151640779561161372742794170871650079354730630295052809861686219832051317434540700509875756919204767407141948108962130508849553455749453270666861766819234540020110314097743396820486417771135153580440467204098723742618541638647984855242200380108046652510798567400481416408400690185823497609585853018785693168007602539249593540701258007603823795779345368724057021804086315369706842797968720876984678869525958167487496028696306518735375746069534492105218896522035496407620221017842239379782093913377561322022783881230896780217879438278148776370548337072202322489877164121762086357680790883196140491015039362134466409896235884245532246757363233288073572289993799783553287351666870613819364327120408044486440906066054541769724969487334856539787741846836652485026758480915575414702784969212149481392166261822088937982070135392936086080251752782467889140605447754564961699398371992641265618293600318373757383019515778433225384395212707288157435192439200906680908322106066772164525476646464742002025000055752524017403252431306516488689624895202244051111089300657136250912150205074288261952658324157157950200495511183915837506242404676142159581606587952236026243905273753085408571046107921832590541153843615351878370514046221431226550097511081447387877358817498155470032331687662727949371447587190027336460905128595183377134783426777931823788286424011338537949908187347387494036027730160451654576987144764544654433149621214391490397288600353144143749261105995150652522426906477521703117361036049931004335988334697549499921160530763964518907585743690200889316232645407936822195652877789268368304773463965888902003476851684443572762685649963760100534800551455139376398856722549490308861580928525216587357152793811522611526620219186840037390695604388371975512980423290612972427741356363708326995261446935598578292440432944507966951167512680581629628594981501624342960291189969381611852390483911642131300039000712113036881046073402658298369856445295325558957617083378821163040086685158753915800789070602179152476064639666232299049526660003991534431886649274325110642185575899826001106054603282181847503254900953604434415686439703526068062711452657121913794269003351292642969010590240180484745250559318778940607209052472227461541236355696831250708207027684677376281772199577124601602876509531430325589781256883867833172406337349436959532022819507222679010492390984071536206279763759065311778490261264821979704396256566496873651345010651221525963779089565135871573001578656053047336235712790384333697319263924811602737982684093593258915588145717367293718823159221667911768994142697125410651553535059854662059595929559856758613500266382407257780528554637568466128778582955952194217749237691743788979589914379481475504749003390479319362192162064037742804408343299415987097030211531855025327740325227217845379775377855641843588854446735252181726866997552702169002653118588062073109050304439004600275611949529292197268846106063631569321555544595254876414763015112509762025978666575901240378055297796085307412792460348854428112045827538925735290792429327732052753388614469563170492846887431988213582994022132978302496579981525227651410338737651737541174637903117320651142314576857711613025672842144608032255887483286497251664573858947822522397621738174398165556250088956678722291112231575736390210270052310096580756807583200369727175191448065728983480667081865718920915956113856647603067627661943363486540224621472819136757275430787188464190672304346239641579706224051981462761669252865406376360203779178171793536398808379700763983500952428696900226505117776901070762993246326885723860715903708406166058328190890870123430975854478351026886478331280681998896838718537829979414835287634643719850979768384697258278613430157982369794977984538804623308463920146922426426952913778067660955265028117220491146107307886350049568334269382294424616091940877833741617930451694362800815643903439695412202920711712641545806326989040894977005179371720692927487865745732288693637814193450488780556518010034175634466071495331284829155614925770880156860761254309189074023285874989288153322451141084583671126875931558049592799487336201642139721651043697324102159693515386966048984904907187662362425245978876533251926376309510763801592271815905589463169524274578783055574158305521714977259757860457399983715144899831394414892702980932150991675539380756777938561862740622651159697617768597229031002876951507892872799722448083118590288503431336792274385342632341482092768742094715989415922198042969032562656825843434527681994191609967042728886401113559946445537188874853523481384003413652151268779520665416852712919057641539435022588840645465999240959982667348772303628311056662371204998963904700250254011167679656294789208841422069095196273526668358933473319444079181703667318096358401684033313782460146161259348923376479032896395278161265874943011067254457674910383160808693222131953514855021986027261791011503932249179442736927345851678806528407196627453469897426990951119119016433317052708234463648144982723386277913598989886985019963099909905413535830513646266226037763739698886661072712935966645153200595625555212056919745821966546034270153328912443849733007694470892533394268736381707471351089127511750449008807009180825404814976111119368861979960184032428540394437154615669791028490604209962408569240467614347168792387601441518008489709494712232674297114007996472211079621536407336198112733811412617329230649797324659957449284812842595632721008730093480179097862554811046374294148687732517530703963011796771369603046388902980056775851946978158491429651366916660007911337900397451020338698473735829907682950778537616483590982247222274775254891071151019835944485084524831988838820753997120549809161818750836020934800563012603970069715819001642267793848449620002675093370785495919201395072781019901525383511744121414006621321001342075221546628105788047004820136883935533113115295015449149622176986075782090167345140839404431819517813024157885310501452968852819704383835033369548947803889181969498504275548711274597363071708720826987751285904013796973025115779276628728403138639857113895710049433707693336398181339222614574850955333586631434138688894421386246514890841183110285196638942838380275768005958617337634722083848014686526167277589614855035312385598180023941241011370529339980719229482255339824466527360658323724105192308639164612367467876110884920036754786366249007243076335341797534673224731118949645786438833553686363086516834699227029461038014109970170924578156136546189788945521315987510977283725331908662030727200719180943377187324212357426732199536140485615990543761401864582695898887067813525302238794953153559842372222506018781342962900516418895931515591923544883200000000000000000000000000000000, - 769504687410430789443164102802348170556955825754287976192365649440817926528450766390472130645775905577062653270336459165731089720345175283163153371769628680564750201063435431780790635382120042083598625126000376539226022711579649481386063153817952539710905368653875788751492133305982657981328057186144518206599136362839995224914407011827343335286089130678802202052228871622295911127508916002819121200390914449992034517194380213643741999900270454032061419418198770350738875056399558980450432978000925063347361292343078609973607437654486711719405866267993587950707701400227365120518875905009018908839309330093950865546944225360709290144245749739610643624295295125096730040213037543102478913832372292307489517564765575652572269937939751714496664064526485502173864522291821511197280513940242332236378994719249214383779176715554950045009002605661682699418693620406931854000367193104630730318295297021007760795676697272365901355043079789404199750444183145065644500008141774671740021418350319954144076932086795002413008822533879693573760362031332827288833905580046968760324985651989745126353966823855209087237329516525859674000806867721751218470785115730143514180408311590353406045687084011788822496030292072905868133331197177444982721877599499943804021479775272508004912898837240030517935205082838717587913246065819384044634801112894375575192468628627370630614834659796513989023763238574615867770185895801777671971816238748418010843504168791568858691657433240142164958989747831352449599371302904928641861896330041763052974682356504475965113144332702120050169067358824296804394921479147630463564338546869906198251372060709534561334911885622896179363994435351594526495224356299483951510027731121330016039340301910780550673643192568436054830097512775215830634263517395047559240853170208814721036182773374543515502358422693226745264819595391343528522656353515155492868667035971235459848844291862699762417423493461930051911599773146797506987186280256452794575306154729878203598883024795103162790229558549303410252754298438039811475393391875485846379478285075795376484694271226108499921131615862116834766399589354081499015524763389808281499308239875198267160015691333156057057691755119651506706028340085320396090646396389069019143552314614123537642398824542032046630299299523461545536419522483899159932369238374564920212556407232685460565997194151676125061647788233295947917773688429879262118132808871214631672207966778078218770679283740837057868820983267891881062227884252976119559284836511693896678347118232698092198915665863625170328843391720626752255711215268154433219020213046267995965666488361385714004046628884857271621153869522299845269709469974375513088075473802786731567800296722729094248402272046473961434296111349854719468161413468380190735404607298393832742111997518294336734387728602511860640231809591789347956381320029536120589740387498071093846077883736735844578605426363468161032864983997387447002881245177320661646326690662925414857552116084008244227669479582955208625949718979858282461648767516963154419435898719735834235141822094990025641943561459660107606779097776804453892111292374767303746367320713618001493525900784788808519401247666427150557866349161640288472490151842037840304682556931165463769014715221019457677987510986668030401015131864430814211858155727852477620830562667137083260293296007021009134185990680774346603374397440704602601825932708971015266261373433961804409471548433487358184982722713700380584524400375609406825519959683117989972287114598672330083650862264491791872181880451060440833167215856376881208553866138274954536397674667211663871193538199945354246043831358212985894704667885594553687168359615293225504598468739830666374580345086549868056922929793804597087673234699735508850619777366801006717818485055744697446535102517528926745995449327318673228234261896450652634332231081980721613037093870668079070674353796665823373312137913233965835805602822693091564737349367070564033237391230642433081105710102968776156372950942759551082553115698712465004434472959249879724863173257316573491480910798102108734890643745389856288668548096165783669414095589167819837652257026243349511010772854250507294351850251846248529500336153859404690106330288141701385218194602310591843849172793118868081150956176522964934493438253645122001424426619940996851766054705131393896936994003591235412061914448811335346115607764359351763525094360276528452345762415224131311202622039546356442520307259608468281152879226910388464120570585145314549946583319057179294255837720045385425003348261833021208974730068651672599255229253579156560687814801080380151544216528247379919381450269157550303630872867569705651979585038733622632562539154798461861258813515981407854042196591652356728781031433867807887504995822798893352171000702980784109919937828658138318735014645052041873902537795993433742117516810243934779362532181854360160389197079828988098974012442866777223124489783029704435641894795415389310059885227498559238612064776400163957821445453134393769010685664069302011476095677850872370812639091385881152463561336645819727923072922018880368303703106799597446127283635337416972866831686030320817006910768270810715552253783964795044207063248862269852211009781021453744226258474922701131712973731676806415347472352461355397295229800573797323054475967150572704102337158186504402451080645701940138730200198883428306061992820345739318448196396418135876313789503263263767931461149525180587704536832504099516356000131512206310828383404403623447263215544946854532865678479710597891449991999886565688433990536536505244640123803311713908845057276559256458261186441871708409368767027758890877922583867452933714129272049080333278286240066167310823608675877268723550457944521288150969433933032894701304507455838489243816773947708949355425418125571800242424698018911495423960591989735376149312188199474636521682870003173925283186872148370975443769245827557848996435898981745704553648646105275406577872525650583030691736005720299435855229049668687598712882870246512579693865465791397968066785396371528227217057349855982634511656563055652744729058046545019577419309515549573912131802624373642285315019099835162623527591370755201754242826380330123619591526623071749207050423520549112993033042994219688320868514770749488633108007322831283524251308904069456269120522111690948765097104934547893106962265326661190917524098837070029064038920322103309023838164776131234448120314354407056152593979456285677982917289244651471625606408247813687471486035052155848425131690225017636223234639274384482538565233572232922389426558305621243964678341971871043656639967753233265285953397819329522606440997557190191639355268576992680370017215254044330384971979020112643963774135560609673356753889536852032182396177684668754316492386950305422753015393046322644795756912346765699631088698721703209011914554724862194481434009529442250698150672549566785203009799198307226671951346502793744170605366833328050004633648094146740681801594209160205289297733800891699210461896797452907428285205002230644600184910446961139460543455174743329590184791251412889668543350232640624793935467016921767046122035471468782498786708539329927208500951669906575075678617599494195039353086937538413273015223147468031043959303561206551034392552049519775753757256604600091319018249369482460340386051446472916993409413466223437830336289220093052808308942166570546114514233113611526844206217676573072089754999757037820140044419376646779668690191398771571409098565916763749569871555803622985931187259866018616840130779797468664370054244229726833187021189468356840620047499367052491909900438911635207176247465251868997112073177308789823213132547771027684983139507724820036899983425131538630094514509859231020359482827576969899136703251892133301904438578527195511266990595113983786119045197556922326769022650085672520016231407153463296404348689575496559635843568898632417509898655147197599926076314082034070579709940432710334240461275240489729791548719007869609423923285930756038090846037872521253420295668784700499719330338764040604187913871097792662167256515131377352920037141679530942563520604435986587982627642039555614608173054180042124266719350855805034329737791752401524076320132204706464607484876770025427833184196353707844764610455637662441786906944454912000777622725478312615291714628977825401803761560053130185921943946717160748920399935642744497508554677113243453805644834403871464274040379178485930930152619440431805878680031060464517085259545149418671709942883070599197033787860067848196887158571910766306002213533357403626216971891299396922850871082771637893369886795231708864905063865487161717519367702450379528970637306259445883066803094426182496324193616382942558021773973310329014511751867259003212984046484027551020995489474614028902071657363950284766151105114533638563046110377470238267977632173356243331584381224298728005970639238569584062677567308329142885486446241952394865659851385698440584727360906783931801427047923072652653088180203593862986724699141850539007304113158153990518802148914339377229421114385349461122390318172133248059907005828621607185615432833343297158088379577171700175581058736275072353756083707530130342947410403584346251611308999311503132079804033478436591548649303805450967433727465780239534137437049829091415683260251038577861278536743391423420484643333972938740698201476881287090468016246937839727447608726410290702375058602889883547193633823814780356431316775324895080005477416467668174577416806410397638920416996055930263970652700459494653872736981943203388691944724091450444664832402185224593643778446266608205315952024117200126336310065288107299188499863737719763059167032088405813130769427605980105625840756569119440194116263753347474427308715250506788314968437294199599031567123890015476670005775812234887418874089979847519988161781257728879751169477399970415798294353028837863192115029404446369518220410647608659665674843964199009094110753376270513249632180317837775570995426472260013196085142754817147775020427553598577238682945705210919776216735544486342790187854695144608372064757623781893698545747265084899840216176235718390636199230198358661006889018526476126860971886191401193568391485230951083720195794849725526185932752862379433783860054684285005107709362392460349177884538922542637951686621810110605397583180286319333350247984068645250987101869372307930814040003757886404503265586143649841301022876851309885019616335352344568422285583394928254580735027498844854533643061476150990550635869726189749696480497483936453816064990276249408228117468012278689832744787733988352338126733545950897760444700981534517827012576933255320785808669815735735068241142598765315093971746871868944739548415525364390849458473910122509428397193920794269744410630954058301067718805428424659919002342190265653002240000, - 13951400037700736039792423939673116586310556261750377102255851422193785569813728433743783929436481724191431854744705859980931598278388953347834325598540196431297326776190485667927091065464385339078270236812437143108910073603067402220101140179823553278588180923377549253078319424391740565308467628152056107679608111782825884151542111015917294079919918549338392920178578083457454464178478119859733503931511741903361309063085153749312022645663098011558731264761369340284385141155931042595559408521388923354006311329991007808894621887037215242140311379511497088482522280877727377777244955642235929958939329650281816437250979882942002839273987277990415267621844631184061068057498315703001226020580728351675648667071421290228624124872146482858302841500492805473162955107971807830313363004400390816133663292614657135787785156106030984953409314687686084864162764742898531209673716879965919200688345062907133639834802571400787476518857477891197124341129851862410423774789143618932751779720398807980956230174846503132396444862817358933663157707254169023999121756228020187819270928765956353724142221108100390000974066403069315075380224809993761725974453617564236121560247225774114779064779699465154731456384896503335314689798645754821232513193100706588701826127749619275219436359740056673257810462624065370489232852976960949938337787838777114661726145175141209031404472840385304924195993971436029583217587138774203085667225954321277714965305057999385773244442232086206339719339724980776340973362032920963621860179053283043028098094916625442603912235872955433900421689946797883826560549492635116209469292993620352133191118366770909956010775565510350566194852498436577381800963994966942665679485604333021926926842129988353668762606956705036610559898201077507793347803298741892277646024681823935321109026322195238593558153797788413709105901014450621247176328521605478299321471888786952220115049234580619712524318861430776445642823967061436321547024221020856849321827471583345294879393845360980964209433890991399025327686878911271735327173907205722633365171629721630449125340148776518492149786192687573495855332401978681016566400174780906305013446688398230241838814995988219253991108722180267019915563013093423719838871733518120757163949520942563610513749875464477982316352746128805768213170418112686287268709306624578949950148415556652950405552295821205179714130879766855363828613202458812903239686740270235528602276138378769183580849803499998640622733461010179871815740129718437205758379321726880709408559893104243888901938873294299847383395995242159671981702781143710880537866573769717529151642043949989558225298073540697336967150290549177405135929555789835669800664414630283118828662194051781535581775963306044849826641882568249270967127007071657630251953841750733776416050636574783564038646771682371090257763188659179192080671068111222304956187377022746681813347197664249997970310241946151303412927292423919147728143589611941480717637971471433345649987074264910226565332305865724927986751404052485971293478235168734841694721485586928192726857455650459874000303068031158568049713646354667198471760154867492537429167004295226316432531402291058803305829285424390999872677990134771640158435205582689197866348879956695230373249628088729244396059224474724324955300015222901470961847641394767983606676822258076592081111425486138834888378827381468922145230461414711733656552574987219068727782730082645603095114040078520457992052897310765033823426389253010325765552607426521173704201676686678927135803834597740293295529783286014403422033191472807246062897578275302897700459712087342127098871166634063968445065771649955414847101054236060559040016822549190986406942579702550360902210357068887661901213926117728506453202572219780476319381866239088091038024467713165317915641786045694415771858156780450080814139696193018381232211487548993665096645693654847953882467867450362064278442959606125333670425217062227996925244777399109841532686624462683419104861605825107619425824794229995942655017211538655191473081563549347502443929657891675355070071901585129728309544426722951975466401416864189554421375724359805826596387661737689872750627669526184942413801596640111522917638129576089909989604370214911686541610166891319531582737717965304858417141753434775690685332260824221087077847708538688860446369904376495599190578541063926637776222960401727662199389875529071551084620258816534303353618680192265374313780447582840666264508552804407860317306909659753951653015173881636323208703673714060674593614342652935574107317843485373636498411266257952522218421407306178417410641509398539132484167436514508670984537540121188612906835614882750391038708857989575676079847280509173659217875671176124601291592291376607274008645464213436156316134713109137467832209717329812626227528596873963219201524946061002533726503002586112791594120772334499918430700722037821125994592862191599793427422770712548032219570222201957155935568417546241400919691833194859288830786674427665150116163044709661454478414398281291892422540840105395333460744407696357414912012924004710483977787909423977467831409409670831304324865226575415986176710247502288143193897100482591099006263260776614608536252979929735232035433552183952764385224842221772720956219176254056193386500197266130079733457186371503013146504045539813145723117642977643109369718635307604974772657352321575905255437210504538034476500187667745553166205937951593564082411543483043620134926144779546662336341286342515808907982600632431985339996992207498895909977998532834661908165468689342694834180449415675712470823311458526094789651718554099361495912834948982390895097051364396315736213640306576259973364124015841565522022677694827865520873604092467751837787957717454691917193285892325758509715538462712963779513078110584597322005508983895444329309278408662545138541732724036124144086080120725230499773068996138170724172980367956497143993314017495803271977912921483595564509892603776706861179283672487516236797297128118484346780968044361878189155185133370521406245283523135596721268515957245478222511107627948437211567599750053626262794641833585611317092103889246900182037456690264920772325824125398459129826045920349824517202460207438290048514279968223327076179973471960777783807150257383595041165997528067014398360419580639044384512971434142817809343884518091397419717891319609998855706768078167664969599341567307914514309640930671062916972788524612519784684245782246113240254630811373692242462332879196621316779704075703141409347428723231400244215275145010126526642065509266703802216667138257028268494017649033197457638967823600442842540780114972071911228357921017470437257270057096423809399630624284784783628329745498745263569048531230742870114574290566977747209210875276456718757099355744444243994899392410184946668435119990497350884707536714241392703606874525455488346240954335355989967127712563299395239094186664255443882296457834114353319511197783918636441915958443833005419027343930563670835000388233213917203825432647112871177366097480746990793588728957688688343876835701723834927092697323663712089241357613491316629643763706503804218564488395229815115430057258654482705732683894798198697194757277006533357953311413149394739368325814623926020932486059090722908285127496852953971355390840716306929323173373492758735913673116914366314461209424323653396015860491233781444679232586704458509996144854691803854332889397176147590760809426335956679236219562018159031343012510875435056996399210559160770259620173935022131952990229001209840857175894313624364112350007667387436193416229737433428555706409787908004144198445072328772602023501411893878949534155830483072585535873170315003314686805543648179051876104605290491246900484678978025503960838498278214573985715328384422475058273563862663699857294616560605750012193380517080559274717766197788537852073023702408037890331037351161963613658527583824193734019484888801235930279071912602265206201378889418707682489114255761201523711711604588358540684584517819324702213081683546606456280648811850320369047912871318908322657353288577366478961947033688763672075220305266124474401587597970227942591281418061572137865186791470610115905480087802404402262372167270661371042471450909413767004211183236478813360518719115689401384277213132902741737531334286046476365694586063295954571108308582333994506306080297995664811385696557714483994791409600279366877662679823578703850097034963023160083931125640020516244368764048998792705894810344352913413021025782301750548172081705716398533665722890005838846416282485001887497649110022568973100331480596435819416080561685210708258026579256443635713974929451389720448662295819689010804890731697941568274966670905085572269426430880502709340181454311822723043171621831929815183131079204050943761988352427631377915955238061189463920125998300514024688352328170960704532799000261328191992840519507673576466058229351522171573433034127026513258970054356810178557449487999845667739545387070832137150300657829184035161433389309793097837501943012104188494181346359011856094798713296076791573387933170223363282808953420514982080703307641112177919661326442341647474023053971099343140836095735068804358552702485616128341049257298311085691079001538493537895110832688253203022052057998497118470563739411093208526256100984087949264873061169255928099436718781110876082326087708486002463269842437482152189186828348392566304092297113691205517210090645163900941566754953580524295150066383019383461116607652194427969275475793933525906143094613148687683560422601601935071525899299125663086774516919344236966059902391414569679953184267317526878008552960544023375338955777307834262477086730118473730852764189980616833246280170837457197505121243887899700287958039481016042839801494923585213452275453270510472367604978566754280476654252173057596259222811150050431766431104958481287300345298418455586946242678686912446131590335130287537569962667555570218761780170023023429840541685340478553340833118355214304216249386549077670778258164309141268121326023436070751732973017825143859777039570253709189120953286503879108661198934990731946126917983868502326861297426704315899773374428954890198852703922767048187329685940304689595402204429545863599291025102154855643977154075595355510821728570770096858913713262686346448095375420516576760126453862166511252104127836990433388917289576030778963155804657539387121746001732498325559165022162429566287172568780903055992042025767432191628562143883611228795946777448793536609309487907162940445036013176375070144421534948970518161589079059238913649147624110294087817819396463723186159480055576474771363663200444656463973206920175788200229093989679391624651081502246853203792226883838732680128558025180542256107309050644685221230580486188965683851805169398134331420570298613760000, - 163493344888400660214787841766286825388217986041783700267013605060116534873188687974960884944336969428160586336545124779458251823888593948176744333839033873609482661949666005051638155679583698395821611646234488517888099132441055909488499771820119139950309930509230374042477400219916273747915485916759077127465943672058170136935857414733592551690600733637912994596063598693454938749365906445392483618597994967985853805136912938720013320162788293599619467040611162637385441039413426732632622356022589562715990997770348996884502839774982658332820356117591871446614700845255275351325942178137418878077304598646731839295895220184322387680005866421767740940725867502770599132952009331391527578413011671954478455364828837976022430696051676634622190819128884772645824803060354402257050944043273360108815493615209925829345757401273055721490074099195820806820358419108451827958924580374361628979303732468788790195298271822735276094044598397944601921786153624804481211026781010790734804665813713668384772506941077756026788304116847706370203897757877361402672577293268821575615802456962271222427443892354061369426788818605385383573075146308660916534035795483825737744100364552071592577289960805343248196186479229103009531892382748747239626016612402139668432832913181037779071620052351893477248156718212314946958465746881518919624360451413366000926043204877850878628156258243205347031499067984902758921461642630778852997846254197543427016700434951145193376495942027778554823105647235941628421380887963019033723473634510453735415640087120428585188380046953064564505637732770090249806847714778365376576470543402509499634807646585266223699854381230490939284572502968635665806823329170460747180412024319866850900150274137922062555729766809301649256831369648472845319684261612136519817007533116497250011471525583750674181012167036634993578328332005587648344899874694032365705226588406908910979896149121359246503219832042713830808647669289319314657175513734325042041551704547600581121982483663244151993055014581997406930107808667151293463714203079196501611445431114424800839836445257537636651235519984322555607775131275615609002010309814189076258297928281699673426179402355937345314889559563503414800968198586060798335429975141428566717395354252809321677070339195350285541856548187646804492598909539127680678513374295318299027649730038610624192782583289796836682185826977126704091270782926987011944311330874640865057459164627678399241655667349192591860532718180988392862785254267925483378871600740903000879139878568544307216278783168229955421702135969893816070486371786023037067201686598172782027310271531469555437644612200033609197069332539795428990707570958649155532185040634484646221124067263167940476110254705208776782897843650607469974460636332929429861422410398491552698532636838320846838851150645305467807939616041152862092581437624562165579078351474243970660355086513100239209994344507848945160119326743310013157248612272744642306253757403463703355714006878764702056491665992168978045435068459830791019667336550965453164787092978007807688774406575496243698058785820957369033265805014514082754393490000316225395655485000363152643183564783698538760039114446604749058581252824303019115926260182355697323995346830978225262668138531898369901855071358411619920858025437787566147223831303861498671000826262381857102503403281536370698421179199449585916883169553573456272047323353218714754466889919027983333942037595398501509894807398056415416159640206205320470833305030881974957337923831089552445446536827654419055339811302241878491082605741875803904734720519275835318239705336496816465888574394920608742560776689519280860012517050269568115119880122915279376699892596337397538188088966788914642952841199631407940466102057477182046720689647604402284571405958250473307403734178217448018958602508372865607276534310493170889105698627946417416909337649855910477534225132312416730269964257198225073906759121463479956740146622324673371706136863900283618118028242077227755619144275904443077706628537493881925200911951476561797082734903185240169111960301866190333758897071180347333824591277438865670045271709946391399394565453021534338867075770623129326274640271910257734370231293580677163478448518612633601218921311921893576668336983661936903815481159665612319679650806425425884292093687147497580727827392772079290013517459256838699303531546676272621715501324936467644573844025133973749878287136423272890424813339414662555933624397112427689798812730617088258504606780885413630429063244381837786145326742749665940970335445861061552300431138767787733912313151641055810940934629760575501921852766154642704873435411154368923470488729071854794971314168902899481784482403707010626326116292292988181596351482895864237073176920126124924343767553562838808773032820965266850819860898022302585812717065591369712208557188219730973366951491710523175713726996628682310717187949038273730527874468671848246483099214951038602554492292434613951319440886634845050877176866669823471642464137494883647079745684172965082741217715142975259771616148437761146473957159230679463044041422618805634730831360315065423824239057851502232229576497904453814704970478053508617681368720840588241185176692896078796276603453600339955993684154082180164335988831550419957405798315142636637499182450175054421911534261963537850858141186283505954293222055652004185839638118737477014828772019518806201827051801563811132493687901621600526506796751748453931173186320780600122172332033884374579564469901277997785906228905535914344139528622785367798107440998469270631025448032197639741353453415464221852451620665031339322195864190800671279336411907570614472199351426783216756318264455228641572011906063326207401618818495787377326817798103492156063548822046587555933595723933895567044076380898302455640822814984540073610117382660604805621922435570043961954619704703921597415799384181451058433032298021668367697703414261640991830073861471310500750843364345385790881012345208409187857193272060543361827834495349974373512159426891732864852413128487179535100553437514782308100024270468245263511718021830107650257371265599930006604793899043492249459138857318951977127559344448530616070359096093525640522173816340626766589745461564784860270358897675018331578741017864759590177341436054522939543187086080400332293529703387940828947040225021913069984706398989495462405974022049793280028751485744831148229079721597735330582741102613243164179682652245359275253608470594570906620025188530426115937452569931633141317461083428341581164772067563573749538662320182517399276725708474489974154131487071443218353686750033872885588038779533077595875920273363533126773984881405548292804688441939549907419337747823754996216308367789448576084757255081321698506038224778428329015378719354087102533678562023465590964498986044094093000209962209250570298351400196240031762916578269653581418122579260634701510436689681874301303643656704368422813857289285813326723955832134660219757092623194022263839550582387238659145765523658065285473131496978525628407211922614161263487496106154546902287322948704975486622398113330019786628556050227101112413693994422203966641638043502796115137448454018484801750994365233153419059427742064641146282495535114371048107154878259582154585807251401424146375066157941713317842321290761744133082804875931686776413375854161324266853463459026316815796681814969157398979108222921485417911400459922969457581566411515708363905536643427842243759748708316185010667242334552270953918229412896127876094846352609149013001376288130180277820398535954653873781712340084137313111983071646849983898931416336227993009666132082465326630048476742251376785762167559482355512253417953823912614145254969702578921869442947256874554008452710150354482178082990807361260647193935486869261993031482455885709656872542770159081235516398744352896668878062284172298779091467307038700225180207915667577198913441977940858742935659699551531105776719682676691625258944918753827313449354350348847636343677085361753722905424918953007222898980226882634086124459840748012750668085422198451089164176633980624627752674804479673274601419124671421077073888001936991945316630914232990688724542952385431063922382452684940075586362633805658075205027120673354380809230853606838039308910126505139301337616969928920451385357597526276772248498840007057944051346936204811222936789201453226653172322678271626200840900945379577049142163665310870196560924321535790033728333818665967296937015781880421153883975133902587945775172893908834494911491805625261396895428758669224892575405987669619145355096169658278066314829068745449036786829424027921242728785445310896529017119801423883846832959841402071288937341441576974792781912663094768275977892948938602118362074940658313060872774353882075503172838114804909045942067680386850661694460998499919970410385565742893671721998928981270623528184426400691973537077436656950947892988039902688654541474270499851302227075314534157991450977219425307132580318930707675397000554969488820485267014797936927371439128306151643500320244375459312925518119596616038460475974819820712472428972263316729710046846486084811920592079533067949550852927259873172077979208827213608765659193475441572948025734556776262565627455414350587642084800076207721299552676020024622154555987331807126854805750426027848722624382410667244582595712735157664066211227101063925010889780340062792462464469174460149600895006809914609082931536648395624125447549384636274874461602367549211553944634262097065225888214757346536060963356780758046853497541131587507271710958088219219343682737967826298629780421035942660412190228413334209769731756518375116639306403096062429515687044125633411318342565386544432977662551874105299990521757667186305702892524954053758729764627938454903122219647826312696351569600604296204475881437456168214726868815863847937396074458460341014682207190562933299064043126314106217995983530781574095180579323072052088184656108436490692469467153725469446604477812853320519682417318725749070313709145827162862235813664520545236230890362486377622911822148972161998859985451339935133707823107762814729894690348212900049793380823283235183247344329603368237087944542361466238092698807915817371400935645264199306723522232233353017934551331312348083319150472486319081486965719852526796287120447996361256561636775218293101078948677244528776771309525302548594735260691295846311374416510136701348433390641817262096931238448807785991945122938937988476987801325986142759096426265939437738763068436704516045986371683197791805826200589164609367569345362834782518773826088871737360314556008183067526725058712559965483129631846215623245587363855818631491033032156114790506836372774547115757715548464264062735645978093914565357685164436817628495082790460755804160000, - 1392170584150084680857352044805202879240909405753946469944814121851249895345818175653001741816814835295274656861651903022366308037592741062232428215631676455227180033485095532026806940641205903337392913675816858153535228547796506645067810753337647060977704069100443537170302112919055210899432307871329262851372780870861913439324240989164411437157066938079937176840424576153066004513787368247574721107675149851641231989552011564961484557623208303952962088131862033203530238493067919111799310875728943437866370247441586425744979520110180338526526234242329239535891173646886199614440619134469761465187782602662820524890229049770959560133539725267581739319192924899119648775059812977045236980853439984252380059670793498723501778891525011209021353020255067639974477814248757453937584547507975268741268001394022086293799208674258759380372882874019847295537928238384520512473729447438232302001113148477181847097750460830367491001521817287417631865676364975036698867745846005412858814721237675823599324362015985601307442644389223718035471227756061451740413593887859402049448630097444962515955984757361553496187341296159955385462486038405210025601140973410016573254857185649732748307979844263941153735581103119357935246733404460493050731897575588322953051120661768691239516577451058277807743730702456565187005186309157387760730659573427374181902052649678002142268622539336043326547443960928558160729491957273667434550642898740061151688947374032996137693969051488971996888518455394203122978672240917298288273769932286845144084624680526301330404919177432142663319420014709618194493471048924334017520278114400596060258633447910349192959363927302933893091625312385996228943222342974669343302380617856695858285615491466806616526278819907691390462304811562224379700327824337476801708811971916279740901988221880329667277282610340932723379767624507637097722122948112762878994738512509870903271445585629505014717519760467480642255964221345653150462799885385144822564455110501454906885089819276408565621018357475123999447547624955700016984333133852328860560477932120449914412033972847337178397422468048611344227950715871796925965085383961068529288990388585778989323936620737070904086185801221159480728016344871707195549924867485874643518750554137310928355908183480629412054781134599678546480825335109271061240482341926672264380016706473316014804195383095186713025191816617929939284452783671339693380134563378447667798464741696892777710130596268947469120510696157298073337530822121724710452089969940713929428200022027379450891842351268887553417674240334045982008239458720944706335263470340287379536325867702648976994670450811175139234514249461623631689681699135166106178520560164522132191368637538200647728280163885445124363212945039330974294174317548233277573736785949697249689214181316315762781869401219366446440550489903933253495786869349849468898308821471579112383016195481520460355464629543309445817743979026014231293436751303454273187674799567880754469176178719537429114875233239081369523503113454386312865735820760619467301577850281608803237623657300958718194569853395332559585891268350845408699410378284334008049380801414058194018005313775056036637136461811264350293921494648717115194575543302111405355674635301708326250146768405313924603159969325829192235437636024865684861688939963060545774664829556697741385655682116867966909125587809274105078863516483990497463748999793647310437451733631360869997497017132996809356975347491667691450218370270471795762886371713874164209016767712851072398085459460236320964631471340796020837769121367906457234859471597319087110552616420157750744082164765166192490906836121203068244031860859085758565463793461656754222389923340218270421443503542961798472346611905125919980001904820755347772312963969234492303360166954914600953589127351894057721661370735125974397865148944940790036306605721225683695488496099609358846763732139676540844847340915698468512701326572654805723408301626390000395369235972566760766792146671159408193487949409899019037273313858693648598559319101912091072771433117142562327714252237884095093535806291322667151742584547542724818163439203114492260876240232744654160585365560140120292036586562191631817089033325182845395054722419870017884951621489808330339149487743229631034181428363127787655672350218166318568298840867716815499393548723937120811025924380466735138680587906965072442763811736337850086875039788178984596060800121627509732285587159672348710498814375846978900401895939965889600920433531990479255655566227217446377874055350486849834248863884162355261497702430806266577651842402485137536857216574329589404231886949181002376379356532166435301011958899469671459517847906213273899382586247754292402315816762776639113677827332590897120917446943480845892620067286299137145718046935535632955422993273928480604853072710687810160578178525514126705458840141949987110388116650113882741505525993918482335590966400903309999457502283725528621622218400912430609179571115263203426638735198036519300907968862614106322766781244305572708182114086640580224866685429022593870255266912181190973366181689594439724307636960990421299570096919442079783785781866840409683769238730170108647356120744211320830714956362795997005865416138449504328544614482341799156829173701746595625278351122728468660617921665837976766237247322780359789669447806858660712190411560688817447968362284040548231278996266863838213122388696603548155543204475260479880484986149387895805076528252752873359802199854119163856356112972741832591773778355963569148318014940266670320221008192859286362433877048912533258181828294981939125045178366018763051382043397096942665723016949376638138328142914672982562405270520940186611574242428865354978444342405433649518281314170326533581286326668663082329438609632933126289100577653898273175850494515226767603531674513975362924800192377612142349109349003389277361198327934744778037077528437009339650188082771950539024227306135345509198960548039162261150400830297425649279155617096669825053211753441418300863918009615084257519102384564669366016645014427870452659243987181024779674474871567122958103964177862652027904297524322732555213595284854542470162866586906695610871669444810493356533539937671640673384640868169688736562053991001133146868804614513835435912938007927948909362226025324523842087270993649753163802233477527573309486300653555371836273018818249346750485983773032159509413068360955325213036105116281762964160053851921538883263506279860873537986596098142053549459260020546881008187560972763381300310564264401206063555550983889434927626017794491978385474491331645993832836821985092532721504544096337220865257022956940346869068548549304092453944945273793082621030693251016014213298660865119284841291010420411653787353900287954675509968574536737504671891681085566469800385634787070961071553031700984207208870578094655758164315120996920733703208665685388890251063515218352669790249691709652841252183270677977625648635762629778629249666447429937511457264151797683244070049973071574020292836915349597749335292643490479797943157881940445370002876190540218683930149399021884954519223898056581185682757275148232776028148356424902052928413646211600145605533812293341636648916796415999454758412508455556027744030537025746060000039851521108560246259270919860487785916464685665417941232062574157666932792190706908389232484463629621519049457680685081031078365675622002091454540826668674120353148817386121194152842678156321529794655573800453036424756768843682782376183428477379600618740786515335585259231269898494036387627709831947244776830181314477215204057167835919532586853883257716336795708561692179012932945405291960994997946928555481817895907216366347685103528457209536667068112305032642780633838001044605349076159263134274339462498347613044255153580641008672636629841675537721437192669722194223032598452502153494091409124785630062568608119173722812970045401776268833846990915527894815029615779044203896746223955717077937697732553477056398761825586338238389375818231413386768951311119140690534209411749491829133175744529018527449290763164525976073228096721851744021053478632538425031956498031773636475695724052236737951370276690837772722580121682427851607919020643689518465288639480590332937072417647250218798348580744446960677313829863958209785101128096494192943685996856578877893025669336803022287814674417237615176761707780188817549493988823899646774259541480547544004824911699264045584683374197671384503138797289144350310465898443540027246301261681196729275128097871036212350595089154836844494975101854797209532057846954126889167394501713472860503274836773932002928092735432364424185745174103500480587013453429075012527289853213426890834371383435710375703320584709114981538647755423836844380747216600496208906141765171977153455176265849034471759515794525343477508991188524422813416561485044860612088976240629317210281917191232847108128307981166777186058312710360176780513934553647340669174173488161173917643464651562892304383692639752761241226723325508027127435377754506320053897647103938623028922810206933892818060953902958403655007255737711489037408410571029435402199973525556499512840444095105499401104690017633543990651924624040502223826137517451658023882027334740202450419051873256103665690868255102239071253130210023543308228337383009103043639620831097419024975635009006006327670665321460478913495679810711105265527421244213405594197327538182570227037150969933852425655916740966261048733618818479160546546120347683503488110738593908799666034680563826825254437566526560946794259867194695716414885546747935250500310722344386147283299992268068510278270424093747998672397733322024143935281706365405391918891807124821591843008549743349452927919914477764916079527419627756153783735529204030987205645575865390607642671596761146836543519704443646009364876844382477009485118772484372519641879006694464923384401536589244247968402784325307007458260315834268222543286690557759169055162927580010870429735487546371734529286685537707715550404092736520913189600807080514711224860195067005140389327945409296684619876959902411842059934425261112965640634441201298625631233412298486160650678658010089384492620930982124880228899657271813119563785743229851734661443736534513080515343432759927445502815362926588858873322505293294335036323314915055429302135155526215183149792470406564302170745484309376226340033847657399499805749168701529911697909252292390965975529921441014479333532175186987872935513737761337130027853601594198078492895146490748874032173907955012957821942995997832452922701410553413525936928238951744340618960640069183856049090987802675037254744670675661713603497544185457145935059497681427845968443072687978680114453923598674006750215274977215688563985326904248348180480000, - 9181867725646960777349840978728986932694558136492736408553466066675891498865336831271669912863887744736315292351746124529619676849499813243166759960217057323383622384474206106954937753711070877317657021035518685036824392739107405852818483503290430993885144511883609009765195861912783310724154538394110957398426958512247681593099851895507788961680046899935074799800277935963711348026107325527240947134046676349706077365768620330784655781861115048634479127914921388473990882952918124604165659767737254250675281643371293020658435331374916791008034527117430204759475354667629535562401673313008774952709244172273336010466901534676120513303275004724876128693898814680232629765110522203179553195211426909475891071581127869040326006939115503485468716853574431519430707906509327725066524002440753346244767332353606233250396568769309019380880816674567718706597253045099852963647495626036033272745235554335280340693216571260280699949044995527796455598288247583481248324346295667853312950692521039869154506746860367184637093024513755621013830839612513941809283505987313184533372410225482815115547931345460940653902777720459202935766704338213036025181784771482447074812139765707923983649868784340835520085429223026041453053879316899471608606735409877846493122650082417400347828521994443321948690551399463540743155704032480109527358668561932107853725263799796005465534909579795750745763617007604367228496975084508682648286554948039263366213459310290214938958455316901156800274460579056945605079821517252000239876310040980762118371826102668307191975564395836315416568939223477004864141830992008885029175043968672524170258953584891149851903530364362120882426774863967928513335323307867563959887365670633758469448454722810596035458095233318437340605409544914291887454470907541880687160204413046141667077554746366506802851520117987028693272246356304343443285581999102953592670952554353929352754115723150777834404089071872780172528924030367892065181649022868573710802124888234042182972512308861934099218548267154659315630950968665808972508241404987883578654998286767724182595526550411804452302915285665568928401090816993191288408749102957828824513459676298650533459561843526939671261983210755225632679639273476454336161331854920115494281699528563447437401129251571048091836312309889679476575317988897478130522582571921326991092993845245427206381937451287764195641121884392354394647646406835876313876891043793951442386525071934236667607181218174549922422360238696300713080144971303221470000190608181374045351101286211321727408854877196572025577871024094203556724482036862405667357376851565792508839913974902352995105610620671053821681251506728685415852515690507401717115677806313684432274787666582215880923305785185949153570052788415059373852486297274925078920949791164090494839451545947701904411317905002046280357527097388975524351264578026271304283141988931477503214011970076724207728407569910161472062535330582037216309756310319798048677189573509096073790195866438123915598141152239233251037881496736635069121974738095017499899797589048441676980992363083940609758367406286152612149514452700362108237252424040911631331821154779757388066979300551567130300325901122020991517847096507748738450145095829879193000726698332041199121566859596178479671165459331391000304802993401327502359683115574961446635060469092875057636131834875721596521072499998813057491446805793681386000919226061420101393138083942474198254047057995175752619608298129293381260292107562083664703200505311443733023721766594679929853464656944189914057324728897900020813832138277496530442651084471951970714219090840676590409526704271004743678259406909508670859599394147750219565490617310738808093817693555570673539373868743802599586265727001500857918005367832656639149378388352946593318056055797340811936610353334315718295478522309893573223092829850612503829574784569636644095680770808586327921878358677225832808965907042919528729018531949151662502220555277936577764364349449505249461902464661531992531410113424152919214669065423704272960057195377611899141881225110226912105090817481837370097685672265986959241800597545386990132177488815345157942911717225783368508372976185394279720592264055990600190168548425762661193344417384837154016580601431775607639882247237500752867488834134989533905235659619754595739882728115238133057823766704216383306631747412199800863794300548893566549811882765893176299596405099446166096293156156296580328479915497706101829878857589080525568424107380914270250885421200857501993511339610773278061003223242038746829902251079331936341210483555939192785024827232276496814866672532413774209113740501555627941748672682163096302479166280857620112533436811250912777655145761384155540978387582146414640514981743139319000762428216827619170385467105280302443482121159409148832165707993917957077448551806549783759470578422271087418139913519633808593519611479351850579658395020941141872879674028996733746399160722208709615255341187765762919293842254110772245100324063195451297897055272621828781323323949448822800569007919625272830377572093384579413963880886495137834033202614005086746422386113961842708762301316464179478075183110229373623958233907720057424475636562535782233230463148178263533494890508641740800152178446392778904305765707033468868048999562608923131933601659437123819833067190646798026977940627255199681951822970733116032810699088957200297017053634054822716949621599549403286746942621131428603759740252540956576315486424728285766734917315688327172229462776723789684794124827628992896031996504308208103118648483357762561950915444454672459223113499066482386326883424417193215848020043598544467230035986988618957336150488540531259694503407282976675062794928033024686711293452948774391437077669879243826650702541825707999997893139696988549031553800429590969164299067461416881870640022315622995903302497187234919528788587311986520884844555266857031058431898163205404268570126635688783282117474529580109377513856647249480750320257121591855025043214333749433566420980237242096156522797671711090484606562057248125730034584270855542846240849983912072485372450592532283986992741437221960676500799352970816839130317054927763609184095750357972242248403950197534097886820442662344040603030616824677678365588641206015077252287703225392547484076382539273442686297078084003690872337145101578459642755102923266126376111103887519410087558440196527045640102942995701478834153699415372176381715845597015370875254381366012370237555592221145238009927572474521853268669812870165900692959542477335348203280459380204401733031648337411558811191070776883944607982239562293518253135552415962654640367738734035064660129035358289001892294608482532404485409888997971912763891700080329176478418494255207054500741388408951777919704712917132263326786768642653581507835127753720395496028202412202313256727415376282284776921763627405341614674553362497315041125931539193332727820465751353846114056627139546507959822158637203959187543329109992361527451159890721805783166856488893441269370452585101010196996300156288824414806114702771322608242499833639290614838388515546901111977192970527402891595492509005650045359730724312781996919974308061893172586464955899651955494878150272363195153677479366070976702425502492751644656323288888260009969369889132430231821979902933291683230962125014030306061309169629313076439128293436531686765661696603316234276550146437020482416448203029961909437916886709530696325729188945517473852310192867994283551753150483312011446257289072456573998406288964438722579822824340342810780540731358859832758032698146799985804313519341900920642359152637555928866623118663906424972955053665368568433380796284740629190031096060544205691021333192406856666671626551903345252052680411677360793642209536118725308362521413543191061772322034558752851279744894464855807514838772610481556132413643611187761671366846158174957177980883443255067191229116712951969146969481680638804949843555272311253859243314393033757971404793677395422751414807682863246525285450676883470891602184358108394497911280038679767340218798081393747722339757035774317854638243041116902699971483659705676047842596164225622524184267125902239757504875278134130771339303654045702628729583260231148056427932224417036927389741424450289292304105814295320803919872535766379706467276281673433699837888397450323673610312025136805207841671232006752284751825354270378037947809956069743797154452828187611882325033180173364088378733360396303099337726135949758845263516479051529491773806070904287255384044164920383264524329594346632961861065053094225100502656904580315863663610139332229211108939484270397577408163329225229875695018045927616577859762871754867630109141842030167782190118577756597261337027668579353372330771915286694996477967972553613104175450071956516219919628766295005090973790133179280068301159605028600709121463207692606969712423579412474994957032448431891928472065343593540421060729589754269027051432801989859671550764816774236542550387578465556415760159632058700595529139298049785074550223123443092324418173292142295841792269308707946204661014037723482458207303597779063257343183512987724439727086990981939515094142277011657717064876601626948467170953129910083430703996134339825179622125380947810451034437939224359893311751472191287741431979002114485348032377659944739895033904869103029509649283583762807077477299612550363450531892699691603270617597633966625658903870472101643578327598461719859908198861145845133330255744423289284356774623138429747760368844548030375552594887894128256000345937047538179282245264749348495086302874440947905589386875516147600279315059749843116320812206908086872963863680105754880383073386994231313360415725514891994561285467739326652168076505525671430811080597285978385085994611399706884161529064505571257639816632821573012371944720687370447257728144271771504567056724957709894229724458882030977402492733804833966477048624217739558272469187481753519714576252394762565257055773020659537732240126282270782041994391251206182727341141256648265095486381959425896770299926688070479073068411809573499831651424486133479971582838262722973420897129184447545194418138842936470503421323417408397616737898675308930682026867343381359913886171132108219281267862124788922381953749243757464687400454983232849797015729220876305564839934393558696427080576820230891666878967051869185854578664895953813540576161283029825051901228241964983995512441652365475219591769270510859645651519265457294660833309412500324618889655738868995057589565671552543902660459611777411335087258644584795182913884675869944114865896588928069105693403297181658758656276486434499602353490542523429607905150758787162426107963879219036526879532787819203771666471187563288765399040000, - 48828152958036879639031355362021819371911052587487881417380876848840863941321120910753792870915762151410533361663617234692939149908780175370789018057560529516456830007517198339449393499616819865917492238294395582017075601838946216562990163473442247982969924592090414826507323840659799533898065018982627371005540354164924915540688809478592990782847160895234797663148522536979196573080297435832489641205257183883589322971006562599333434781853632603481960814617274300251687363090953737073623352193683534753056121838366834851781140216528468636563577739999387924330835948491761622538727856633591073881126497738180140810390302532237138642015316817031202748786445651244535918013794396068002966986973648197574500971815796014226809796727613316149433385919169347345231942021745621240772086394654052861950533609264682695029207541927063041680392602397600345562288412889093293963435312898418230620009733819157993402916169210421755601443053230301275854911184014014660914621007477147021252862331099548102801841163863055272423527781835651128888036106727709299677752261164529046295280910084457142963437281857041224357374932687110527337344536445940135674336761525131790756865127146470008938148084770699500261953919995337135427414032900948929867074980705634055756332396030109067556754705894345163396926176304861365394291845774967054639064568201091214113158211910126920944167948887995410970112106774469954823436845526788665865714808706367907696991375257158934841401459422959886925821859361263338359047471680099740835162268714103933823824811648590591010779432839856084812092771311281013639009709079902408052927451657204270855805929994827746095488768363976942793259824881362040817460298031058346003680361532649716287443658867232975276586111588055467732139107576130435326513857583082068714751290232244432805347285420762218770840910260184209734950649014226849620992152167035302324213334339251150383181911417349817328087592865489155670049193583794909901468627335982873616297969090402491771967440619790896268786499910641255123874553184173851829861067743900529230973607711258072155950178134892821793220985573773794732968188797187913462176854422120713042287599823554417260411960514380056389701497718467343479448784215724727916233211211133183864282764322079557289561886048532987241305338384884020736231200662088533505524425344294384963937243038687740745438501513140549745247981528577442606141361688956374590397665047208694640296262562751178571671310421289236419808559931408160493511681503890805070550526932151054883629542920307243902174671376128272743944614017277888859672042524136632669824611774525647411232613847163934449151992529148955078014174513942218973636562260476498059474283074322269067330673032593094750023316810026748337604072985269471761179543401525442549472296978202080885386020150095149502457427451540288319070694107099460934890359830502243317836102107763849338949882544631171693578308592155131303041688867697998043800372434116490386140524613322034864361973523298627844186872149253518528732685103266423685764162247280738351942403422244894447862974012553760280713758101250079563094598546095594357905533347533016059700200869155477660747515316667105993338355181627576771535935260533099113869131776222680640198435666017529583774401111080287180809492426759180868617597275858204983539442713777628395166751582556922924093794372835224657418356825359955033502058571785791041460032208966157003948029146346412356043068877891000770276065249630409375911497924569569967776701823469082670051156152181634851060661088634368137508888969790646040464325459239784917419606205558189732822730575224376259447941215089107619455780738505932066174113536390038758008329872528828448081942607989046253844939554104964929683594362430690657800809865004590318339090877134845634251145286522184704558365578643939120357556726146852363793924888202417218849527549935721568755799845204751865634491613896062981916742889722571178019036811645318902348932630652164530157515104726950835270960920897234563750949611001322728744671131708322915962931943553183482761209796172279507787623644854856107544365635456134003990244364022051859270515069854872549560802287146038391881914445137016713984164653685367095122993225945478347892815873470028563775829989259365257086629587745403536871321285484915617676192767224099696503260885531936584311647075567003314105946360722205217047766508574677869592704377006174054453486010010741081539647507558351260782550089186833466220041178450353694844260498219991312168300366005280943241985245007573469271997417543314607438939591914067097251854189323306767903956514708272806103019394792768745467954810002109281753869682882426943461816682893952967724373401539893578572046186678608543832502291221624661864855299727077664607387247743558285011460257471022891929909518301622533424700043478429586139994738827926328381620293617469219101827400364642577348416377172878873554885510857484070914925304829706654875144520397215789201044307890841421933822049905443140678276909044464597208344287224068860066910152109574836954470738715555437512238999118955330633324349856161167247747971769143897346836278425090280860303659872959019457622588741706181608676780842407084914682515420782918152132411485228292321219396617804133660996599195059790766710608840732169678348159697132040290415266821809163584422649954816880322417134931833451917018033343743045205184124748211418727284103759838859084342204905876538477258096013619242339021836628236411637675619177172600459730867526155690908177929061334664556406703377372639954783017642490033821280962788358263222402849285410117386801233022668410850827176724736053494329311192471447662445571791787686906991821822366717138280400201932665916155383711715644632938470441962303570742094937392318208740236418097744601572835017224986540371584302305819007685886431653599641953559095657500349088042029119401344380087645332644543113276707415522439787710854642032360490042517460503404391520025758994386721728760665407447914568736404546679809575314394658593950536953445082986496600746856615571127925273295589365518667645516277569460097564982823312436804777253675132999532859995027931079816222313875422085822043635380555161157025841248888822526043641396030833320216858190262891782790601379030318714990481184697180532057564452965339040558627727687604073571427017304006773327248759779455362248354809509334173787667311195482974506997943801737144518177483618114204213231766734887375104540258676029218951587140537042204869180956497539738916610142439022882572093497458284595963629709190984032554426990703795575257431244857152724480987466051652578172791489246344068128408827965045826068164228686578012326689025683134959449804328973353817896689196582437506204461153799000160401089121633156306032503869269482438934233687275161074220097965349311569845419522394969113623056108410399682853628722349353197215152149715862451235602268153380330756289317652217690523213588053760240565614074160755057205264289726754091731336786594187563468506290711640897824713417987886654932978731400034888183435364197566995574914044747621948228147191678637367458272147474044318597825625566375257191173429662674200307292435162423446203016205867987681420580625175220487902231809122769644115438964577609076497768288509398850339663198690334948445205378791809270783095851065267974522491274559839156302866861698270953923766022550651708368331831984055326010284798840330723612775410863101629480246904594548428907650590071537109365997308795942659599069641595466470652844043892731317140895881105181318169079861682437145898728859316562918465836406422008997152731756415003049306045154525004274841767230669284755902813451426477717887686371643328897895450930206201553160172635352996842431343349176236214393109669753653355092851039096185101305395886519863493054818041918993255859142605743167654499419908713794657780893907679866075617451316802887766169386648402745435974011462143879123924834918296684725256711838117909881983248694377217996636733156065025088101251810059479143508376793737306707042429312750791416708596929438624600067840087796734113869700902556371958940640545656492027121545225732875372706703186728401487789853618904809647607060593018009491783026766890039586566282478335930951947371573957090643106943793602246821397882061612458867115045408669261395985205763164120995286352792638925224701772429912875465079986686879756778517149442602536452942321362583310696510015280307688662682600360239274738089930400927595474269584714117730105466252744170865354193922598131342341670336425995332011423270680134610151978981904392196427919421407397700350160802596224992913628038493593779637957876790726739335154853160204434476550283617225816695569415569920501946132060088626493496319499783199659404183852558781235549899932734854309969620832686444613588162407335061777919571882565924622487966961644794647612904299540458226913490842897877643480938355590758046084042532978246849754118021253769641697489051694349863797242624099583615239496867629606128150999164690103087772207122346585707063900705626622171551912709596718050103430483484385268278142161392477415554407763693371277429591457447669665915710559784524011621552678357487557542776589023415386647415830118814913139678631774872822670282348708890201119851310967235952541459438375968357833535184590580661476381130942087910877690434486577803961310816991694903371380114406450547208060842522761505858332270700474176742123729248340265042796494953265503689250833909599585469859601681146088468058953163890050208525415595389437196191358029830557518314078931692415206947062217427148222375818645036278178257063449105850757589349604929317224733154198533747895903202822883234715520492111457674459836520717416646134606740674463588116218078515147074029216514814526955070112229861517031523186594558136885747200072691498559856027619452010480818720342952637680528994346578085392948833814423959959110692217903113822877081727759449885155500255774801129362450256263053821460905744923118201412149731432137334765189531017166754567161041860516043868100784953873770291019528102003900101412907781606663262542289644158978100692995007872577076837430918586201306361192152194437764728439879472861195477861956481030313797337820396613077542212242661575580100404218197919530166275084494609393232703804836555487629269506907883959511784670218121929301767412794763105934372405366964330178342298829601511231172985623644240063090884830703733738690709925061268503732054190508931943880377459714874858353022361349081973596405184105626524629828822911218217658594824997306577999067997694108427304786364384759896676002232454024731396750273340120500140220428664914262453885316554549742794034729256494875618164390894203739553206036605173760000, - 215221061851625773018602564610657346494688026723179401886568303697649914156851530355593177997200988580746222430727541590287864825063178780612311727144949305418941566503079581291877185029347934775590069420903190610857671984166163836379291842575140206592542360377342981486566640026090958019457837934451343600011448777287572931747360073900715041439798301871687486171059894167713639795053611295464839161327902783574516192115101427497321752063402736124626470176215779318491505969530231619621759708908510944897761247041238030137042213216702722734854082418353582076782253904508598063595110048880330416720198408633374363336085421360927227809894275392729151925730678096047856864055660913718355521948412809287511560240868897397208924574792175785166120127539344677543143073171902479903432565266775364142871427478114306814213608007914615508526608758985560571502740131157464387143178429668087840194585675234611112335816949224311150545061451029379520547638972672374472147157618115973837174418583418770438285349486821695261782686400855637789115434091352160112433609804512055347589659078648630614544179365865355210595209282134301488013532192441728693159453751109219130581767418648127776261878846191601225427635214729238229988206137529097776258528021775060334386492413788452352060277849171838181272463515548782549266737754081335398563393632086997519195217173227008169907007456199088086661746154842842814141539173328823604930969907226448134259933526219601394472347423620403946376301268523530321661492788118842180484084142772736953336073574146317702891585359982032452203581762778233342308718306579755999890077429368074323280632270787157630354740414260107277847344239533415125516081158448287983405811704888224963419886464004059274702934751699619077764141054464278067623542910997959381379511388187593581941008976182176589363049134844251216884056552211697567913768157010965825560188061512238739141172980216557042235405917899867762729409994257206110596759952900784902877196249341069739095254476310302438968381248504923449718399842215129038207482254531133036856714957761183130266615222316745474541265755110290499023048219621936110741173145092041722550311249222372472175653551024550104324303076599847173926216446377697554476192264219179586028861170193747592162208605658239296069153072995851989984544461089614878185346202535063757415835544054707976396478222863244709202117638221415142345203134173921734542448530116462319602211607026706380602254737559415352061931752450630677058442685800202174680765476987464468696232462799825900252282533701351862922887202493818058735907686284183344520096510547038874136997302288590781495567111552376961905418508426790041237282244744604417492586664077372691254489704494247373937612683065766540103035206267766996134286010659372759393441819818315849510362175566113969646908789614473581555863609625567977482480349774573435882951159275473748825015844927541280397538573421267003654902405690728759243871600851168759786853655991320225171409767954862025985691306611948851940454294556519269578459312251104001288527424089619917317160101332642089505932294220276810440939380314881135646743462987861992163808494622420683689776435684572245147519194393770963428828042562554872112040122395463328137489427371694218374202503464372474888824090425667217781394021071595851868245852553793563945694408678859358422444681210574418107729550475414938755628753361296460282207366707482295051037277615797748634198489207194970334041023817889509636926149190655483092202979020728215448837838385637542856892613493679271344918113043982445544388054431827097866662018032578925474554404717369809272966115818862644976311052445294435081078781939214448614222950144363408352050503457615203018040282343545173562363553747239508891577919285096127550782966006697805864931329514848959649668382443440942364447339878847513559038243850418335784627233412578937633360117474320346005609556027391338422562402748246242433128890140385787218052668473189526148211752093899953527064341416024421098595422643594335423564501072236027711918714583128729573583963061357873510488238010387632723960407989612808002656753286896198698951597574655203598001037232352232937335731725548427792000483950220135481012882665045737191113816631724105206072156159351167380615936196604244858531518886811866150990854793020174860118279171911213100337012612544156303265471543247776582815881608606045425209902162795718735907884144861298065392773180735093756592964777714008494493805169286990080091366501725055277685898539602585461792920823047317209892094201818077212082136660823440244291306863650194355423973769402171877043195624992143638685855714007329139063835233499683486972541950945133612384443255105337394279913570872122854147919710773981547318203717329906791143359620122048059753502920911121769247596074742607806986433939819349574766201955857220340921487795027367698127456201882365312127752455129574111653109408371332794294780674514920723328183378557717872717270603534182948465285150374147184664781157129588651640167627710082428426968965512809651526248023389573916865718748722975107716313490287726519338739636198540228475112005752874615400111947932565365195198926574986743754351765207936449957143444608364184401983202000873700512729189180268583822809975369407587733716642920521161798566556753492568586895438231866573589012845841310422547607487058662641095752801561375619643435175231830458331685901070233073403334093327823724320659128668583495403999969013506656555700070370998968810007426382510444608953180619917519383152646770421568850438260413638775845030570402646053632866836802855251917206769540874277466734080846646984388634066090153857902063678685276284929717927960624274025224867729784683220204401651454888755821372593698960227445070547915142426395442959715342215024531926398134684976430347752088877142237352438223549969696540092828598503053847922960726030845014066363577754051932421310357822339081545491290108731267322291933227234733499288331144904011118497077996346570717676951957029468297553173190026716338657260677200777054549708890705078987495552442398215225008601491342320643116586431530612335379861998351896415591954187247411168888271982493371054526166925229760123830658158716895581093728647712180324573225543560086233149902672866170766046915743251713311449408947626317634574147644836858485429531539498519218016428913343783019778868395358370928383518467067844472128855802953591841106556803251060954180424812225985758553256458417113550892726979074977818114518098344710796583959894294224360445697558996795485339457301949668723141683267617372216771824914100761054133369343803119512131337309037051819486077077958481724768455255678275222580784134457269999511598077519958378686034645282517486804030525353046392053943317997669311683048164712053055305390269541823113279482154229487133341041487050385758339063724868790951704642767324043372949278391810197854358801477967712531437633991925814255824357259108784078194044842576522376000356527231557902286638113954694096633227358382057810892101979090937229146390281217586021720689083822042457633140103267037739910239915693216820731789175203225287569526591004953544335986916653702037581383648115623607037654918044544795738100134198304563098594578996870367464241005503905455835810943256250383021961007359022213766979928835017316216126811654256503768212077812314761731798557327079179646573620782014388787678725270134477621537098883885059735326024989866994161951524391894920115981152141621801768209980955411543097400543110358802314272367064134356827512234205089049143762396531918815446096824527117534323583592509041203546947143175765252929931262676862390290201369344219938775944430911713798879143345051901337006377171521917573050959662926204744568004720722801777859825832217400331841078289073883580201779020404675958829627964931846430655329877359474518631901288971676122240681569218680195764740766382111137234358625090186490829212419076863665029845699666921504520060108943116719857207623447747649799015841708026583480076251759400836710593388687428006344251839566549941186083165602840459321514741770159035454738558675663330838440709867814643808807043710891162402334452792204624663975294384884538089881613945534051676602815094940057568134991195226811054335394322678770650891937830111033682344083044008123739711304141312305607330281830586499258226068177752808769356639772421222892619476614656967003671300631338969142174391363702602210833919420289039025246215157910456248042747974528005039109943608981494049285003255414834042065503894748390345132517706743302369201485761828807022119342448001565394838525242793610623653151908965682453153503314909450427513326218009255937704337753499998914327876688953396668643150842207998487821482263178385467681665170982383081634096032363192800903698064763928567889336633383353458116147730112866478500756132203148875598105195386927731894361814495592411179293251953129414879851562901456293519941634391867591353530202275100832440393370485306811051267917580883104520287416969693974410476682167384182280166172133652988348810803759906720650999382413458619523216989036828958019262289859263461057025202605656578750016050253809798838772626131169013613847150714988408223713969912005672093352509820789011047818178564281951320405539399498107951166471484289090053253531099531397605787560439267139676506909427890508950662063203716004422798282514331090881203361963739332725548379327206620436590056999753119875514943809759331206690867232023201939585764022649954247982502227319212912351647641699433339358198581722205996963370409651694782542863387503731074167952731231661510115711725035596289982057493363582940133075756263273095183991394728513210530115797233361267192292351185930630187178070274310995185376898111839224349999829915064409753221251343676204035196847550060902719617032739483040480876967823178329891381602836410118832231996789079156330542532940690191628007968346043019692074854371485467240210176439500942750395902318711513411633663086846472753674368454914790842758214720151914794992987980062253095565450773185113508339980059201441326036030445937442628428064351485132195716379243366036335833797295311150895621717790097634251060400895882185592406970814390300033566555166933502256158845914097184517881436639933677265937709579618294897145171544886641696902270622503807421817593962282726173718366699999523202415757050377841803022648104836448803469145280161176426734363265373102736521536606870904422290807239988773228969247256214800808325164815656802369199661388561402834116537877640213824635982099452672535815107928524999058207254157695446124309103405219365209278697559345748305102558593895462350093186300700181373448480437054035653494780303769600000, - 802198552808258643277686259379005518785827708216649501948756967539711476700088084669433093970203666198724222047225216891736785311549228881711945275026592105636177897439940998931228478476357976885279013114510577093161484153566572418736803264655119959375997394357092352066547047500057182854775787146722984348912613278557241642968978936192183310364072596293079745395433769535019169320205360138201648925607076412951050933320861554037550515026266360962186097305460428797907082513120298554116020988209584266836226047413138029877094082137909339607986061598967954876028644580074873069642851032855607089381555129693340462099774324650519236711802811328795248225068025405329506408103160035602985693511966021477219875340379881875243231793644564984076210860192887411798903987569336944761466010528310471487268757487933770854837197533478156516025637397179774787825459545840333462475755768134697397675328565761128093062782374457349556339352652530293956904465143950004857193521983195314062151901355551770033673973378827304124780187375665170097352383093039993646798299909296054187237738803808543001636017583002686247339436954788536873330817781699155696188073286956401682082338388248068533213475924298533596499612260770718513625066046650363221176038584469518160423612937610918560818067104982192603486472633521329611414026533505741695096512388875126515031719678267051652175504843079724854923536765696294701011719990388847295915575149609821731550139334271221327511377643945036411179678701517762572161788238542993271759111337853777408252681424864600008709019784089637836725401506419556802392370335654610461011843312446297781804771940444997713364156156909724265374421275082141098398290647747583676237852884535549068871497949785275285644654149225312994864858629505366851332134031437782004344691690029427320648167974058703322689009883674229732276358188411720943468830216174525456716147200747178922105748072445362348208711128116176565386756536831442052532614536399929137112219421138170317065201859724743698204987166307347020323932948111902147080626199470984922336413588167560697806765275487908857813440055725458039626017259668432159071202210268062577413929043998398700830646116417485017256358024262549464927994930713647830223849652019069482790254234458284680930303817017318994553785103854311199051855195725749898719707140539465047608776154116065372447267015792301909358120700034577774861071086272895278474768202538239843330301095938778985177453798725340532811021582185071680997687949905874077443562447919504040086929125238768512499009322088257764707205915986844634452322925401646442809899297447554013947422214080693057268633961274135291065893668778303622545445571551851849089952608369756812930322925160911025089093923391426006133874248194577452116413622577267087509261716507852450637223530594197693552345602364955399688095379447622631034010315684589582767624899657502852137496800178443139341833814127753158665696166184726143068860478985262652684703410407526295468979571421617153881479408495764669494576208474106177563598925294899654524453951579303848051915139168448751856047542625343358273997256428273267389917131768609555369986437561792625076954132967008617720314093478675760627380428237862329467904527091007465714383498228334436530868459228007170576356709836739574673867491594276525951929623068340127764015311633927790572406316488562912272713898977935383814940639289997875960313566390156922378174077634692512910704966083070031239948817237807797259030739627692131570516984637525170557822215124826308986703453659052864334768022083861714068497492046814135365659652967222803838587977888984505931582859786437635086346265136892498230119552795371456195231864872835663924674146231612433850508181101980631561939249730378402432210660578508094960343113625808097024780281367167720794896386686626939816082565249719113691959666545161309268564163060501628313698768317404664190695570403268867483853602136912904712982140732292139461912246994436753796987178744955462763017672870967764586863608360046642514509131930408415629036967980447924639265233624946989938443735303064338416630194111384759758634581031184653144969746615328955132985951155918728634088317968080373294134182174659818143492704977870111853234257557239661604931160410862812439941945013587508900653427699866151280408210000294858701910642252700029351521735094880294228757320626470530146942246162818878482068075622156922337537490118938955118928123249861363624494092767892179395795882441239244973496338243174821722858106024906621761316950138720140777404472982113432687474782978871580066121106538473878035409491386309048330787164137113246350693203171046091498091194684724847349057851263430998467620252373352591326467439872230491958645147055783430833720778394135357553836701902879099293185396425996767555933736156596624866578155274512357963144890486820394702975615142201404530951852359761694323218623506654359846967455510073799177064935447311613291258683202773472509115217166200784627236628828734610295093560462896261080533158195694453135185629306542241461811502162900764366383209229977616045475493845219124719966900404922063131219303785441387316806816603752503818362582714455003495082772070237167989029844073220017808646831009646104338912034205232916407483849675502001877879764782663388823581837423889805100594819322214807122971145833974290561806812460011822503351498717994324456774264777358955212722215598718508203004506554210829629640891412091171491393131338340133328910863826542710638695346362472295721006304939947433078779919816024983387346132119675139577643637229836647045074038519684510070392136199511888391745372664670533644832656340611365157659585903412046643394124687454241251280321645023723743006471174921829271084550847434984523695933971804617348365570935882728058550076667247586718961662841061745919778258905256177476535344155856843622498613267955587699822776210862708408048503985201557823021332601499342827368724699847359219778332375021231008609606295359630781164070950917423629425266598188858760711739061033885395574806109292713124279879462931257389938422088364263003754045697360361105205534590727566534283120476849524137744387721285724199715389650698683663508118642858288490499147918770898174634150202031897818285911142167264130138871846157054450267370467988696338146146913507580971368751483973400091032637387766467003051857139944493340076624102318092226494510961184902145786144175642403090663271537876276723901275519810037745119070170848303605896003369711948807374996869393474249881155749008256758910952378988849932058769176066267583290588802071213217249739406703115384476942040445491628434387052963915579641990949984982889198719878283619326042799676793468292833441267485473264991977702427312053389871881838418989638749334137572844291836718523963694299654153477093013570713861177682165429965401382268931564038000792010187645446052605601969401803900664937728876907022948094903799819356191343174136343413505065606567146398338810497171160723613170244663765752292308791550542299158961223536994601565764758680574998991032482859968200003663454338371080817948895700220533962751766291388368715891234806543421193590640621643402053143374248685334557192239632838921933898013979396421011815931076743320376525810537869631217714318605146092701341635640960594279839673086091789520484728213907500956841525029769640098793836476447269256463303241651201902754141035527358865257963663217805249669674563117487815671341666564737342756259313079622981793959233291090922764286696320841997051174340566887058604674022675895135720826871660765307099724517371880075530174647034916580681215666406273570477987961411488024039013724596299630480864612162869066647559005131698240287486374812058065212306816398960457707386994663142664286044034204162339072237376006548201290431616912805367532800113641586048045810151190214804353746351878698060145529989100518376934434815322536189668795508005538713030484754511945961380290982426104537649532740513780130006305599153050520643972570931659263702647052909276241010947147805158057635485456288073131382552385910234316568659726272453577656777437000815343756317094985655406071474172942426470370763940869585100475246299366496792475401633050227583548434456865215308130830059821225246998357812851953021246036492555422659631496970388767294681570943377978558259618181988678130204572209823544752649360971221435643712360832851339577552811948098172198471603871660605661112717898749901526038164180960975237269910167906301643234268743687997880126769513511258825792312624506124903252122196372918310914893572497712842663192751690903702664838966251483151453584658767559668324237235598338899735005545262271221723206712836612365201079412935668361896859228293646669358845785769996591587264845420688384147577942893081296474504358786654230001639969420903776995905127733451374326819193619334534119754575593943801758460612228284037902029386732701598319496601377750207463847343033609268368501212016105493813080557034862656012898482617090482358867807301734468390393795924223901323255413999822121569170713869404497657664096808348642435876471693342048647083043912801474900167858003387238990723511269022841582599670375324356359733084601668677420104339354160104247649437217494987074002122853889617821104419912511833563806299958557310253600513764063308612718786877493789523108327939730817516655320922378356458082462343199752336951184898894321991719526965265168444160282121718059976423793473165181733973325271935403947261375906078821699770503302184756515187995098576656726062987201951084927727295473337583326308296991287873132093203545040556742710504231205285457626344348158140555858116542696571443831891036004403327767721366805045024990889358672822387553772690456751021619191300854000996894555661240074377876976295539980582091348912259114506170109678691508790571534839905879128663452942201398523596941232311549208573639958268563136103317328196124703145632152047738216997730131983880448896333870260420836757465762802017608545658281198402864192493270761302825188160268144231472559480088331766903171546280921788031419412701194551233361372957277038126795395670398399327018534030098105660901875976845989906819818321684376291993073639405062841839109400057080530319177023348356771351149520331532919591414053895231538765597083410109626405644299098429831362044945714152586104366851816904491799312100535529790278431360607309683305188892771191631512705583784388936933479426298499174322487868526355472059159213695103997448411787034681254270092561435588276662318367177433815820088011327513886075853262353485314245455554809471910384568379069851753051134313482643513715746935508721951492309307092340750497382263685120000, - 2567235105220700435611848552116631881750033690728104594213502003116782440597152173291012971907169045273012086003040588345923718582284708226457741925757579251467872920182593068808888654692539413983515464287577152351502650827053760091787261370261296329090017664948708918898564604465001950406751623728021240895602049418903328313610001470482634554842913213750967153155320093282054177512166287874792931313286447717264763882316555184789279298867152087928486135850636617568981031573642316525053741465714932676314780591413697086145864729585190693107112463072955352569711805729707150900731244165599197795337983262272969459828513884708546909789835161790452791622913754978131037191389151763296488368640019514899629676891537891082138030485670350561861185656633557173103160626816900150573234956221423556218992612699029108544480914967180631424557942313680227916576500546467621455887366778822344354777644097341758799868904989258483899429176596228179273285838068466542930463061217230068427550137676081188506398789465224947120149390803394552403415428666855687823443615754909420189822801955389300524837599609422131975280642147919381576141356545143303835860838475945390076403573258671600096617802234221909434072221924242800715545228730976286836013080627374112987904625555518059383696960988195080354716982418255952911693305306320175742652865012907796911513387035898518821139652960552813553106453364423630927663753194454701614250404468926900091707520458575704304469105377816193865219324423612041850886384121029603660964659935491984815592002156110239474947235241637039562538070866535398517509474253170888197895000274697296457342419581716631717542645140553127213275314899085941123303600820245553873377293543566322785008255584019085042949105927512713793039718703187592795256385552381021473540277913870687316070806607374026371431336717232622580124579071845680323764024205619716866589027146268739919517711033277325262245760843746520949400776310225068922944926742151726855061105743454650523807717256609371936525733825470348317395656106507142712586044601433271604366056849911416104913032241714421997523993618760897123026030928832350885344364610781326957343804104943594422793232144505520334760782070597106045432879799440181620122405123208521395139450653223570877527450729261550293307489939449930589503552572928558647169712480249578815646283513791756276904237541220928115740098727208539913361655221240257729778510272676377425282719570464280676096246018501677606579789210555013255794204885836316379515090509330582604482833377648991712313944533484954727591137349190393101903131311771166566882684850042557661976879885123354070801200091610730861621068420353888357485538205321202450174314657674043957775445511393073016519004653205355235955245276682315703904773656748186262956342413741580269349414714834706060448559762142842543420232032726349815820846630809206019606149074827867929418438156771627041300535955150850522539284155438795803348588545508024390240074526567223930093049334893957464604229729876143594423298866213752752168290939851052318670257288828417829086966900851978442100081191291196924154061192113095300462550798947139035608381528101227634429672563577372401583045491809727265393097111817080389754388503802508695446608449288671250838943277003147521143594020244086659707028379713622174849229705641068284446948321949901463971714119966873486995667636739987201700859217440664559312948368410902407775003672417925198296069003907281312402786356574878807630087211494089177222002438224664463355526651139131468809253975751246184012229109583053619766364564927964459031568098205104107847459324009533061274640672183386119085822153600275693408193341789287039492232849211370198652940850066006527991820796132458391474942944657591356904377325175867008376700210210730543709340503295750360481863690947605675441671707937215453638214619641816817213826975604325114932854229635279098674122260874903914467049192805627871445889885592704540275785355407934259164362223622806931685205748375214526632157907969345707806534443667744001335182239450883668782166222558866559563191465348410590179793338202379606399971172329056709546660285266848371240466299241405693959920459831461415221238539474805249296402583371807578966290416415165403995310339796425708996999905681679725136020541679632780238604919784019020772857731183769439084934647779908675943230273496718518405406451689642053771953020041082571062041232936142230119840700801463252486862509010998252078362591306381290137273923705836281572391052694475111472868141876530280465785656899534300510145027803048128178526262804553758736998469440268101605373178675323444549578819552739849513050677293738298395647648761705482389589967552626089066805239253405634601102316870174026884004003661263610560447909860149204918132501628090251491243841917251927807012019916590316348986924445607300653809064898385539606857383315230351007607061077803712119040200339281995079444105882910686192453729887512470463050337014436955586658924466529681192074868188767801046981322554149622081324709135497332842651193356860878289197393886516992650721160497457239445657305153454786046829715706086774193439915623698479499078541466504485361820888550362314206173615708715834086180194515524110372645853011366428585419766175585012066519359383995561503900094809669000165601174158157460452075971762526140404412199249578235970337443883977608074105896688530764963394913231608392073037972848724839710542327246932058809367312666283075423261030474168851012233099318625773105587988490298935171890954956073330718850614515075541707297320618523020156413333028855086367749306282403207716867451450943823340067224894049846044334375374347954081982074703950966842496569926229021553953795387804524154047135509693710938907053496934221808961918330998144345412233216969202412437765981628278325362776968108680960302056992243590538526109225072615825740298333132679096096703729312341420800143448760042696080143505198829450543050973790558782780251025364010891967346514616373364922191699073018915223839989974637080662504101652918773551010227139482201140107602448270535772418747341141021378848703923606361014108105868082418916752841664738962979729017524909130741892921282826578604525120511529053474698242567494339206990716814527020869052458349884635770129990220121302579700845908187627241801402905463765099291646327834374807281364584732552225401614698287878170116599810404002734046916807339002843693630558151070139343318299573799092260503236838832119506922070165859748457256441770695763600823927450844836029412593208337547376616478078311643810412108215949356833046449172694296804725186414870268516725741460824198885863078810843721506926820059789972796212609709384745269566964643878096426476207539217341912683408200509671165706092757019095708202404925457944037189310516598534336111914498871379484534659518184449929996708998099088940883280046993256475035644457181240661960499734303725445400927039472202677456957416046331402382941085703451469247789198739575508759465600568601688828863834123839902517752348510647305507008461969677517694989468375326756172269787089997289102226468273343850907679166598305855224726139024249156078925624410572951766528847199056298337741232948506010523977784840488447223230111520176549373670667187059598813410261151675112648605481467304808786294849369630384469787088407167177253796147427174757003362580200249845712834611290934865477119580418408049327937947053086284855051298945911388312505987956386662157174701322324414836058330957236155677066876898037883017141583669774911938146426370952018065600818930071357403140104601421368639490564777473592796712237519210253386575421652653822543412985529778004979971153609679498145886386757188248310125346623433567267380228561471964026900960149280154630079813150220220074275696923751411751872952068602925707450989884317642973099364245499943150002383495995233932690346929222843772269519740576472692278342929302487267923675864840700810013519667244978675307295393733298476135011588338951745627393797301722445466886579021682297737779222083463612028667468980109919409942711334716010447185564913534633349115299614902290875771235084830190699991343506417304773756650328663685346883174620943752899906175717885999219341839876663996228199923059690652304027583534193209831861604313057128145402224059330735262188639502079653957694943720109218195478353344951968494444375339373692448387067895834572799490567186758918827591949793078308464581079978110455374260680752616618189864318306275361016824559270403533793332042375375588985300674299220528222434315287864514852608739977148436185078002869362486121530948989445467517878577627254868346265582711030442044888551217668148093443926470700196929968509266100766200666429230147588420362717376111187132034812711672000954026687209267027181867031031006729411967903261847078709676674474066578820738455939792728767071701412061800329079839404599451405913975041603874130431783947416344947812007995269390217908989873282700240724121160538686863333942038769567794374793217318259992737072587307625329641908862423627632872184666358666681464240137921534505376561495917458977783754380443404587142364138641781537626658950344719519815966383929903909342490708805287422051502370539739092081899664242958414227036794262284865443359768840603188825658954461317358515261833778974214195606131378656536704037635635147971732216996910741233402778906907862680632231326348764799985136001074303783772812635187642786852147256246066182145332355913461199253695411614447158011423243278261819386527540244249319105587982701445662002552493569610942404189686116862627445064057691265203347617983821604159943790402369840992145160961032096520398208858169087501299091760553261178645836886510888885239111622429629722792697608450277681243838625655022126951196326828599014199447185313993586867636054675936934641007031517508710663933991416664303309836664628574412608541617880585014745865337548032055033273282687294366212566461456674155312461039137913623566068850089439194449878511378346893399510461033563429581829889569822951026059433202112427078002603820614988918043878945555478341131315171167556232200579152260633204415140588247345801639721386960064182121067811813189269418263422458174013914182380868845877628112692776307831541868100490324033936229409553709117845421257077241878197650781612539937706805594624581965348507493951266939438220273057641986149250452057458383939121579838270730917036484118850743603484754309622449555830077962129211944426155034853798351576288602510169993553179453909237962947876811819734914059354740813678956071710823938540104587188253265360901942762352271588994568848182609046405120000, - 7138519044076796050126725446682441242866669168820380918465125981917592088616461170635769500056004967896367533215885926364856805744067388345409560980897381759328603336686753682782450913463550174183936368776053328139974463007223952799948657125930971070040972582092211919621874718251120292615296688356905368593206232343899742650740514366120494411095653230681787645324378335083065752677031057894060969189427161094392705460154277842872175196622344693376762961668007322310575788484028877083627651857453969176647867914718772170399528208238506444252750115553222434300427194556144602536303800254884131272665448165166754663866762381400294167989943922987868047540929659576485924689879692564770614129888104639390217315005624698371854781149847856104436677153987209562056253133061397233313507701331948145080781243462231319801445109717454473592791802537183957196354879254172751194509834548116120647720360434166506914046931013636359312360225857458278303030310593613926160635012264607815638540261464636876675247399536925608247008949028517823762093115906555011941074388867448235549554490177034251299014742102953465198306328019108076437004763341256014322700044161829771738119172939286076533411150693907053130307757062669671758390794915483237541911434419185074188897775105374456052768844429100177413239253772907427222635001391856514773182001633541633605854643208403374784296888638725014954263071051103018065476877178412667528774797851047982627840245584634173468657319147374852350508106625671755087231904491157718993429651568308827968688124317088543221289336796825629361127475771325210989434439972830611902212444182483204017218290424019391685394984363922405718729669985404106721770706165712989134745585371849333400261161981723232566930158465851986964019244539736259281235508694862344920037364937473469764532903500220503365207686262017717680258291297257866549515792428697948636331991271842561827215133067581777281125577813360337222618195697599413555794912936326429788682324481258774921037975231414544069986530753387321783133209513467131466325777131145070165688819551608313993340272408290584630436214140946879341709220406043282042277429300859868832624796285844617098404724915409460391035729480736470401746548227108079702357646569935832634427515175973022552551206178563750163297351683963668342104002792198017758788220626300558395878422705170341777954214354764862480076634155150307553506867712449026062456704416142057427615322610904052182054480680231967364678603701796738437942639345373192398502033127797907856734819808007364099077161452926744020537701350669081180706154683155386634267171231902921873862774020254043488733669106085465898759934319292646566469534630503098439770608274472379556405927942298996220617568496778901414470167007530461405065571009611935904931682417643269017591431606854389191085946343562182706915799032273095347344611384852234496757064797698640403747724835390634005451815765174744990931549237543897264396965037253261101771915494452259396307197922906126466498586445307186573210951849431077101417725069413185122897680471381164322742415912860267466836143874388781707479728780027597903135417501421459518454517622818395726210673393858200056415514081008061603722113576413352429392822193784695239161716658942624862619967694243692050330734955012831845746894097991602264054276306334874707462036675497031053400311607573024770193252232740934755828633430451562289371521887633665224264554128683439405929566246420222741854792746757901281003173458547927619800255836887473360823002841294944751774267647351812710974515309566344220751283291500590778390632684467988473598499581693466266838226954725660223797710082764340629527595507553306903843953921375362200843580422856867661708875833909147685498388267992145350809476945678388458404381662350752989156828889641583008802449635254831539528619751846487811023593729238575744451226751725768950847488498408248337756045134710046252718448755192647662810112972491281965092299843716305952101008267706780453891846454559672132027793445440191518782781730634203713446601029749618000085072687989152234073717456411728277975138000020764835146749745654211890957449333818383663036646692719014135330388217387842813475095103132465758671858527287704895502158809003165849331974365611647834684440177573181848355470657067388447963899462225291060696279147706643488834919759075440572754463037507859354006469588397878136456569533629413340325625027796021758624575819830094185475025786675664810960709632884557413922730365140052091762183281942920906106486104800626740644318585755470596825431532509388924450449240471433390630556689877432288504346541419144794210376365643699011555545994810529666125299641185971588492479173593166692838616946679219407971986017655244159608398155035288579660664153895032703821918525727772756949855615688954575133469997278941228544790335195683722007403685462659132999931310292823573993532735499380664530025706058301284876038563829484261629835395902416881760276004589399426582650851720711711009128703208801412622409855620363192094412873197230892989062093590108930780761808980415623458803123377148981704270042678497122329121242353418058525485191355187635029321448219549635876558757876096327393251238294690577053650910778259227278858005258672527755111179265135278582273798305646873158209686778635165329669139384238219863628345210367960124061532959742202877716858360934554134428764313841848145206478526937646188049492615509913232919826610799159145090888450416657097663434893661300915210727161208215718401601645192190375745503533918882082344146731818471623197282961838720369589775149823876806045978283732556397613530177557357674809130912851130662500804642069079709450260097818077206642510934390942472014082860426701372875886320003030509960820723899893746032681328003051172353292794587783239838550199613224853102208690829567042864543223504993204010367269190191009013133782136472195216757679089291834753100434393843050417332966874234654108303642898218155278698249337030491639828884010200515455774521357138587264946611990878069169709099158480835918270272235430243912957315128453396287695739464381013402600632708082762064195655082515376871872426615148311790345908241611120794425721472219256730326265602268035960419758204055954882466565127963831795330986636160391734567279030693577957310232655319154643941703013223344142513226213402988161856227138633698940110982805082950658694482992427543807905034996278651958010997297064844847986722185290405107689818837750421271035543581548618890227120154435284290282867063812427397532503529814781498414379234524441128741035067837343705959480418276590455136664412916032272493113521308164828918162054307469067113985547541533305764882298271346880250008930809982749651297113806762907316775155922952925228940555842139867513187342947256301542623188893219533750677062967087395247150739258943283644618542319930402459620001475009842521535518840277875633369262112553330419574082643608842145249951144739106803094644096505521751851543876758943228459649601800974594263638817416626485129967622246921568029701292839923000171100148831680033039902682760875360625472606541889683128133354212161530058865759355179694653790540909701925121460942602753793708797088832804209511783000201032396894014256405821703250669406182523544160261642482524605071268870223589392020505376254917762413285007864594494913250148935853034909442725224275836351587521506712327551726937709816400918104429700455596984928896994662706896439482258664636918635208078132547731009451862623073277595858819436058442561298796954513966009462358134808251702358092491162985984433454525867446611839888716047391911966226987086072051372071361158638231623535492480110066917475249970459682025054363425663951769927362857610092645211410928489201542912539815596425434995879387682675557411953038362145928607763523593628144665374274097989360493161311660756821772882058768132955150213181480987804913878821565400308081766528149024831016938111047606974707284725570386230881114267635179375524625050028631787159215172394705302709878791572323535884559804180457784667524834418768338286940515341008267986158048829255327137685793685979538513773922994776472076857367899686450917915330660618391272191992203169173872839804411546831433622013214704520813227514436940115656798400365761500631698250733070886985841367953723641642550289461733705784529287322998930187016902016204281756665061664999539330980695302172117562965649224860486227599303239042962126705099744116005971208088902157097544567594207152850942697999104959306322691391270410634740663298881299388272051518101780019318258931426965728722014174119714699492850590426110353935518212485962195363856735708667044342027496839006309695712147973973536648788681456406771008343441364626324951418961984285609638211673011296317990968740232729900096425453239867780085540412888096524977784671307130306700646790431787743674270184918081750460853198881808607375161303011940191123205792594777242031230251825882891337932320929824519469482263200164287853776712027386473541141951385247910029182785254101493234558755432582032074331083546350971986900607223304005010603307491178834280777013751924450067508005196171912588758831694112113965732513984758663349841805738274179773112351065078438377206833711192741011878931811623145402009918898725479174408469161445467790696463274501152706093560537638438924432328220641555957974030694950110832593861434453234975863700186120657288531300370476090324675023512087644024344203167856833096869243461828139017995059945915756737542424214484262188298533726165319350637719892968166132662625935526267835839882176793144037552655990346623362743876453522963874228906585844158404843353517887113179793305824197153545525345463413332681449463742573243940704807181042781965197851301722762007023242911048037145913771872927834308499968396945856650860802897518530732121562510500607114874466710575142517692451306687628514263893016316293478624265408923297544401847143341203975877766863967623445321297353961348021244790312997145167698747883801398350313470161257604105213538543601525887444030371760771095123431830771488318171327725238022320640005916139232506406240198280078638814523455071512544187881796274224337772805358567712331760380480544646891084884139045252809763147478525621924896604753765874988159124100103856092341982734356550551358236717204070219073009936711488734911808131291917872445209289307652075051975762684100345550237392429014428731262016200390854011044714201163698663348076339181402974453918264751792219494956440619636355271192800041388025804295365528428619127997933238811503256832315691508039972795248931307719816642560000, - 17412632706264910145852314742448217559917582087146970801159255403252864270793336102817018669387271709459669751414720723524388668089010192687870178775012458077474876139225521773117350321705518481035143966420491144698812459706290664354617338311083639631634949753965340738582254162114621618225985146251022498428001138934241009550923074392290100435357361740403586151017744231460411793901893199399562413399339845114828821287936691885238367614317178618955850050796707835910222497322460982041880296696209317591281947016813801389620608081756377839161142731418967310955303945129503445744469415506022707773925004468975818086705097668644758877066205729693663152715190318911979941547336367717050527364253952754143048568133724609254839630858909793452219595807273639089523867990585951305748698933391892676672911412155779640384736749823348536931036891521475619253622572999461359819255217139357566593040629312383816687408303604331885997547864400460469557236025774918446294293695563657140308820212561893186093701101096588283844054432123393393225579935567445014878545862886247354406547791987383514222056872996574924616103627929904695970356782105544708321890073618706372717594405836791239933698717663138146959191132174432640222980791294774455159523643190848251437217083105429039182327625907148046712869052379918863844679666510734838292573952725109884417976890154891534117385587849642572602022841012960663502993684030669833700301516348468695788745170265279572181866565358267722616160390263181968187971512778374912564769111510134965338032238568113121189748264849247906932360554790756382075551525957881346532381762534561636269409061362027321412873282050884991471001770071323880738190283639680050210394071577533708842336340425298120853119514578754857115252221302244840168511597095094197783356583249463592750868934494161203092261039012559954990092008101675534347087886281278112349704860410845465216475773908750874538232666789904859068251881703173514281360307125380088494528653825235748414093923500984486869585968082691229068413507210951696346643176034491987911101695275484854255998764068941956101876013367557338748557751381294615110289999791490691178678825446113413573344708717085793406734904893867357178234317514679833886838278510549948109609113645435377532961337435204284726438640683644322228327824077710902328196422991392794581493006440413617995315513798570810230777469696445897053635585278248716694143929313736390454121079189420197957615922360259311420150146387622861956139957219666224438131537125612207573643011499278586091675492274798958180650700621237551731955550964060723257160416182295639581814657962319909590577134316227364981338976776511007049933272697431666576980984247733089703178176813866704796812761271152667900560265848998384640509140090123269476864783081000118709152538660864305505339216892109593809514653351561256198031233373257934742067781072083033382500837046844931108520285885361164029313231472420047823572320811625743177780887872008377845156472392020368007944350765225680318681393913104039883723477510541338549222210481709327255352036932833695722744471206684715822384290104998205823514551003048673087937918101137731823925929401014848132066933818182033597882515199174263691631002927512867451396604174971054481110252661351989650630863768191584582560785639979442767694291819216957799233631532651056234562696878979961400658300520206662586019992899997474417937737029894159472891890012142663243437058588898719791324235828435414322479588506611049991987068359149751345327531425293103274680531106253925239432578417721039846046637122625809034914427086368630356360201594639522943795128105624496580265654834628582542084814741242324797735207322919590477736894457296399416152852843151268483750126580977332104787608781761834617255701530347950877264505022331504095244618620479160726207390764978523879411975835444071111538318085264902593062922815811854022942999892894504703726992255162817946466911944630202007868939145624986653157597333079264707104275383844099969309833612399218681941713072037349918766143407690122331079011082899547878414243298465703898644181111415075568761253234462091600786253025104778244531510251801271799994533495886079411049194233140074812782779650140624403352716968568610321628320116024476800351506817463520261340907765563133334062923669054846812309901617262052949188922088979037320679920072229841322329533112124676786210359591698654044091157322763638412731199538167294986256269231380364834221431416042343903777647409919445901753362478808443712842534324983886055507699174167605941486711133218292130369194162052702466274152813651279516665647914654347500605139934289347051085203815973573487366053647502603909909744573535798891289815668883919554936478049398639429835020263422777072875409144300077171208890898244743195760821325702420365305267017802128575901243418824300615179826442103308307518915539829056822965997852380064756955073808146431201597089083331070101696912462117816139865418300985798350509398907456503932383752975680022170524376774648002336930087048802370120755718687354364089659714874163589380285882104218544994734495571486762962881807462160285919715980244852722271386922008459184294947188061857415533543065352820843588144178197462040362300188004632430909723134780563920290643249310502620960505614170424009476173726688532900768985317333631574489717940788244507584089593732548597970762444805230636445995912765335312536967440437524294766152135367719221891908112879586272421036935561370731148177892982764491767041819183196977779804914956388345876284387908795102582530695883828207198938518512348044634262619490981089276311721780248323789339210610995527344774682093520757567698469700415785667026874230072326031837561943411396610888890781528331248551819603372213887447592766163510202213288639339681198143367748478832668128203377970391927879333798441617756266203388372025635422303810325921362467179739303819934142202835307872734277415601345613419697950090592479994634074804996432781799826802200128243407979049282091273963642665271006959975627983613093760568792476988761690879490795405618206544591109572627578969896010545617788245074327723563356403242058535118072779868968628452673916424559913301357975423281696030079867641223788646077316009096407999491341550072311807270174531113406884358860524538511779428169946862810539657400491124760268884539096810366397240857651560530037763700755822192985639902833199402128068187303372930512871562879676177275381051782223696339301943548645810279607212104623188725927295535635334260003118350945615082720703699948667544728707199248434379461888219954990062011930241035420708965987236135265345339173419338221283807268868664290995786942854081648329244438314017855511716062833618587459770574257817433222645110915978637228521900083693604255900922155027167723329730298438386937213099765047864321198942869244540283110451669185573952527241751885871591319808072908474704821062070137537633499496280656814857078812977424651765252117233336479846040770479246210410772103985166237526778198845808927668637683210043314202099588000334912398772312431449675292813378979751045752009666133585597841748459239552812236472330420006340562880442793564625584427164006891061212700877018216704807172967062329805837092799948555573534267707461927701757107130301654511207760347372070037750916649565757119390439277064337091474405281878358670453853933657034357473864547389265812216877481199090870787255467765559349369653694586924859448647180169473150635714999125024980270029467437083399472653738132525937551026046253811084565151570920563852487680813215476899328253133247207604531129758490061893219066626761475115414129181638174880765766171772000410964178150181843207742040415642063881322637943362615168630951537272990959971125582501298209252050917354604231482794942839869793391414882699321419156860182794581336593144746740379199336912888761158123909919281332299992880659959126193172191354920972349733834360221749839067777203356620662606905271733277524088132955174771348677554638851965364616822392121977888885190980929823098158648112997245113175767337745114055475171891678743275675873602305555262549757499275730005994582613102804369839273043415767158411637412334084312943004960501349395776563927391644257855699331546236215833177645677444875471105958716144572757657275548424253598298431685602062605777813675500750671951085075099709778755468572554469034832959326175993400192130904703050904613069248640605740038761035472122481672115190034226561577347886281533379515062612535358459602484015360882875721489237538013254002444976783221012049488564064448175338802114165033043071552658432601678168758414365295313684892858091169572474326700924830218381194599845650607966912608845669237260412462086644906822373306979473470844521863314273764551092202572647872934754130735402367998828820598974929783988645963315331770526383035763017381429182571069762519831834224703596525149874207083687170092347846068480684211485567255348721488946994703266801375314657072527093866400156519688098125167239844004397954497296408235219753963065988309767132236435522363681051244141687409324578153134566396827009093233375600122749085592925457002235046068671060889745764108659959297742960126673870432301742547648163023901239004173836892684506707458367620235195113784670163083614676755300980753420400587544050059449735423594370759077495458221496087375708130448318578399830611056690583737803291756292533194747216671510064191783822362362887748115074709527822871160790771940673957582650314589548413483140971794620156015206115081409531920829921130489600345119842297092033371074593177500106933698011943846182726293499611336145732259941225423636678942797869388573231675823454806349514535726674304369649390949392563796287040410084852576529561985250863050994652555504634406819482488341268406783655453986226913863109795740881651865401212601900162580388289175131397785529002466688439691940416884430415940036730458383491937131236909530442011109346014402855326178488799298297282852948197356089503672473446953042743552230589211945067101847302433875105372722155902130474310033066355491414599390451177269086368773094852483699646620702767301049369674133849283865763958134304501332200647731048612221790243371493788110237844194888955188746295634591993666028193083993799628372772147982026070275060369233772141336761752267762973293794425666412830992798538206709633578666885016535483954145085638953874887097102133959113481906713958273370464323214092550426143550966131347914271575033206972935210167923538458857185820441822164219769601012766251074372760681621003535688429179030732800000, - 37552904380108383587595899996140759275060922957334398744607108025158851528133897233899885137258926377049054388138311378024724177557501941001420008695685124456291546565589800420186592034648425141694597980039000050933945208721309231490735696930296423509181394798342501591115193947824771693430468581271506065194062764253422850922147164442834797494524509129802411813932168977555453280924559191382427369132259884735905025708274168153582879313641419831789726104069251559954867711986017917259077363406709254707030631103340686094042495168942974826362038068353994278975369346199402259054917209171621876293239457363215171655524861612984384608136133053799664688947789709865024525273131435377063391179855618079786661450509539229055474745006915453446590583574383101452687061247257554286270062560175787162599975367741910895696785740736995647579190546737894310687473532600917395458140807472470591047244568805840450394752297992770320380417344843274710542073748606980136245810376992393615870110906179633001559861126855957669827367295618595315092082885997077954408561725698141900803808966394965800474305784747788720777965432541134850419130165668080452108585063391997927088941050849867546992770368565881620267750757727539596051414099773705010504727810792196356443944843710046144284577816683652234377787202338236132133707051003436502456588083008852850431116303061889019412877761284730796737622762092584939966999901303073170253113564177742215467834872049599514539451411913332053780013997807676374364608736173369101463660273539409854615350130893576386403757834155808359156826158568919933979028345689390427844148623088571862103697717121410456549206364121013045142336278350035692319208285216086761704567828788277024173983584242681140104765698999630382552111085631376351334982425452766461934801082103391544367186542047238634258715747931656247772153815531523766305042763697734064357956506623420174603799870539693923258414709658914655772742923996058578772456012738686726330249776796777363368135783926507657742814914805333456972220605595184658829511927270244713728088645864782496336181804153504835998472262010125845402101547543985151548621214623932111202177703667577474921420734902675816872172743064268994199476415980046571211667072589325055187589820004537824314015682798816193679126116978654457479692737169316569410638761133511955625888441481279702379359099895537639710290971118973058222896169656430958661655233834036686696614316348813059253986546323871666001575327301892552230854506562192242488666478878530594011193903305338559215132566475625912008891271975714675810169082537993592429535883742285773605469641816499561571975667086630053484615610481607354410154114540828323063415979423522312581043892123198778776159501452403260830201223472651596964966620235838339666632020622222657237820574536987467487408242745469303524148304939705586617187585956432674753862298079298546276013087722516262185174221808124150131708202746491529410081551136767836092217644190995905593597918979787591463457978391750507182891207419158233472346486169496032885326090455048414561248260619533701731575294942599426672252938750523829981696489420706677122937233445184367637127558427031733306965491943344491690467014859187862159917941042796271187133674693844524071881870879314816768781670118281969355302578866640122721420585397621898120047535517037998006951060566705053466063459778190429666841640563678258183842364784648170188857011247581038984459246589638123764319121236923001898227240801626944943086578967811805462566789858389198462170298281039947406060915488648194984223785514166676104236882805965465431831448447194078123442269596693423277449514247034811557615148155358336213944163430710067166322423302841716716128581610425186375272315221160460302253468127399412660906228534047905978886736406780977702807726617334357066114982101989474409499573892914441214885325214640089126905168357470921983537117141886704357577616231832443255823297267407003115103916389379244333656666589659236590319457620014086536812331438122638482598372624131328872797363549335009878600789938025454495274772322319138453860984817694179347315228628423231014145434508932770250608818772493911157874359914124260708090677860556883910503093860901680908679739941163657125535416635371257460976372840047122579979548112235769225910576194920344129077580924302300409526710952187895332252640620839101128562731396379575545641409044771462868731875489070123835240759181763977851824602341970977935479648919845354106971837762022465065581768580558380161479139903903963952344262310868421234681092081212628772360227330590377044918836596626180133790012773072831552953383718291113258017729089846203655043817990628335220508761662580761844758033723766118242157765757541672682291140582602404570625248701431269890196259277340202516020916314903005583950568705460111608615374169152632039089268970914815453721520386688815611165967593566693814167374536153891080748988090826936338820854525209480023191797979316707462034064028606121976390505672436023312469624798963473968745399806853950434468763978817089428144607454352705641195503360986036662643734455246665885433581397587429672596954804402700620496115033132013053151019343237755522043897260005382387568842320727826540526886478868521286834771047274614196640790314058031120028093764720482232583021961374809001848988487148586497668620530576819906497485824331881575348291695711236104548271976245195015188150262095968809425284133263150602458125998782894053302314010139815293740435725886172171786988109769280616086588011221769510798562376036988563645632861371027315919404799057726916798248329395438957202501682388862950369977470624264837856760381160416168943106336009209398763398894437696517023287562125941834860940887586492475853245202891381188101810583514922406627897338378182457849344375125783209813391155196194842824189705258948090639862341760536072657639430081319458130429641999871046425893955912368437702636477171887311769816356575293689962438750232934468649666413376492335574350669693141400688661570903902348104136753346635513034510291149658397946669991861172028977949005059486685309399587323277988316243857191401232993490976868214712501144307122080309587887996438154746431070381179288648059707890385954173974222344369093598025855071806566187601187932377331534682767231527050341918090763311633603633199622008526626007528852841294353503897692201410784168379600022055660612890821578006829233615575446545725249513574333069495335627265387461533438899198445467529737844126364199922000752112184176614395422641628626506695140232781904134239126555328231196671753633232220273150984167786645279212824884116102845690219388179866796425080034328790830011184052828772623692100622106726867907772739574336204817773854889682469392152327923115678239089363673555032031651970959854434064196046139090725976221085641520200047479665631704833230383239853776541514099400893950679877540661285792863801090613026584753469261183909507743108530079022258675130787733013116172372912395562355380314988291953562545565823179524498537230209583966887812132651042755529612606353290123230358648062205565026647524500170671495235587612169757995156530393623351204798337486909716938113484370990942647417142974993267463808736923577503808367535264556695433768203033495288198579957909420286420125417315000902120031029515634108246818890489855515310636376082540560802546143297097602330202560114664768411571072312838183762677061286216398971298918988786671762863366307954187168932556804130088557241815927480204534795075385397545388488349398869699367581106702078234965635937501662643344253653087287531141432237422660155667764740960899143220651467148711561758028962237631030249242131618838401787662259908069615760108559749301671721186777793143855965724748865195910242585454035566423715878823287514761800022408360942459794012503919233522436913251036425517650478340948953375530309944859625795248713171276523832342732750407997425689019645244489055731112005863006270036614592906337926454656166495495435294359253915448738440940389874692468441512735518662326956632858027196962067645401320870255102045444224605374275905098354062968804397011922646933406527949703900970087163331274558535834832281393395406006487897183186439171667009475303780437349350939733175730813134398767153760934304104709198760800835440787077030221020855663252570822442887152391472615488237868419632839002198633114545148319047603289226669215564574779025813946820406525737913248902896855756349028325399667417162838997031468575410372378614419385534956299438599479768418509292219442706102773302296401921276654793540487278167089630514466592325903801044200931722207757079036707763863626815481048500526270014376326195074218921287071099732461413943834117334643420174564889384091372299428938442589879016054156717306728844723340926657334791487027235723428910289142759300655444757816287714550510188060622806624558340871847395571133570554064817901071038251318993778979503097152363956257640005087099366343305622747613759189649560460138247261702243753992898080637532359756905647965239787473630198428019053438576727524922594684366537130665051083626637768975758951544588141674523021124915028433658062466581190590115582872470010188857165398017664705378848697843617135693204383891953422969536523951172347146188776708985750478030737707771428251529367281691781979190022605962152112605110612304627033333533403330368584063939982770442464451552596369780430248075674220889040758644637677007042298562819822076345586443556478991439773222020254410184628640054087912695638414135250625329556682294599952934224825045887100653375217089702558332228805119997518601492721932564076258828823454109368410068961381440301070750011639075092207844589234068876062487110195622076431578178936170005962567774476968823190917538384253209249850236450624915813785812188569985459299609245149402212539194914269702593661862487020722787677364710168544996772993982060629937323865414000189506232624826909695955596750869445037811638645038137420054566987966820251335941115660462941131176698675981206046278105165918854375911389782072079748444237948802871176293199202040967823239106029890658100990675823724186806062782787988986206299114020183221011367365128441755917730552977293160515490788345134331226213953323306479141951561466846185025329252276221553083765427854082505075179334805843240441562030299317714800091442314302454696509364901297173457058173071523410043543917508887077434445157043672908853848908782760038490433034547676280559814873272582642310557978712270599686727256391535952101036695329594570844028272640000, - 72076295849694720960244941167468012467789681965012076454500622009787372907836671604587114354189197085940405862177362032560389693423232351152540832504017378750068523347360817841205571743801260971867915823129723191703770772186926850575769965294444519823610436687271596493634561353381271785907475284256628659678970302039182733794058213100379998903367359604970956605324519824257059828265848983984611537230673829431502394081739226401084311526655655267456528095377637351618488030199616325380415177452320884651662738994775337575384342897408044816961844983420995973066863187378442970159740819861564523052154413427561007888411010393146041860434879266886796387840865730387271701384510021779709466218008637355241435640454223631178884213842164892447228839907992938479226100308667369446336911231287189926691653392617079081777309851375281181633273322634795643333387193695104068656613794352803106779351830440724309622270336264228660024404664507127655705500837595207977716194095474406607081123857639269370193576960056063256973582128004474323663206861662810381311194992954965705582480394729716888708672783269196800106639062380343403149203738473545974699512231859940836365694807090788030026462300326643515783212467547957604074985922732653496614142910953021236043799676809010245038917710059012979771907592736328196257044201675831362020224582310869719527260883223289088309127650616213265765355558253445089516738022523795721316944874018072333138348710526069538192283317967334562233172333969706029659938412638010168985493560560604627066717620948476859768091254368763848818832295567354877801311248425057581966562379599414874113630490783815468763276463710641143404657281992545539276827157588498030822428967148674112704768619315318666596949194727912367844929494821412223618072269289805140106166284168062436987154445518001708666195077508996500438735657032894303138950612485079584183117273590327275760122918735753966002199693198719981135855876927893088245255363230132443895790664048039641019063689893631058250417887495421566551890844632832976179395985258089283904000100782914373508015119665391346286599692274956184321008937399747237599077095440074319962863150849097884730034654456573556281914777122191483610267532767373732611591496330292850909384647604965139589415899956009420584936946430161193364070189961745045139113159525786984622171678896576823235040203553832217678994486204130014870858038493722061523751802945663665865595023273455935897959155389398977448252160252329242291683007025970959685394618660960602602318049154398630243818338297807061428021773070567972490599659458141081041982664357377392487726613505903174606429794030307327994006900890502048495917190228395914689227398700365858433198510619307384198306581486040364902480660490829538634445127668942991113219937190617432527423821449060160737058112009955077727980606759437771763033014596835095169942106694379871971894303315393842007890807814954734324092340568868314199691183044822689910627674937428096128881891239691296683023957852441644798341878112309564475156533711503217824142270002368197849720563354664357592154840155619408466220289705824819474002645753044189837285219881099233811948197205175619451578490508512010888912848094420427207664030418913964478754358030086722810738063944877803335043235905058009462202813390745568988200932378753546619439725314193698376975736409501741290597097414093668429639111205543449844009332976113399193659055349629117136666914631801366165069772702809393570992817033089154782655911896655132374971490400268290780636844345045813948463324661241220403543797182953470821876890939417378283760545543503161329959104968892661371341613231162131246369567763009704224074261847744601436931969102874139992476218456705759337219100436370423926403678663703724054808755985917234602075501001498052294221844966892739893548951408281014552546930240674618715921417342944303659959700257949727646103191991561890449277080980520931265183968341779620687845216084242426004447293143913519425709536438053393427692735625087780001688304065612105057928065744932611890981811350819160398416877472215741086094788669556227125828024157749328740535906956764976671885573219702456838828508486069534977189004182489952460177019738857836053272238892469411823280614507307722816594137065453036972306176207555673668448800456034176181585771232919082115457103184718381438769714164631587152729860555345073957902781169485384233173018078563387496968158641819810419568888671802344960290408347354175835323638747025286023658721482999332343398090128776052952963549460290361226570419352219414628867819962526964902729110933688261251872778050070658814449674561206395398543840210112168733317829031277201289521367154646578153519671165494674632043517386435470967974022500314497485627984162828522506288981138940944681863331522595698749223979028700400702576648226584529872319329762017567872906998660026982070451990470839177746623062776823771279235622530814790405130651437589953029950570654421375000492694028992094636377835615274330198347573718754905101311080705235746730211419858651813181478638146137800902118766127660823793470570479308290288766522505696417187386022559096232835958371558414320482901915200822841674013867078239124204053434846886121463077709700866146106908048881090583553262320193353945124216353505375414892665756373981320211528346848806313977459336876556689951270007105860193337495174500800444982581196021635972211512668611246604245200444094326554487327865223527146923294216216063764406721109244408516480601207805145579542416880453827642882156369077097419838124499602072998678984390455594172454256019189160776951295129092019864141335998719266999722913964232561435893013324911534086721482638918673174332758754861350682198434189153029517556662856827177104352687495537141210029441254621101506454253699492000485520423481254348077929204813628941132580455655230992950874851403045071399999226462847796882872574458617240214997507701784801799086935546878546828269563245166913859996904139514093287248168050693405964332105226108743852840037803759281800852135612298905132438196668762524357293762762775934617993235745912611059422218104631148507736613016585748872827366227938014974013309736549964867895443641588433307096436873556581322547138091302087558941761084808972476305236702340594348178263322860193169405103149132592332716725476798133179428698115097373726941207572845255693318016068213369740079441744728700061992946833436068405691571724449233853915671701399714881170245267521016064835763851175688171323869573711259051585070641353744832200421301749377920261947670234909084596277770850183843558415746198823092936259124073142470022973494977886295575836874922936328959336612820430080371979222891958002231797959482710301595803756524042276613018023451511525873083653580378039292333784322430099454676153586745568985749045477075957485657690050035107127371586479399296826901136201756165818544674368579978081864098528750482567158248329419666949551086015604760272679540176206888383349578718638229263435032513217977821649498251599378512756828469046057215663208663270629153218553432122844836564332877440812687711572705031276418031097767873631800314935331096015471890802993725526320057594328332450718825683353534636431502362777984272266565276825869021440242441476761256049807903124817872766077214745419395771213692975344852535500670151957376700507346312065622266790821277931885283923787626405880397299140468176969099364102074985660311008326364179603803452778115887994566214431756390360826727764493250908238932393603581908715419683719400264404414317055008721905992601822706477886647253195145843534616946006281894615301441197505865498715026654808794811180074249390972078798612350887775847035976890703704342521367903482131236812897028925109138792741939931991784908107287637193419935258498322180696179565372708722246022266208159409451865293220831210028928592216160262052338913994438300881677460216626669986865440387680963216667715558848998592431344083866295880891194387338247508623475409024347289137960971822081558888442813019488531883684538101283011410909777509332556369295505693280941588914002925927788015144195670109664484989317449783321660741607892801100492463069747957044681946709984494274091236013646535844075361692481080007076803652133803263105017541846809156681341916443094851104993411665766863893905628638276377347148242555248404126386126432089758805412199880509788269739273616061580493839780040735846866709891449635256488037692500443314149451226055689266648667353855377296207226655475369274042508332852098579281640776945940793630490668673992818956593284924244897087563063413553929694678203124402177027908747263855155960657348476786073734573014406522906539992689685805965696362130807906098883816252597432561615274655104329086432293206895456914716951133944424534943925384096695607562723338853245476291246182036692400647309325254354589300143490642463774648282329614369730995222181859113750641479427523192930980477320062250733656274103148055640827174575996565381543244476852558106684441969468533094304487023432871949554627357364728316530679205231759547388339133941350418233398988501560879845338176799272755608807231046837523075940729528327721729557707972990457700400149403493724468277573812311457477826753166962402023811096644802068062944861635855554973242397388868080019164150674672645099353044510383240833657487445418370567352194203296857195128043250629588687272783920211286332259765156641270295053462594768735636753966922607134541492716224242789258884281247508524695814364381916777159429696610728000466079446788596824216767520349473525802677059537376765922531299982802232457314764000489121470926875011170944985613895922288731273739846196599718741181040070968986922985773320629633649992767989484149747013321872997097750107711195492181737168185535614142327724825862401026018480203254686666762559268672549533764074140065703522433109256156592557074751923932560222505836956675936588486155502396019747819145247355855113906459873736004795744329029600017830375682118053764122958747551908117322824479259967057281448011895493749685865624875910523726854541073916745999210524962252317525607500671170681737977915317464682634960268956736784797313119552963854214779280270014407714742089751912132518467390025474254127263636847524835435510527009236288566372946053367195027792459607022583281312161951320284569201940372161131120160072477217786949071232659900587415250746280961614184544911590832997070798518193336580823402026633642008958264065696053563939696537213375959650592622170649027191767040000, - 123801617186620929437144596339296127111344038300396242442286142872394549377991268808555231020581459382581756716507380255704446360641513314634332905522095845182564968421798733478403291878388810961277059372311021806087871859201375606762056107409177994994403320437254906663449364798258748857663778420312908547475906431157161019576763928128602712150696335584208499211962510580494668245679075802747258514733269951238723582905325255302569596751250721834261630149484089172576008713282244858616313126844381357361254697492276259754170285889027281167546834651259360056127430144917890169299478657978078460308341474268412886131524767581703345332108784083846523089241281508413256200978256878117209671843532244701042318137257356232590208379949094864897546786392924081813124030149191877876643680403332630310584045555346880514323911498170776531971652873573148453733290670774002559343828727728166697838943572941272981383769743810634327622585041900500554969419886119304118698019218927516278905105270940564517304114879872478414232996389569189545127705109404057149054447631452886888750141832675874665586267323170296210980172913041267826093152826229910986076241127092774773848740452986318175789930233570319238726142579806236001859965340255712008644241858075733708954550392927880997397135629406481345210874303803547773186853346163254379376457291464149608954908771968065306007020301010376199178395583664684850008910009787543063044553580147391107741765872569285841006462773048171969477315883810803846990172912077155076177158992430147602766678131475521085451307346469514076708697210842228364129036080717642076986452908157315045095517990377491232534654094649712197808886088915144483518751036862485861241426313345901881482558063628191923259586425931005761384301577093566145719368972265390353158761209481064445987791708718601579895021627754133306302472177361316558692799821727016169706784505073271122727406373156767646707029983225933377306239330721038376155365630277298674331483647860015659007849698292672043322605340549648965234385612899873025016035460264551687082812056451335939142722179484351174998800427250042166320047328687677810376352112486566733829364544803127736413166557243886207636511503632035432612692354723195192294858498145223859531009180743334637946633579341527359240769652291860430554572532330781563586545327220032274373599432424703226060596317575637250921646468127356705764168024193394678384056883829560815997809358575540863968311897174653912754730649220859550696828292757307107420680520885442835265509857818628659918252536379245838494671796463627499136043695488883297887605130768023874993692595055700299866683871402336322579300120552019669856804815555552029473827583103877163722806734491294590243015078985003129390018105539250925536277121076583468791814396021885277406604936450168314452245313550918371754413810589774824610980457036731331542125970229652619003310696038343336416927308249216683978683386459951946860843761572526690210082682502172488301551465795703374317017522290044946635601079639219766074857703619428199593451500009080230926248866456714618769240545186040850086283713392518853760784797184827655262168855571389364186162709574131854085973896951118752932351261382087622569453163935874562229692549878517787859519262559163828923038492630488519996383955978014714073428793703983743788371145939501004873114464523687045299281696958908934534530196121103558366530995533355411131939031390378940438711524856795562321614391575385391101534523727434976272476038245151759847138460934322788769835887453759720339473803724226868826182667111067153895531980718714653967047070066668766362355035410767321788677238908360051628420703196184809201234760914302231915681736025818827774842624913093737031029150053227569231665805385335682240879485301575273623713976792314402022999666967362134501996006683982735464000551459666048090240566795679974210304703417575296262572018921004728039008998247336097574551862697218956347313380185534833050046416188003540319807368970342656111410829596538451724597620491750883828181760717584211213679978022478415119336104174624514058126445301844499152062671451061761004111029046363938829903862379700425819342796650505283003561572931600117081856630865579252447704557860147995038413337844301358105109160449322549138448410477534314229664168686505377692605068554133743395299727877796000288765421734568165952873307786776469387890049571376774746933872028031463414834906492137010899934126706845308271129785987952843353553933636213588949209566319237594234689037861493775281545059489142640957254078582417978458806454102349979637093293300636621452293096068602711650523596818442144040045288804499812738095582331216372077718757286865887402955803326941776003147618076408810177942139705648543678921691663975788328876232950495689945940841071523230100140845014106687629496174051363317987411310213406823804464853295624554659702251683703316341486673586416794494522607034451329560303830685759282398310122590130468409781453699640865213914353042106619721720044065010214735347073928013149488043447246617930424957464472589413840255674660637956021192220505085380923264984196764540282356206615400733687458131648323104099443771125297082563039245494850891428226940494316914252547291624768439513733242716889405754428388108333731867394976313021350664966478729695707941904605642362650966542748319202733155796758897332525710285954707820863979529278949900138698228592727118685355551898301270541634229512754997113688434792682714039643529439322440564496427274368628531699787113281962444786647491881994078596914496950854412049132097026920287605193332811495890231145093103478255094534364418220220352365832574488625272491852024625849245531075883633647686415147062607816040485030031036951449933544076734112457589174747673752349215892671260028229609578275523403888000392884165510124610651369580755150849967954657888711283683260864993712850365751682296017941306583117437707419342792527659979071542699206136347998744291018571836957973128336029905788606236870506913631371688252888473577219426309055965040163523224064296650724425786543646860778566630758593151653909473524005740574229518243166218708104660019596149596739234664705168909584482310349690463269497698275173560182755458931063813090896634871110569152928587827760617450035562214256266921294714512484940776604526313208686236486327226864921177596065717203356402505235841139365161562473512112405572532740656330569135569571505142637884522677929410349092494236424238667700717805895243563244862116720417441306968453458743164071223226980713912660776553251794609275275229356505570648596204670449754417487992255529215829363155554117546427891687171006634226020655893307660796583807772620448776275573724040050591307131591885649023715269768080406404359311353504704927773849741665335610495594346051024779864357963300605394031171702252886951433105248177140818820771284881254886085622858561896755720013681458977427242127474040174048085897997512120188713908944190833888997738210402689672055550067807291018694133122720518074358800225449714617341416124266917825698266433858808723765660729475154167840412342008912321357917100757745139155752006663538192910501002020218799645308964004680839797016552911464407922727588606664070068258579217299086720420579933616014849992660776966048509057516524949720417411787326352043843251140985415997461251235270260785997268832458233723749979423683827809131390066983160087850429890464133981792174074210146646243218086784064539535213137767434943241422149124929743705762634262762042026824663501640506244093569462399161642041344171784803715398919853089279727148240982091543035481119757128463489918695460265663365397760738086134249430187990142487699815190872003636365146602350056005406745377060015154155638435492082052440905314416045341926690680424446612487010925996518449997506759411442227308509949568461217533464303337123075153942001016736617777995931708027535924534546852547868867332052901246595881706413061635060985475867332751708424523941716297594058648939562711107661868542951571640862778455277686181013571911909968529976629675113967367992232996060805179490685384608684875560102691433663740156193782922111241426556652713913645411406145297181399123852852498408540806289965287034472588337070257347893577307058273104470666992359470386530246043865924280698663734913384883823386475439674281578374212483476031223848173973945415247943363849376440306346456623356802975064025135168205714638374527349767131439241954660512236294389075916777814518137138712517392209416830306833529365852218033268263330478894729695106309986761070191406208408332557372740427288307280743981635977494628798778927545922755634539046679216615521425723016109238554757797238414488313820398154027767370414018373903365965525051577843683651843970934913333393461341107517581279578547235694290560094526030951952015744519459757453090855195251720876322573943440554933653312356421376539920902981290074816337570757954060969006258254125601262150607803777350441859579477058142403478912047684534531147752241867295584659838263103253497336764377609831632876364685958789073773631133164360562449300082615611848622736248624046643521793329732479140530421618297981833111764802769175411532601811587777784266499930570258291809221076169222221890350532233943492402908733421483016957399708824695109324311498896957482115987117886954435830366760216042214365624879194586682308269125304435062071243097056506173760933130604018726843498508832848770938444413152477681753139356786682393595211847623299815939494425819364727529107411170994346105992685968157840957572407215639395001258803243701583799008853651983931222184277047660941013723822967433572007609032348502167515095612677684727631425857041210879491822600040304188546864804751913920314366409182972763631035452512716436402877575879928003143453726944210717356779066887156306305713337979990180454180436260451065269795551388925543802022332348463252988351151108641065631134648204941207428449869409755042136021752546603905533776229439640830745766240623644980088750994071446332761819207776798268725405330531790666242798222832181904266479945771817915142991981524832275641797070574595818247099124645993031547374519827289101237444974301551539382458694378734915728685797432007001020376862479554035456562700353938454710743712653247598387007169562606712748090604414038930385676616560438132646384719836630600456348811814595106014316440953329107994505711948969609242702396235040166561579854294092565814367625249998243166140278844670888989058662400000, - 191215213735709878200658991247943550639786992779762472700258699201879723502094059009030289094703598054783287588427455720812205327624471806176933987654346771028456295491527075080422247849352669262685053830141740393233105454768825921994586758105056653135455958830349228595925180191693193066987308824668410625385498573257140976953851805898900926578591819113425408953245022646461710734110724227211349498314474710546118205027332669822149114259528472201156890351161636073130918708913871736691289963441362510124748361844347982357646454508417218212379342214892855940477808247430805781299990887981673273254407696812132060730965770363667199958692263775132409298130041523232001791175393663540948263482586433696478304303917690605722333882274289895959285770939257802941769043833574287972221525890190966785227353388401860945345479557134377794755695748534355890334970353943420323593267523397358875919111206602743485222483960741880573332581796573035204367300311724492698876606722994068084495216720845152791983024603617921357347365057028515068911544245004291907570268924363510402583968075440134470259967087360931961064227344715829451239872948578138820043162196991031785894483121146212430511457917900031882249342859698513034689146666557141301740661956377583918445566311369290332008829063172929945082249601113858235669850875487123777354678268393940563845829609105903561566471625373860939000967806513154214813918261911423793787905842959610640866292589611475609257438204417546636269989854049731526359868894932717711893708114057729538927322130678893166027303503370880668418065726970128802281722738646957980548067402014539440861251338880265855356876014254920352707203781288107531684301410426953233589554145918133890962942546417061870573918647555305215347890217538460404057524137158972223116096997406123797969997693665025298633280331388185518726362267718853390393850618068989260157848780111046223780581195246483726157938176291968335391095387577031919790713191515904863700892571253844471250100152646455263235239533810267434434343304600774978523045702222331550907469040565231470240882070293658232715332169660116457497670930959007844219191116178274849613100692964531302497773596897598760513090867631678272087512419264676637926777424251094813453200732649764200215539984388912299127182607705359672903039724472532237156120025114822819347842416079237357481474459052239096486271537064516348440050991590353589841054292055805162936623138595703215236323048843692945952467220671662487846400657724593452665585802388947927022062616365757879401579251410032816603330345981988529040627016598165954227838565309364396827966720371196081250714442728725088780358497952013908032882875169770030820197584070664896157854949255867719694997381773179430872535739113717317612806587467374191189534870304752567332229463623905040080566551112243773919783276977763870461695744551284391156045617087804839060072120270862552660998930762154187522541140083855914627881655017814281572102269997551604175301595487241086996771105834813621332621917861176347250226251021910569901480567382412597723342971687309495827092016798911645684704914657921406502146447384178514849984028318155348389740327222081529888975190758052439388284955374422808642713185833112737197673284927814900610034795572820362344100490364747783881811323739358937534961594231227992499978641303575154331349140964563751443058608166050452497362621516455163690264866611596727756916837696913617501066195047146951006476033444791282494844265879358025348517341000788248901983410532002921619424592971044691353732082024470876143523660036454894557053638310162408747365800435378550862342179916843894723446790073339733446120528674933521365205869277551009260071474145324560124318274155202775122517170325347545045129702734188252596826371842772448008431834255975226928710916585185829158177169186903868653234756248456390452934601288289240319231846551397464135183476191009926030108350663286973367724127869984826108344066993812844003973186514071230913714502442855867702129330420758300273114435154341201304141853338677331025699765460264403812720303787669037125336423051169548465739293360870054180056583485616222025236188076895577770766871202567428158498699123097919592980619375251040847881829688632120734082962982033218788048748170204392520220426791373320265517755077674312523984246649794756284046571484990298196966045020602606351039421394323971765528137843078347965438005754553140711807506581699649917772170562758019109521363678282699919220893317111277081194365956747382930858458981337414959154033889021667354619942084861810985186560736971007984012604354245984776448250597791640192542466916110108412815802861689372737770883942703583854166161079157429516802949908662681106064143359513775162036071848033637306169758512696707672786311134030417464455119863686929804790356373561214811143330044685116618669522669413440197475598903218528658221133707099573321940157409082536025191841005425814099816323368936348100317183914333014292711868534229222895009992500890667732948608107377704021489477949978777566136238497191632904555824081265401292417516001919481072657507473797909506963129541255846201260689559099429701054898057872236461124699877792695315475524679413691531172055344178912992759894474585701976911166557252602221890819807689846536926503926783369214270577083144000866218912523543981874053962117767796232913735980551303539660222808564127575807586884571137370231889664192737639387173254049884184163010832176629395661031816334586915881092214863115726068185731014554159411050669471579416245212657040315376508048727680568794398604448360145120723051311251762253278420039814621859996381005516737566213589460609194619212007321581580616431350893762255104967111864255568368478616147843547757944648499332627501130135800795095659572355191572268606055610830177428389473835622708846895210176906105859036340656557318913636649182572473319485961047152099938016394058292814332666747776034660732287553001035464358995681954661267566485073047289569769678229692198238079838354180668604832126813199106462763454290627348975654933612647112168798379875679114768512772705573170557970453302789430215459658057982874792947867904309612165758680745681789660619204863009429840503012961479440201526106069420250943900131801178878082145907445197529076772541169659704820201365926100039257888647829125004569323228932679523888595534855653897820932814400089077478167425248428408974167475464278276184410159829387431144409854740603249075541297631030945216693065898410160499498840142735560690017256851652778568374799942452737841578670526563835296220663302411976186534559394883958974133040078556197679868268696506591409640165907526352267869297291106244830976883710114561885132138223324202759595779641175067195878160229087096779901223863550930656172378465558734718484543136829668481411122953904750515817631821083646511064074268340994641761011628337799917584581264908218056504494063140406043837438519313327194126201079723919642904201741466550932631808385215637556641249847351163526965574024447762359398745685592590822681335522881825023802964836740342459114125984180055767112007404539869386860716797584379867156311888573881256268052365222378771028114307765129445037552384048139822004715041139175502262534078814825559091334783908362197037167867045258234472173329522683817385270562184735586503565485243759158964401264744993171479487749119851021039267939804008884227939776462494125495970747730542373849882953411758241223710653165739927504113648017488542855383005690291543013016105625133669832988562598668603492682325827798333614374071508417978903641231412779154959219513272018562309804454101392669402365113331660167761786714842095902902951432829802143344056531211571132241918254594462038209691195645620802129797403551886669122243469679623574118156355068784477409749030585331040644134980496746190308757660693548685222132744570277424836559309518725432123247894511610393142868287148689540614475690799243699353339171079070058210484613593563874263972605784446405888936386724640786930655052958434955619371267337809863835589903604700956128557259120177424064572193787835044113699576538188803978507120968314899659122854950872356395073911952968935622354069667148816823469465962338427552060343574591988793508727462576171469245590087325182259507682173827920368911755041791356763303825644399555140446616866291698159599825325977104178327444705188159798037762314969435236773126583971463328024788942528332305925630398297148492940212348980569105255972577072966991262629854284578680437988351719469067518461790882702668408871450558481321802396571298184279804100893230703098338659770559211527647680886224187030245822572386024634867847434555560635908459354291938423420076831607506715051975725177010053452952615866530766572285954137314077949662399022019237132227575434304555905037409207388070779901763050082192227064872595285241864132551245919926638569855265344321860300937652103910102307000968085097545978482934140608234861370574150520218076513006327281489522757614274289801218187240905143483664808241125237004205279079020279975470968176652476721603753247202810898137518377845159039756530329140767025101018267038853090722183997340703795023615589714681949700845140007274069046179222234823624066115859418498324138006520431946218023204994469486278569784825132900722562895107961160618080308326576095705987475931509537807687042061275003390540477211419885596504900806123038934636291048035803089330020649042026315887694427875657485179223394270865384739022819477454047062453064223637496969114631843129812534162365752530960962810595948435390751753278672931691233635591953238741487508811907845505903977197681397808337630760808894637403896909920636024825916715075742362317518722718873769990503103048016689823852982020331070026206289038710722201729737708344385894073844475215357095567489402618225799316897681792394363150991793271614704322904180602118014913852774910156563799790513521767894571174395970810375076665667804519712878424062605544738537475686282815365147065632147678628264991374748398967947242359028134760517227128125555026589049011208890471778910083126460873110543099911816597737801487699214337328409259012411723339907609649365107777236451940241352006266519568926686291822663719289739568025419670116636560421427105488665587374037266230226004266087314928095428380785729248362331991270358684319530938279256825608598726312106896086218489705705675072536705070292237458680376566534186467987744881256043456360054909266076631040000, - 266679926262189955022484980874036315248373201745850707036048236292160820472170471924950526761918020411510467043205587141401244938796784512418337518585650609619517337761016218075803860613400279182379073757410664741389863657642296781087603895097986655016908645167499723569112829190600359884096027266868559823509165046449777705766096547096487449743369753468468190010286039356814608814333354433994874418925867612192707357999225619730567232875782811716265690886006481667553412678821063041268900786602128665870665159489804227198746447000379510059209796909889438069742346641920447307793983890009694222334276452876328574894121174798146388386512618861639771667024572908465251802782577006368403410242411394090795958371419916564098395695111138315218953449209985168367345527528852382017365372199065980001487875943949686145823328131166128921755110771411652860501071033214169494645490303140906703018239477524108471746548314681658079223209306607991731267784496673407642616005626043289361318886777898610671174952948963323126326116415409478144515156628866040211666661977115857943285022781047250703255773351145024351563278011447268812481324093092059909624539780599627996440524538863933210226756967313341537211014162732322463042327713188493659429399092747693278753043656779769575242306321245551647646114243477133480820519714723183579685666580666291565999015501047449511615907682268841869960100607134296031353449238256993662166446764890106555452205317110554378841062042781768819766351298994121431394415356498787061305620343888094844351141617832530423925928291143854710843270961943764288319825525773201934372503803581442592289377984453428539592151854202058398591226868912446799899953708484934424113659861190691257231017796745047503717927091985875059664156949424818660443031847510916442649309004205996032390407643818420582227284131371320086616914154792157737543755111868105423425025703367580472237681810036950017346421306334507196126101507846526402849194545972043630479727938528631439009197926918719412642936313481154171097265286167355171298871946158311576477391980451112558149691387985736811132183862724639920100665023008504304257380369509570794670423635455122733259302993746622388967258255946140164637158067250229395096587016465920718485368999062223975814162055023786207051946532632408497311315422725670779003260841354420560673432464067143602773943453267736281204043408397332505446523063272359701567337296798770938294781256770055513317441274069984699873083406669693460982598218185925676979488695478865167856936412308027046208411127797892912970014629555213471476576612948191420596130486789575454425417027396883526947973788583493393825721190408433141714319886428068424506130372076452240647381583157549077756639371013648068617939825599747835040173242198838367487208746887807498481577807162881570398941921183019619420033556377004868931066096812489895058061552016785963913751565168716134200566861114484691818158132363152174345834396199646236603662346062660243271002215293489008676383312044257662195642707122424072614452197927572526622633722193410486086142034464970744270062583021853843391528855947854369205129634229063949422956534755880973597778203369951510894678514945063609199606095008655525692206830053106486165683781547136980264341634448149322103761435463721436240065251438254208057433448001342357227818098064477227133091039815031436651449489522451465679387904943225189905666473735733615895609588835105733801360288501728299984044945340021786303036152126072963501645387634483403699243762289289844084179219799313162586703111603426582738104675867715031009216254024885513849931663243972340907933429913904014355888273656027712442099912077090184327332440997041177922596046620537161981932631854195523248379877240809986849151460899959928120517711248581570152854771193864178329099675506684945118680019107354530514661277034491878867404558160134634401497655106661098117361836710271033829444589436699405818418700566665072703699390299291947400989648460179517285131271262012988846863560911442509122168981901435094460023614335919185407919015921704385546924594463620218001983711440413139015702814578074460586057875501930952023540844415389242163186396206699308665337564294838490721962448166317787628911403896477361231662559078762610665967848493951684123994624055014698431144360745115974149533765595655324946219658923584560502760717657420025100984666915392108988184366509331715546820349646080959547493173823336653617639990372427048716553883260005069685025125896687481061679687727464568666437333781189713722292646340732244852871573409634850335947696599537620554434074776243220228700689584926632789846358143306107941996395078193042916751939422727330959648767040516485705064923582092322592104054857451678366238490170997319742596448078246153330662328785587940786554948322814388461155861622602623511547258902176075692590134423629640916043711662408161756269865341053217744711117811625176695622882133480202739336019678927028717392531672165928133643827928976223833177921819642097788633937820195384290179297986081472085876570708091203973591426885801957330321191829850285299365510193921342172144757648809473755803405413963809388780720773143511488872826248077328867477069858224831180455234488441151214475608009915949852203718222123907707849902585418172190523053635521061030590687370908643025913201794815743205671686999555788897414211877639798321123014790528333799568106199399796183319892439466161719765808689155213693783117099293919434501457098728670649410739670595771739641356738988202818531026926650105628368975358897948867279431615185405505181522656981014912399302967798833818356668015088137049440262177209259281201284331854081396590914081810210439714558087431234621106649384159390475252488930167478617094626651569992305274100675533482409320567877883759584353855236512673795301676137019403468552424433932663970505824204344966880305587867234686779374592029593618241847349372184313438686501750873695269170000069774346163080788438692305218955292364627799830519408004642843901451046837771499648524152909666248575608358412228895326095045441821639206306985262632592683539803598313090246216482945499216504748842170761372240887704255245828787380152619862835235998765128809689764126200167846171050584719029626172189924226297983733602437820470495507375517098684909235173886778794962891219527269172380486874427900335518275868789274850373896155299343097590973201690950524489189902064922414638269910028756422355362841191656157445793332065185210206741022148796657624171202650189759736521447027912011847361540130439219824730309405617051243990345513942275297572037059747500918508171732187159079352387003066971649578468444170473007475115481851682586607408268843335238207550732446424841364462372195707856545448737394599874664684268351166603500828494302932528660298211685389159013729117894369374028852670211781426185956313563962120888802526905172802371804019079282353748245644700899731820895630564935279049533943090424882627475337447942902384905637323130384139623161905111107355981450557224586133446383269075422532370136248147102504753017360114835854457747346553965036054735155258858762732086956284846338687702175821586932148518948599451670855162537291929571869612733461808908909816504851202359020377230275043214955550170749924973956627057448953920633450828205877279667472582976915870477699802855368566789798976744986805761120488600946075704106940061975186991679502141465704052262277620898505369360294338351164366757065956765526512133016065096585951204189904422685626946105048674077485574722925742920156116388802338322604970115626020058893882831080416920494095713056317477690489941335420097939784463825705388571416518408906853623499876614082423459198002311448802006847592746467396991379683655426319455585998246564722208214702818229151014119958183242268596184149253596856039920462297396306852158882300680950502755444313232547434992576898597065475366362186317473019098791986635275830400602124250538066244422238769788137869246594810752666484997745081031303669165788698618280306188216352437933406429237169378011516421507263954656610667155285022988174039695039339021360224641999918854042563993191152264912909057795337602817009628892312142563394244414283483962578061930105744628780241729414343995743809609875914465291052803308014828924895888543550335343203807352609961343357621275893384507677451634509738220114893669420681646002079033751266787073971086025903074903043456214697345206854230698413283788275299265738981448735658612768740690613421255950902820744739526599965559917002597219908483101087990649749876813566062436841333592532072078314405634510821349062557295259393236751961724868346656338350035209135313966217035811849339136695717858662227320398183997860836290702661622906692548016490078454101686554737072202697449816063206701819210461709687993418999419790524261713979153245371983198345346003607264401687197202375011470631226694050112643338094443741952709053345563240478157349342856116575934169335034345820500657490884066617712000079804494998262235562001314120779680561511775612773040223852074321330473258992373834139579057986897954948492924263839323577027010356387754621122927367363631828005677565437913413403629344096143359029160384712334593558562480260168356352235657443496981282782286790341723839301988969212646486978301573798125053518623223307019041691752427904541458103955638013581190969508990462810987985645806466122574315461320478131549522907364399759602037809545694561649366596069210099198241557312325448728948168748862939863826169622491319230742459937589660025020052526811329181929959773476984272013933880532113439167624052787261114900843602194183687270987015957886958385722453469604531618473306401994914764019080876418989478137378483487387185925400082893287579667288358930026646169420369217753359016414332227795200390164641571368125552858682802665631862944447881609370392885127854478425999992703726838016060305129671061697930735012326405126570018923379847045007926193834383949592297575640187928093433756406998286008417580691648155290290988682967176926287067165000996761597405595517703727042589437178908370278077647337463090381218349826921373689391896458665265925053370037319688659578990247698449562858959504196574577772250957563272033912243092681572809228513765447608209485020406388792399465044704709417144008513412894618148916015436771345502586202775971212722720479041320762375617415713242841957503947557996479571460692663262920545272799984437166080000, - 337073389830239747405601858465164647963945299199904418298999237499992435605126363345761250831764219440522301175379555996600755122605153011018251995862547667449408890754469322684824139390799443674235752533503968078560356225871407663086203748546022653968983449942412196941145444936214743319437955919211617730187537442201769310654885687903683470346170378718688288025733904990049694551834646934012671699896956733373723852165529459372070909147895933329382082176499523294592924584615282190756967491295343474984590593557460265831317621483194925128838898036050052499602550418362335375786399068845162622235540370886390783451199844158193667086693671531334870601859607376406669451406828194487096464482856164871583561100291651238957030267440953877340978013015320879379493277921348801174674177197498232591853589636227862174701310442729438398948005989300593690885360738139430468353821347624478455306985252341877278527290765887411122878114374704415347886939928049240189268261172598525200177405310518486755625632373080869760083298925662645591950862862440046873012002815770717011242778466962106272221668159855727749160009195302375779703437859212064235633679458585286222574425867432449612631629793299677817850314719133818361910725038531366540718503139520715547603956047490243176067303446127430570369892033698148592623543630594179395791104728799469517643601197010463307594323942648497623958133154345726198196199766024847285150669501942069319494568633569844411110947213817892335794675816283553327662571872443064114254694880046288158345732444127938115170074797332769751355952958002962859220345023697540132530592796661131590389274995658835015144848751594992529642097499447974185582762671245796412582271019377113092162622974307029913420273140038260894485188828052372022833640886995743109434209171325324858913678033858849373716767069349084231831580867932063269449306709116267119167045350928117166767192293665203433861028111385473251771222801868618101980754313885528183931086771567537144991203340563460245810281755240553681197326831016125873175561824336239143766181421626006841266998091755075839132456656402861259054789972652462673456972882492860551147003715826069128349142488825854578056527191633870491891161768238765590107888306786475268451891173146471329917542954732224578038609426464629147687325968300080674580381687296900556709145162359229802314074484022550079306156892804062057410460775640485261006415588725936939748732134614787061100553188460512928560890880751377948436518145851796143692139971500064674870045572198409717206343098052869866799006289864041725269640535212382713245996426312136283037326294613566102720814848935248545272284899745714621831634993641006861635742436481345256849137856187641341856420561361485644161854389953238375585626134409088910427818368951712315015093800323383149701352936382364846370550013104044117283023184427293158444019025118273336752548123677942432408454874591625142057737950826440024445993802532930464161213334562741722290976312632759122226104790637321562378887037776954883867120471968599550917797590440969132830807494857554690347208164649400322172912587281044004286583938297494934434877397307683302629455555133966625696776792596153551696457372100091550359122655128022666843543182627612917024763795242555258207754983975775677881938391601364954110369150781073850884266324105382331426136384957599857522093370719739760226768434691096632484186252055668491289819558081835776874299261574211058227074142043499139600851643359387203157455881590644758620880499802562156751755764304812545009254958194053154364782973767354733974110041562022540690419907501606600772693156374899881948722998486337094801253046211925357293671880363340060597739213960526520785304581123259241568742722966839711954686566633651912038311958884289918893526212606788377846603091801274437542550888531228487478913156745407276708389026196733999362920872395466897008616203306189739953928487161520346146210314274373484642810152265181679555072950442941184150800643060802759431087700393929214612390743319089764170388629436318472942483584075931212542491606592750162896266589604386868616320420196809946609218446213581174278019940631869709568564672148024979148418456415770040859409877999553552737826490841354002306194783079234751376057643068654243870055440223720045688499982430914895924814178351405242633840225952404820314495776751603657975074440173079678521213476542702716435432427556182600199181381952431870593277228873507061352418637738624018023518920111467917372295275399210341950341521235151760405787893470590619262023333264752382521551985426761490908335729046256639632786127877589679376430294298934364978970603189162230674627770045896277142664360156172468860443025786189740723512873116946141711560485933978536274486928057338714015644068644093340114589534735650538248060087799834812842930572087597523353255664203224073974913260887352771856947659754221717054049885741834493804076268832139990515421527374966608596349776978876773262215382533095242155143262586127081131763115932365127875549888411729051484538380243932137621770302648671339685723971089227748362867668338331765965500380911645899627176843545742964896262287106133008587195431607973646732058457840554313363970004163666376408361664390091080916717998522771439242789517207967466985047128430626561070567589843645092198210169658760166666073898713979066084842707930813547307136477586701027978366073228466975487453851626889188604444145734537004426782079297392519760707955501634298087951251486338136993668327875624193267522891069520841751247008889797770560370669775565734919054432251295985237119296397045173140203756508742156644540854648104394174429072836066712983491868870663311197690598587182653668774170324256683164511955826925681284772748275451688296759425313653713498178152514157190213994608304881124657738047980946369902715230167338772476382335332484631840251682173087237141523897511835044171637849492586304457286711673530443311716226350445041317013704290004017440766951159512004934845309578883881219001222858518843811223076911900133977504300845428423071683766910240302444498584462861057061781121882927042398942957794103855226037430719934247476877678326258147735879572178215564375346376474947885033240697712566996796074570894692014118622165251238603610547520023517975317096647809138102050439259754859555029512232677749468891283177862401877345036383007265786897889754845310905205219450811956756926921544270855135007393326567512263183675442464468426306096851153321887824175441882537186942266635965065841422055275938717860604061041273981909897289743882832335096306695573015718050900079561794610296132722560593790020465560603849928465382432929262412846925332346580071267897825456024248419099148487814257890037517655714068811059329445836152012236297307129408143292684744216989412307339741687976513250403346123660764090015137374717631345248611728069806286954207527092784423783123859837901702074144443227339613649722681322794899226213697412346631017780286382844920957998186060771604525235397088559634327252286539831752337014346237891354128028040895453652321218720647340105615476501162374850610838753826012005032332907368882024269324661529223160298681209834121553708518013498444655238418664096655933233033387026245387625158831028240272009449696035896015726948611809261294698365384018878475444376706934690093861571010991884815931218478115468991495106738597660327023475212249347480491245596622045508149080465609044891506049678768308014774718845064036665454127334662911065845198796756266675352320632919752900147212092808855659956614105568012508835657209611790340803764450403596521243402541962110642154068412952665916318034000033479780776220003600296196742095359236779599805275861589446660275282282541752189322962479423397451982454784648977059929939400595692882878895264041455642238993307562987837653803645873617296520367261851402840507416366963376364990857685263769669471737690601570554265689594632585044506695088904185553362641961019980416485782170038749497451022255080319321358910531019701452082883814431478894903684285293483364194345214253411614835388730878741087969683417765043416606290667049055610835536710510783294652348706737329391813494930679841245853273485522627979556215347897938487829946247278488979449669924410554314802456100867313041785170155649059536034386459041357847428068723745873841515911452042995438586651056610479126585209247685464857900326291859819934706814248637822583955463967991992707175718620521397546587891783079457804816510664480886198862948077832162365601581204833118329807261630204741581713038234806262828321685965840582881262635193841073718206262901711591058624790884488347204314603142815646674158152237158580062600945065924617327041029602886837509628405343500912116766800845667726724541750980130490909190749325289237448394649015588135921460817489500882022319405063593949180176219816954530232652106663317854561078431786627770202311215210071600162561623245493449390182366428463529092697227988777269206383929221630062983624744620614751530403928491573911023885129032641779589348084981400114850237553973174604014064091216432936046584968962207596987104334360373408759816469985050206603041714097289797509901289585189304710202329961733006040124052550710409276310126956819282903023515948290436250739949772116252343901735978621649004446547528910527118155501919451429550073579035161575967310951935156459715857992353141786349258526292441861489041365841667807206940797549094042422244353509221289275731730040496446859058184158129133417643029824835109694611100599705770532424329019126842219726508630912926213072184298006025510798705938923360136277392759286669831207929336277487697433841170385705970807728984703405580248264366897351670223620234493129836151874109060620540726046848744183661780887648332242055561951988707573401657114364023925588637842288234091826061114342572087381231911898799512774960858055588061210518474156215932396293377871445360431933684885242371798020723221902339476852477999422194309743796610885463257037359815210687013617956365775667336010856784384269489616594936740317536635783494409220736236641824782502212546126273847792481358185721498445788076745032800216937841774484926327209477287853060868263233947816852549524309346418851034289544712447408589000002866567383675153563633409337711338133680038093379932318235569844644548611878230166546010867358860908018660027638169048426356782400669296043285347326688216492277760000, - 387386896691628782102714896601858971646419874533650422979598442437929109225282928491901510921856736650342987155118037245760991882696641801865690172989381240722231852513385823309553991793736318268748784025099969257189953105178450012094639262627151887882702247344782334638276084107503827850544120703457948209820819685762381461196419131034369852690651721961965603878836320123423001270244981055927357625866560932224101160888335168732983802389511865026939278198266264953227187457015797674548339852365256089591719038736310504218963005598484376281165049711881373356662793426069208505914461368152288092850080053051003374454934004923267339092240712614458626190061531501006690060532887420327655954295927205772457029899408485998008105925799295531802548664361594572462657678691073327013267904729993371821765915637603919033320359186459611581679264559494859886358472855759979947450742509049189885961908614406788193017020165112258332096327346536370779092035336036473039415233499207701884118752460220649656425740176916957018732449119949686797184142051387538445645455291566850717962670567339949461889992899464297558562359073938005031014527002351706812755117562870287453295597228051168222432040771659726048012747720221600123979874111724134838109000112341132278612927071029447785860828511575872779748778845933826785003614088720954243085505329703043585608297479385113644420847119808580701030432005099093179933303612102668251575328973830541163474981068195415358416248496579739025661147725067943129044360888562948571264123611669430858800183091036966735994959450788978284794592781729373133332804688671736591803637865662886800126153026261870866094872892410041322858244410529027072786750530817206042833534076753338006835456198116703984455935927370698903435430140992077620349776682988903473978871168333671272315749447467150197947516031270593226141742612499401051433058075908831864155936372589742099022344115823787818173692901849597053507257344496287273067074678368977648132891886290835216500450793736481407342549849573642822215604879408936974769071041425123926973408707290945569591049100243288540802184558655605383759209164702022378054401223509684394165276754438251634701851089977146563350806492645193389174923932015568990516092580991153626280511584681643751126008918949957476770835165977996511024836956931271519685553245009833091509190511713127923521486400764517679086069813968570282951615358209660855778912880166693829828405885812966673642078549814011546310618254560486468384401268994865237209770855672608353348884833582129643821612744863978293320678321189069262108631804531999157355305275593377465413861666594452999539295571677568303065477839905931093413086839290684471767408245513571910758488050173970003593390751386732987963328361421300945742835303217548886126967758150070505979270688098317054114088370563423774289849883562728172744449524877237972041709410103588213348617136922100936124168860949576968422889080229458862403166022162778658765769170653015942662391406463981234974888043727847636594144274306814449627666107711590001678632881370157834186797758915442237640558067072271790635765057858563351343176444672937851295625516394844549061552119303710315451840815384451568065831895181652176989227689194166902614645080797467939510078776918765770543957588061582290821347154730448648195432781681105194730879389068974722114757789772926778780217041544549622450028932965941596037058637618775561212722616223899545520132203440753320525431403473248539800344365985171431038660394655610959308921494655872455757516373866322714063111686289030514302059071204378464427459399054765393728835619559025994573226933896555503687029479922166481049042203232674265678452820839908444623894767323517172458893426939283095972959505984588414319761708301647291493854624235877930847038112941667261425094203718821185620418941259623523945136228531413610214558751398259371071771081880094530189647995359991656900552202165162417640119358474515752277967569195983171849447586680481987431845573936311258386926742399130828445407292995654275517677451853027078500331082660548598217322095571666152449956250977143089989188107701678471211884033941699743613509457803409730105276419311580455030507036701305814396387230402198902018415437507096481886259808545580748847963619994243296631049442684302738874040556908677817054353565956327951911387998261640340553289640333049312984043453036472123581312625187143946660363095418295120156818103965745953519233744873038775622054689472198954949186215022321925194899824103986484206395729572445087768213181924068544498267320712676522727054807246124167472349074913509247741965701208459327653442968343200650986209326582692289871653521589469724786494425768055287404852251328043366171480994431070307839509750261705587489875116189776575528402699195943555061485679782533873940329491638928932960689719391278844978112387435115397291999641156902295709771568944211173684693603472553789603496587809621829003501521590869197581648169733956765885074801252557790556285131495590443808807168102975531209471208126591556082696685209853934203726469576816638450004475494345097113576770021129382609693609866384414936922379568362297017993182570018844827496916629250940371178257673205459431739109538474202978075340223433216362259809450713350730594130061668660238420784532798617689131562644007032965038235613061658359881350281510912932263156920589014848104106572327861878313804517676861213017988750925435189186843423956123466485377224657184977043492611868365844435923629597054671395291166678011702703947162271951096597501500416085447877601865260150087703902464441318750938324861804903703739868786404051663796281319026631446525465757582997544054387209852637552991367415660482959891679449819445571739410803428237974938447293801103655360033855382111083704309226609876750982067774827928072372788236397639430491115943117689673194140358122105651683726428277480282257385421009208836466524610650461233663767883443113815218467715279724777116892628590129420331618226499292861161906120849127546169158412404599235080191771633957366777648413424080522185031578988068241922404552242900481180847660754410643974397927581526581336468911771188159422331694153136326324844146607701872041934804491042291950528890516054590404342754553737816052151867785008532219410537810483720082716498153062545405310461111912152511603637268355165569401005662874083683728829004697695956708310506381701272008013031883310091263929433368392915789514748039963716166959605235798353278942938399786741340814256103077278463613651596059085066197655566760049212177381414482385534240438370259828413064762604565573300887295876524040466563079184559125357015877373509303100765068407544438203419280579384339538283998790023456118721583495062629914832008663457686828980884191928346966541302550512995411365254363571244133012802799667827637449710520381724587105151732407053806391568238026129304510345390281714158185126663817369313063263216241736058761892354667141249412883466532464556797358363622902402109657345542373086325190395586792955546386680604739941736504621926737336255167873957933197017960759122118338471843757819292171464871303109330306672013087911340704716341061026030082905995732087631006993354424738308653864859357492121253928201500321760825254198887332200612889814000269577774723971198751133515027527804706563052898698370356891013759443393539659986543787202182898956501708892893143491865617693629442424286148892237024888007373757545178393352721793149699564437831098286292459455451520458500868719683891529512328727450932341883881962889928609819928688544618462765197517005738347747956485382454172075270194875551745556124626660854641611213186494774073748177473825344504626135043163971264818643468797311969491235777570709426202076184578645356643027831826445978696300941008609990726931979724496805787127517964655385601000761666617893050403527299967454891027916755142516513593019876078915140465630975560285778757788227294866622591700920523925964645592289547926317897852214663510799360612057832064844883049626706258604833863638857420706792424935970804766039383191539115729232066313446320813054463330597777160240744986168297383775844203837268258832727862156675696396820642316918365443657657185654977720260960491643032277688500916131233924348048628345008875734718966069754203724143212690177972746190463610158777503114000791685476935452694828937831608616068390713401993701260931888721823682052015697809158198037211200813159779488905023668527818051999416284705436508093006671649389160885874745527585653643228897224105598912078171903980502731877406503949547251356398989587330157485651707407644153073686021464066458485502818910833185183160255840411466988545793654677135085244388481488307638615062329606060509363967988454553420465527284022369874124293128297948703392654475318971082590173603653680279212338726379266316571985929173157108058493543548221799737331997674977661644054108825031637920750696437977295656159819919239905376189027644431073539835656550894806452901673354209915369204641017712019561427806120587613429957994131801091689396576160840176980389668406414030117481626518998494198014701249512227964967934077072621113283379305215308442552089145789830029528980573507448446948909226107311824824296197487965999219157680347610559915466541768425046732321577933373942807315700789737108027350374866253600230097973853097064368885449702572841156611867302579694516781820549571287240387095196930754969678883085482873714413557060863765918652022116752480745369238611075840618215357842206276947881063043633346966015795792161279684926268088439683648223317234353139219996245543691762600618774487315054895677613814016566034505247510449122577166198079547744279968339177667077025594036681904628909775296104168187480672714082224947483790153456700838329460311886355290256415831569948901386292148775260076550349459264429828382377738148020117838390601114057733577107164727230139880371100489111915761993311510119866529005918784015057953447612775262140707808418791354403748530873888312515831704372302234981328994126478469317718322856691221858188398678971669783017128783487789426547810445164340680700875831136545065625826163817044761201706823977943560493719321039723162183724848512421958689778225951621875987113781981886512606378469486777368213710200521556855315075207431663021082908954323583143785409389530857624998230052959414089711289595279784856932884041298301033140715520000, - 406002541489047673413959689976466727118130292384376245691648999224106738936449323702734534513742842997442623560624418238072886884283024957599391245324676955257370939965011658975870966652986998534629638580713865433376000726477556116537605338543232266136014414222692590071248195351688093606434169209799420258572323751678110178572098530745881990140274539804040380645505915430488464094917381286373526190516238591680906308441845428472758137247650327239436772579961237249048560144883114318984359654778089665943222985687323617191308374935593603876670201011744469735370290476347253225694186900881789470824440658640276499785724360508376922780425707474661611399869375793306239297915784126960909763317379489976382662126780829833954023132504514890495634461028090548955808186436259034910261650208714173857744826080799438077881977393543151341689826281223554772940042543831263917307526182827457624047176740878580986441486425503997812638912020794275716132680330591757329238694028886229871733908796693891350973173537581696782263965511916747239935421506523166230981894818727321255260908378475279484473440399540421417556450492127839447433267623786816943920435483080098026783367164437847298584448210219378843682156366675260407030454046487421971328190109911437848003240560499038721824303802752980198338145428075854212682923576215263571999907794157239669516394255400388140574678400141334591547502576807400793384251497929140215261787030290684398622705673438133149488639177932686651405916914450698656816568957935532146263741178277045997882814293021718578611182076773667279486889535715111852345763506442024994677384702342814436367659982291609381559806520989804826874061615766470454467800377122995866342094295154570133387119171218190794828285767776671665356915422637644215716447750068954854356904201282196120721231266753284612113847599788555107264693223042485583196340504568761074585084717777238293550374552260341279623078232850951998899335863963388103075971576753458377125019008214306644275921376623225837643049727003583124503265232995636146019197105369445655026775441810198475272337679457089291842098725272744006838721666975602210442096864410571118148536179325210743164265902874552231257301251118581059075973594192623484466002149263035496284493981779820297067897178431208118274138116031816094721178443481599350279884635559794398060996623012989055297573668747617077493705810694627486795988115702687814465127236025754772650233406132767588531281296184527585989249195009453449941719125563541492724005355573865653119784819981098136003875996522896473843978007458735092020197873604339448304535442381550774415727634584068153313953370781131514713790096022773522072266803227657238907533126674829589482680644873424186969484122857848881710555651622484337373083575041435364038746426567330074592275993622307537866133586347479972750856080610360294426673107329820798401254419968971934456542573448697305952172253880141432697252589578076508569627972389329398206111949396020726477809975358812459064686489896755541172400464138555521776353293228661324600068749449899892902064113599760213323406632664592988024943086351891034114759984938407443737778237885991646397827410450111765372733284576191940725567884149340123446158225566870844072465491799255303168940418465880002777410970466874294136135583843422883398509798183081449817928436505477245640918971007473525305176407206817133720464726444503355011563937447050896265134968382083856309494019702714065585602073170612501540462411859273112251067815299212618378151025137066845055057041813704884436269902552570462104614933066103985555443285775959492451119363789675239476203119310165998424195482807230743098239999474251196714305696201098945431213905916144622867086593768648956363608128551897379591431549481921878591302082473494796022792315920677113029639247552901538948525885585329646980861614444327791138017333006428674638802817596678478558599062955588390037739565982956551770685844532326881653392268183276663780821100960507641696130118408887678794827248557867640415227986109244021409433065269024848519519690678023472903359421266588907604994370929395140366281467796004016829966732550827891441174591316533263603866510156218358996033589870419408902833714990075887480416061792425370521871117404730139412452728511687875364606770783045884056314156079390914893915264525413207065313968501768950848032773576265906192940541609951234287084282927503913789414459855952453656143531134792878129735634840625953577714695896502106478260890119299702995881057523050743971520045148740186612668650853039271352087058153458079827854981581080437121863646008847297140621046103002478768232975440235639716088841210452929329007888536572904989892402583686726496358603112924826608702944206169535691159097378971699479738836898142531786990383507167926883715935129462619707590950308006660730873635383531485191823366243731599746051824838968633381793185966618129474251587678318904896938298455800190431389591173069872865039114388718512546249479728374436041098160128355153913758135351789691753324729149776761240101200276086784761581849939366759253599325238862780969827353859657646685846590301357306783976250102493101553211369120897340911390389423962927324581181746979545455719226867716698287182257675613279696269034987699875612018270121819138730437416835852845173342139385612664618641510539844751825527696237786711452367095830661588010146202278857218110265368423324555751636642295095562146974550257021865207021740589402690296405511162060748673681026307288610264153542874975037545394651977205638674941863919400992424358527097605874889565693413859023720420555401979843912777426833201471074024181423539159540928365800026190982689028731793135116784066901173447464146166608118061482257254221113313058720735424788679368030482888715836770268815164785064289446755776265092467141017794085454105006712624163918193855989556076836605623613352611822889663595157584381591108447659188490395222336607615534101296307092264564687870800149017823910468753009336875585618835851125026276857165015707325271799647930112379273665331418467156973767764017982238128309090578186449997506805288023123228207918920511169114810745849017892374299909274741903161912942587150047553180166873690284102804243810753113360674739135841451881612973789705896835227455856939542769650580610536483084237983656039270436881869915182470080831586008713250466419209386648229843521946293775192585372402417658875756000374868541194857250950120953771812648182219560384630438062082003683403571409272801115412960260043672808669742512615868404670570711671724878449027453302096854801545777508001134734267011534735857308857572362797480477638755962911984261562617520268673655737762608879037562656183553968039338856774812228286382089151626590341831964784718398785807691785121918079815792339215993451654883506006813182095733047962984525369396706910904297743008370078389460584480761286904593162015211847129739935230166060430155103708883137693366676986760995654966266117156832421311641244216462630193923252398985606491645385342536879707143373075332221898463155393580874832968327915223804629923721631034355952766542617318242399603499600389603953291198480441217778473731458669439326728360486764772824971892690135679748587079674130676789656064323277977605355804903429569916879279269793583383760878239684964355457900929220198365495963629110813970740233048128630445853722023338563272327795195854852823058022525857084686773349097322483441801306510217399875339512394024967808442153802666559328152802128985433479947126572972666976120953198485464151967608542781785373624678961582486041219530996780724651816604069656842376271851946913270889912611173836948575834077420454458361065041456500905920215085999421854708384588880088097168150797308590970851184067744798338550050834875171016674581190961738322989608056494338590636259714141706430436057929207599525832723171847706940743611686468276739931336020002741927347499748786043584270803540766579018626021386323153753992027734447876290687419674652001737974701895620343903310970624288713533085854193666127779303943436981603586167284478737212621145250593055948550151342537246200312043317389188085679376217249927812007990050775830524620334932950203574168497813748135526617836468177588735941248799198653173804216711577292204296939590804789271986890171563780376859687106382791196246041608716460011806202302697272343247957408913354649944315090307655648835299428236096790152847817513260559743861641057118761526432610984687708208403771912772636589481698774279876447774887733082637101860357391359596226340557802848056245547970380169245676192480749259093620764064239073574412102133493568052456197156003544918154825486976084350979067226724426873748502199941822923088519974518143163112332182603029852020147004361438124453061459827872930427367116209169593080164088638490644116856176322299004858491201865233291677803063849146676753851234428006799184060958407636768036680930566416390838623303812294412004341821763421927339907711788747050295792065669517023100134830470215272569906140526758094744991755690283546863019742816354397394498995554123356486797519079908036557267494805755263853438619670383944922186265752276563390629317573370699306577036128117848324493202131561906958101473474421483397010890647644451925107658581089749077561849518423688259555400503954399351219155938235966559044914948336725162362511476828046512257498628851848655359428860423947498985717760050854050132993668844781749688508170542951456956530174752091214510394555821563434176011137509085200748899406548500781918849868955377940063082823627976203394396476011340044155331519669942183491853702997846447286102815317817610665589657622668295605488847849658590818619689936196098070361221488797309335835569821333963036850108059163026881500807279607597340134707040228474069252992092175937053597303300835417198356090420715689033284674758416815874382038529219553990721772848780160126913974860820827388957206711469198776116217291964195004101912093501023643735354415286182519700256751011550742797014462306750713575168092484316204981523502672738556997000894010954358296039888560959028845787083352010537038377340688928296062002081081256430852788033314829204437060601425106324013223506427898582545833511664885365863275285588676545639864827649455314044104385919058197953951541204353651037582384388512339933007816794133881788587189987800570847559680000, - 389076104130732263884699858962832273146319016294859947924338196203537038891129318547497582864566466798229535736461418343980141658822771472725251385368891846076724666946427004616471391018771139269629441080326465292931169559237558750648420321908371243209780788775148886426355628372108293363070315820417332554576614403478029541334686248605917615611800546895382435210178741488715815813955405230494848408822276658107906536427758538747872974932827632161589720254861689191572376064321539713247006716777612611494152974986354449219741373905342013005845642704084587903131423143294132086400795463876599449976074548745255838076595633584341557695943516970878998369179197225790176996016324067615819537637558571332654674560163740367798101230769740732834849429792803655034348408115530470604859235606984167022072274373384527987096750029704197213651247151345850537502666752349142259910291252116492129783340787327185416175121558626217567862068442898858950936429481035762535624411846743385553225884804896566046525023312194808816610178790345954126116828923617783031031353371231918263950950557242613732073412148475368861788052937606978426005726233822101115634951070661935649202628649721456239188403386902598611596140306694333054550693558324953917149000187946724873572007587918705521934160467962015746686745087582313614954526651823733644560502695562329311587193437870166295254323581058714588440823141954614205456842129173282366130292274372048150557680626819660852006774936512246508589844309827731300911495599005727091883625821439813704527349946681705182267853321821776890880797080187782684539055966123197835010046140536683335134206488707784396967506517902514774135796082961849637001548179098337297313351952867388206396617152283965528010846256554652464257902674419222726032339765911329669261003283983181673608330747077217536453019073513269044899498764303516382580204070736482088875143860573967555967103458086814149513171255021388441924105980079025582410512068459628142930741993171485730964665019715051517136157265514619040022833218221751562121306433917062625026424579363476020933587315383333717021740815933096224862109920864562203882023662627877276909046161941592195609476876782051574658095443363362377694980849578019742290442985288272955469170892126369934810983370835023138640113827308598683217968501406872084140875663578998577526336506923642275245773611757682821797409502104637598617367573409471247350133651068848680819557210562826437607181342525709888581257468797922636163091196956636630434538406916337594713027466908077559151992099703151677869388381827155664033833915973107319461498057810097878226254371897787692937805973085012943555173220204727537055829094486352030945682739481711224331871612138414764581633335567883904792573726913575353716557713108695095656454844513204901039965347339453530231466709712565055735080763230044037906274008336610317045271227246433486846510807947954182991418587196828049143952424769631925708125179999474640977201800384905718509883759056556171625998306455866548989939979701781844777938569858196837299244503273330440933302493640512996448679602238654673260685902899115879076912269326351593976875799178382315503898186717618037959733016845223684035505316857037728372529653354178496038137171035368665351175254653733944329423418971654399047807179379915620374522931645715215901554437934541449714575239608406168391258581048761750776418232942490557681166001078167691570687846129295480374203914655929481601705045409527778608141504746503598932710070636779658444554437668212278536077927898458267898327663471204143857728593312432200100565081214327262933613587938462687601841391104237866647800942802675614135170157023529334885501506895724701807799640589085598422380301141614119027566001032527397688217297184802830483061369457301193607265857314818323591753921838128422138554415203335107248655743126482224546802915823385981334799527534985087100777620862416291893396137879205788957939316818969738649371142110869632587372470419361277496690547427690047715020602307285916252997088286798383449130311517642104018102965566896064422755649859244763422429347597433142784550725463602298925080105490259441152003496616472433370022613368619969420818073302456566826332543600900967737026692776601784486643185819263972584206665230335292022774659517239099434477945866992359631120079683482242030214620782075046395686167022839225960899937392598497909825847766746200131289853572103365101903843133693687289063944609713856852532664567723773173932536993466932009193060460906970100382331192303457914054489487435907575638703923274072183008482449660565548568907425232834037158320689551923711453603262842033392611738519737646439002543925775796775527592201033013409195406312804656308190619400578120548864765844611963387645048332847544228605975773032397212919855374638708306564718479271828539013057012094159285006361566953298935710717793798800058729935656301718445875286793845038442139899242839069808177920859693083090043585337240248926880734823650689422007339663821145489000665629444861021724398350780443867678467521024750503217840506500683333837472284041186128598344051752999265737190258146151756452010658649033204494663883225134271565016779311551267022153122898280967515417647942600412645879133291231465854083259940315280558408864502980673608088260583708617008183924873166751040286446387161124615991200972073532978218485237576652142170450216638905960553315262003987503253795544250980422247562671114606639932841854858090142220339016000207087172234942338488414902041361707030821389554473137086413106354027247838625919401604355947031824312822402121986192635858580591251031559982277231936603554796365320794302458491854902398560639068204540572052045346273930999160252040635005428517636366341222430853491058855922325165443451270734194404071840132496613786756388458510350312940457194118410117030774282804799581392681240367483159145753946542010872516527919053075413324195230773652502770513831383604565058024164952939126500383790127345759426033032918380178479090030394986171567729048807999413871274751523571728312513081861848129715377095029936361638493141877267743686237492404229890662603161658319723132756950991091064128518852764917507794556040789194380919901329502394631667783435011908928150929281875288429966945215451019236593699512398512902062626556733430943305220822427699934647853606028847684167976814294962977572272108967666732617751053800915971869476369041455650894480114506636570826832519271699708631655025072359514653196767756953438315462948759542020586107676368723085083598810599608021486888479504573959944400616838958535765039311394935953952737306656613468382736940806562021934814529963351568021191825033965053338998168376125605067101820069762812680072660241889224823236138589598054234893903556411364031985099957918419734855808526354314904739355075921914923990921528307908551099316009377252652046464759051537815393752847959819800971348586990745229580874081403948705112866275971622417458579049179348229660329243154555453129465909293843366721382196928941472261387374180004207950849012737255311147758623825528219975249075629137068924768227000190312295852838263505215558992123393689797823447719869045038126426132421862663290018813632515222479263013739453556992209890620146962346743859395371103917459110632622144751033685071549800065800415938733795485574483376162678794322360853018891141815769898975292680226368081876334775220454305779524791298537678508792008385257079097410775095387020850909806119500163841004806041779182231722707460534015368270740358752256146402665201223332372606903771677596330101033038959544799631911386709761073170218716444491080688480600604288254941689632765637938211019668941022770908465169791263291506698309015733410586185201525171674966874510053651688583915009793709094184795418217979753822208375599266962157929741242866166106632511926187985018223916487542524360843236454921698176819918502186593808101117160076878030044314504761680467858925013488774464112041023333317737411849544133391096168861154049004241233884278128707833083017606497087066469745259534650178522859251756749287085284852487862398177139194791543275409941940225848235186026876021006834575987881048176387492209505105396605428463620899216650223139801760389753992681523923626902007905066646349578526199007315907205908702716708183661061878026414599700032463944408844871303294813036305407385005834649915699978291209522175181492869702897847093646328457779102769250864957711614731847562980460104689710448337993212510829666540995916757181268158364875853260999923200838667653634459797359057071254285877244807355082056012968178484760228219468521544604563854561836420310886221950088995461348708764873599623419733002061934238066472809790147269892968384277008575346474426315216151136061224148956222193690775544235954314070548956227230600295503617306847501320825524635625092579908459332322590145167298791969999472572019830812728401871827243664697463266120359481367427804047528111146729036260027588723222589642394761718224497835040914753019053454726504289837637205441035935130688988833904556709117518384614823791661339699211783897292715068779101546856859570868256620926759117699941438920244235892912230573568291891705634204232233329430462416776408393696888239272709402576144056438593375387990838189969463237630629320293800027246731915034602663196120615413427073980263821784303044896576818690926746555150347618521477061997532176258224016395467680203463074413941878324721809179244418727026266307365992091790318441011492837072499857817378643057330306219312162484074221904451952689303078686011409364198194695155370044997997582112594351067605364840433710570046781865406459153389814300061709424089856875745365427286167740871210321219822838668189376714289116918900631296386991810514841187996586291457706703332241082097086695670527459170509519639785933452092105578887473189062057571743881556759403713362678823365564642940588689790698357558333797640134145756167143816787766937664716197425134712337515766268390814164046977089286524079903459224429949870795264104565944775537771459397603747770762108204956455365790440011475885874519892479115797533563254240358230353239149241063950578753769135868296767690475849231645198322117294704131538418924327545143674390663018823326138701968245044962617767483974267180972196306127565719656008085087381333917824435963822080000, - 341760457946940958256847934546933341039743970735465566148552910636849774300595775045059763430987058539470319951052210460562122895869771098321391675797418798618862563171915477280441246553704840326522305086703062180090583715287225954404870819227852826884559290245835287267819708673800385733314885886924219192287228088601733415574104198607059845007262379567230326130146073858577861319399563427337018172101701891613212477345558134461571990727098879182367219863586879529602800355791188073153345585028898591163113854117093010077702377691644396660988098996371609559471456566241161325009067485697170767784259079473696565199619697843354275962751426706594046329229331264268351945638738205987516409382154453695168608424702477392509325645161807751481391224498373157525789629998547964941350445838317578391735238189069473215234063212027320343592876682396735999696138480475191485185605166009096880067291509292480009109977031844496822618143357695253945148485131473880313462697117843811375019496115210233253773283826114231819074415191303321676185222784824175106197786436512176077249883064063171262701418059523173492885887706190281079933606814133928951616132549380739068343337067003489774618806997169512805992010792820523178422184012888423565443849391212333726374281213319613552871788237966545135968265616445941777072066774336262079228774150172951950849075423922613508297152617256863519441767805006758713781569419951636679194863186155263886818819434869603372469923872797362902095310972058905101980941879351538666634636423757218838465747628841535494700680857887647948648389410923044226893880130974609182374547406982095763761376327322610321644717815259419156141421752389096109289060027728643197291905657382005097776786945011516438331467724850076763547876751366360282098666323723315825775569688136200814785403830381545740467069064821555962629224381248900104150651809815339813196779748557705416880460748673419088732118659096905097542633607423197709849392015728290945506574803146932463039243097663101934766966857217829315356544423045359294134109529649190315566011332288746535537057725849181201996112899484172844913413569232080877187755873568410505764697967393886730580296907378281090917703621187693572921545651734985052108385346338852948276403515198990494215340282954322915733023359247388674492075590954340130977886006964758096625367051614320172762089504817354597637611274325746458755146499022868048086851076109152713311818277854253752281561560101227414722959013412219366194755933721136191751044116951249695226961665926074858829629464834216528660732211333680405182476517753279598195242226405749599280720738964157157708702321529296834676515881034566958419753038586511200328884512845065007438261339271636326522293193147693356967705555281357807633211678983770811521970001623558072540712129436095845625551102600083593008302195599021167026585335943830905426038306899692276886195874405862970982379306669877518016743926773622498814816874843417129922571092000893171189091410402909468576087573766625952351023187218936940943724627420276093233274841384329944138222263503459993052776524885970599766855652280168748094311001359132456627742732841423923262235774070842972139485459281097893208436452359112199838852803290833316970411265153070389087409430068192715434533357991847462124636018812903171973639705899473817418601837595700679123150590337470532372856430775136921332954607682065130912891340113159091189747563617456624333894310009036899962139194378786412257278659135544130402771346838641879681394321331759481503171342932543218926774894610460773533807242748880931830106734612492616862134733281274686113300672052304702222325972961482031539821509384121985182777853497548116488520995825294861005733480846183995856950162056622492057647346715248920689266034435115247340794124203449010427617010144046435154333861829971691238170765293351563745952457995930188406157082915414683948710211647682207455703168960742644393395027724421852031284767995579939808588574221502025499278520892426979479937050104218349924529206559107202503499663996736230368922351797028169158589052255929552099429531828351385773250197667764964495231339150758322587247799872418868946548631854622353213909803044529631100350895938947603908301529809464165929979471861370970823572164846944926074162430929435481982403371594752507445275325045104641231747243898092266148732908330646002721282248043124790772411092882382575311348248211622203304268712662130157364764959907291572858340357104722851774427930588198670898801445666022137960772020975891557838995601565701127863967377115944015967653318983297909694851197886719754644952026144091466587116834978456354987657196929461257815886054393472469941914949471331886861303534629536869771251831753361199857259833935371577314954798232918286666556645158000215587243043615696156612335726979594168716107975290973429248066319248519453116962922582630829661129282725089098513135535144133574450680058724364895260641466255668360000560618957453633307221289724873314700143648123166143753709714484992698332496417276511390284334356849469704280689272624141851713118648263621552535873345341335707117755115821833662618284423306512169776631130234604469279228554392322324698846965560630825010237862078157877907749901147155101601472391358676686359989349220558109522510409891484311862952262709002039788621191387160479367232688100817460646905901467643411902100861784018547574570578124654454462672267764131005889234475059566577114503260432566178445735119933009470676991802402891019786611696141916230370495809197205141302798730867134374307842143315620922634138466303540828251850935451297173395111471429126515144816958873154017750187445670073450413817488865681422800909221724225564683906469077595717595134078167109811457442744222209496246590391698481166819457851092693398385871905638241182689361218065629786813287542806176922420914498482218529759194178586920530731652146136265784414664460592756903756499418788667902433549884659969550115397836940293153040100154120830386546385036410104471008797450293695142830297956644771492001486168016518065301388587927519038399100245864861792447767886828410532689904317414486393821644971038690154005212318550432298378886839804945363471897257502351801465482384830520615946787318078608285135813689495881851874923408614205857563966957796913876288459096091566542554953518107730926880033561900350825546272691349745033261656500933691972850283260541276050244388104391114969568504232273501747973199884325096981691718549180062435221175283458645509210103818826682388453142978781349064578252354114551732324871364037292037260010125465625319026096506044239797500422326028172169144480027181508636833332296978686178649548753202705179854141920750517747380760931983323607060115772849766001678919912145860296295509819415048222174601288277861384318578793340898279945848803583333606910459817016821617727870612367570130358010714013672688945284582444570429282852064860827375816552365180373746218019963655028290847145339701628894274966175007315776004744478780894662246269058089709955461859455409331579215858064652421098297428970552055387427976147854786425876554717244640712145307758622822627620354872320848623181429259713733795690654854218568242597660738401172497555322891810795103861678203940537853854207790426596907588060049330311592581924957054894199516787528896156521339534111627768166354460310290970796402614921935983016977850611222370690358216543427500320902860501583582941893943587600238996457667115582531714444077814686762421011478502208755046813734462003093947531546403561678166469334079845835376120445879935620077306292750298886985022926074562162348920833092780233484088066514221079574120944341951483515998819401452986468014076253869573556893983551792500280057649332498090708424823668595276773908263044256338606568130046130522619150223096238283689035244253383624777410515689573858626193903652450233282319017297149453081075565617590899092102917273622680105950624335061194837245489094111009054899856259098865139692112393671054420377069255563001627246348592557176748607878554591503672324364597531817906941793813241373876031887920439774037278890597249462701819671254657867157193506947358835981774128929987088879031531296342564263769287077396897755515954804614761345188705721388721339408165546786348112666676461263649294714559939340951724286024090613780273177408901704964351635967356528611521542903927718892435790223540378603195813230392280432377849880054372781009206205456515927099047970325939942277389817203855024685246688721514446465431529461136340813987986812274486094625549615478816311320153683704200249231839031531557186629175617543018825016706307253704114768051223174649930413984322311627208734597799652560506212871843620967997722705448872069152586951807087374718026787109752737269550132812305200676180916457687687175505457148002302895655416297975895075468625568531867938999689427519040936987946207929213852101896808080630859051692582619848302058038382248419403780436723090993561031014954668895453821574314549000722807083054515568089318393662829594394478602151079399961512532726049977166804314774259958334756477945656798993176976758234471170146713958667152104118258547969031248040900028655730408194845926068540929404987869528805785546033530451287860864239320955498179565551761427689338691438961140632203488422636712085742756127939355653713031560720357160728109665824912669161341617457271322099682851479262786667122197271047645802483247072430607271986999458425837742589663545454749626101864600602458268444834616871142651685409229830760726999127128300869529209103850430092940235389588257198208766252356935065303836703292849431714411202875508541777124922955387448849254238043299931579012598429711906462380596884932783133753084958880827554910579968302565311096539296363422279466028678961005970483951385962358163627709494710500427524626534622964232848989432851275344411061491008883209660798738574985251443498333342498077706102169556247994620775760305212151601705277027350315630531301385116822853967039288998220366803831851737653028999004687694383626945329387753547184485084739962070240924623313148598648498419897442353754745699807196607452431598419721314907890078482091327382851612084376365184562194944652914454996240799283802233295310455072284628339118322304360256713193707279065975399063723559374920089600000, - 275782070281308011852603361386339354973051270019967941106608481660331373821627797201779098294202958785481828981114043584759816691274337404182613970928116589966776689016003193104453856083303352966084508501240435152462427878829130038764521664735541108167408816899376650804134936257303830489667765420214590771364328152679513599286481834068462643598179156517852455284523640096556271453924038376233519700553893450907951492891835110543461218471600638404075293470496047035892844935223030039861637878203144442407499348392185383618547915637398290036411111079789938174209063253854273366611271840732648843602653991225367004022639043497058882002108669014693088773164224371978736190876953974404189581308011249492319367712842345729283374419695688989627461287140556655686296194064230129967833480442077315022567538907970351454095367539996757470451994922607351603348355664086730610973990389794541481137008722882903586562703010670723235075137104144024017743289138403918950442086561268636751850422503197504372100609704436261942455249155242782564873171241080129601026248899572952639469515130125090898224690201258449465594682913438731517111083443719569307901780791913674885299955706797250271264757080811441333281121830935331669827551853068941074791525730618096702293352583972519229068035163338951169706532203999635619843358172073205553220011686070608128311903038665017897734983121748574932599518988572066012351024631969707709236366919701461700894117177314380289124808935082390968516021363876583203163766036397815575279357810471063056060336956308613539427702310880234910740820851542103346226031597855520996010068738478317196934414516398520834032692442351343843212100313376113380574227632162894447641997664099129667405426612530808113214788460839227878780042638457480976416402879376778785823312462588951354866952135408677656158007156597878447974160286304645995195035404884279647817729056366420168278723222082222884950905235883938473925004222644452163718187410600470984375872507275311408602870774434095704944440316893663532928797241998901530103934378246224343502744505932626227769994588865832279829566545610293607232162943920641974000436565478581052105858268285209110280376246872582214530783692827383980799328295516187867545825665388485241818383025804479596850680495786627493124115326777050451840255408166730600603761405655271250990398255084514383429486655031321301753944388082303566006968192864067844251250940784838031552854696482377126569919156806033263328881725355102514495662617939949864023938384764586576342885109446341791477115805351210757082513841764452314493391245836564251358871438450940795786631096669847008028183967035145101409994829654024150780609948577130032115874743778764507815201383626097530432712522650358132256751362527461712434901457271878612956583272665231398015656790554183758780119494002015298569355113912383232987571990642958448207913311231287767499185094406996754225927352747940813215452512814198299247041414737668966312582207001989264318096227865339949345748017712840422434123982801294711391910123623242898343843216393877172750807626533228727616345981420592148542060677196814222896093412763130211428055416165716443245240017212971228184900065165481679861797021424171566425524468306596839925754744246580525189723579202572018063882248207996768707117033662743019075742533043509443066509118629146314021411744524192078832777602472253059238781594579230377084834469030549197271074576776245958582749590033825899277135567494378902866410125429073553357271415840457081943621950777421135567510591386220170073811952454087068753778967889380249841819227140833989907002905217357354603035006828523103592037954707387040693791766231806655271239775125801539593371233997557625875459563392487702072070077128658132815096993174349932672954602257282001338902942811472469901055911258772118243559778942004895889402059804288072674958078100012776196002827246094415068192734547638986094106550406225732705821053876529099003237218107045472509144611845934481999278825729187515798013195557728066666480663495985138970977731021366098228334678249744455838032529594797619108096008191356352342997604469510862793249064542021771308923326086614431909914303279083172860504919115852672394359288928104231108078549013651146626958989989633664170969108033223630878162624348520308803358305668745120983043713475861536690575668498045459956855226175422593033244399265235322234213201086188766593100126820823648546588171438915581542227866826867754426540277412232201486684543635859223199477544567216496925008417149140010694607645874465840034829427611787021420785326535804531908060231981988317760590040756485139599476357143327651479525056957912277716168343749690885235076866540511487180818540944924646521190140520053046620437033661735209164872933843773449182404678275407327224539951414706967786580575914784915324409344651380768565785046949425982532903445015880576730635121073782630176338712941568891591411011746510309507563493114968670856603709329707988769915672917333064793140611789202099920776962042396353701536009698294787594269643299888070055715576119651185913055689181875057568012937264281420814549095966065368247940371053509306484734015674941344890512399834109372387217539668838025082122248725275978921190204830541304774968813296172014498351102629265507491073026952698335814271404474734043102175744590063657958681167019705570765756875192846959839537835835072314988682035474800057453660040073368003136027277477543834974221384939423721027096854323302093993664226742200054453643421997035774961389812756525239171778573530647877098162969092753370954627997714647295692181193194568818433604443448253625138827150747569082867875614473961926311572671546320674075434188117180805733746776105632119217527655708415186375905027657135615605582755508204721681253767040482621187146362254702590409802198714715517467018459979765438986627579183318748096534600644600711398391875006781711280215705279949315835604094192474409120598666222312085799322503297818237998604759341407592276105366003528572009542802781559737017349481712070559178032462750408396842674593287756455740172764796521900177769595195592639734905493623722430018388337812319509818783049386504005461236222502812200209618235221634178596531289373364762047479183608296207433887861480133451500314783026956876005196678335231720075727258802939918470072873123677825310337081133649062540593343731225849873958293598527643635669287042014705747972467690211072916765785226372036512610940732447987003000470991378721870893899763326854153851946385028523625558173772765045036750617113734204653378578307854759430550427236267924090016265054372047675672950311479986392216911435375188425605547657088388131750294001040730634558339595461605082909785497540316798252119967425796885154821384691165300586746834512082079832593528219069973160173431641475800156943109537584875897061618689706879797555794590684357379170583045646273513430529804721231344347325372402714040115557269850965482174416471926095293034327041026591124711236975429383482492559131111539157218098223113022275556700890910438247438218554150465435500809049433728503867792829157359933901678781443007920836559012624107964422472606765003941993433713653311282453573347334783456829946996478537576646494226913837719870471683414247105664969199682023228244966287110235554244948198415185928725966379813815511145627625109259554775888275473669402361295562330488622164844533914185654578441645095130562952972991436162881133289644269286529014547389313642626161574022020757003585927754241756421808710634360663174236608911503851662333125058901867633255509642918689757498489533130010391925788309116678077864436826849781172211332620291889847653186787595757934239488691293679157618069841463499190469633645937975370424430976941222353861513971668228943586331552766847635950895122522706829310430413247280933017731445642968265408711758991531472922069254284261660598898175719529025630333107700252249149446236419644468384435538802789077754322882675565414079189894039907003854590557169010576698027405576330731190633343173450874421713856347964007328771631860751090740582031255588675847771177631040320127343605579252379480457964959038612866648068314520915357034842667687842598861435450989504374270124183972022959834326283458722993662098104546609138464921943471798541994343896006453957480633990755761485229949392136856982415545865575289636642953516584948637116497508355320265794021379278492332422465388808717166178499238432812296738706505842545855274330413689482916918890395615013348014301176792446131338380421386535938461013095916813752979291445502801547823210731902961258463350469867834486448538335270138082130767273157169662410910877540375873391743808133199755064913477780083386608847585947899124493794090046603585592673968482197259481914530283443307748842620804314922748652443571563025619009059705866598138985385322013664432714359978949942824156762374399765007955819305734291753927957048248695231522235193025783922043695668644911241611518525424559596744145977448948578171058713777761411272719281301507788283334800862635526568577541170531105915616447940358508482313563379843419575723039524315719204915091202995716710349020401114467492837621379163162518774366805675346790830265048383908005838634629249175658445880978104930630150217999786508403691789106182384179017583950710015755079213452654092830456868734622942293529805171809705652906902040613308388997898404547652785271176159906179370446267309651130809966870105685127897813011503371568688999558286720887272306420406572632535074402835786786294371408901764222533385180760943376632039240689601727834180327144241645984734338594534253597862485601966309563288192953980065575941568294491507386237969514476593384236369135833958148836117971221373647513351345041554672363615611569706094280264278034420537159405952083398434495710372736782954374245536888808147758444306269368548027937621153328034733729258860375214274160915667610559255710895854709161189244415080702532621848857202522993417299673432299019946777323614675485120005594394585940941562853857865715455599151733447290213381593194800927678637611407201594978323721093952593635068171930061395520443739827187119392796305142759975066621815055754604317011631665663315809431616684872135628597955743866728556572411237976563284609296586265067520000, - 204866400856058635997086631217122960339973874567156128349918065297021753811131071339533322223989785898487676608635884969094361206882736261754035176640355333078241319035943799596968833187948899339151333166046415074381064311012043254597774347780748142496638766633262568605282173438357963349900185924733185346438781257610776458129553020009750685756699152724086018094630662568231824271194078520306050544475473547849457645360964415435776469588891949262562273071562979364969713260847305390513855346514529138179727757682834520190207342943439101320193509549035262749261341799629410291322260840383287694761219871043604680566025860553918109573299280832447721433626972654170852246114529461745931365193521102001836404185241961386919964517845410220893669947000725740115752581506626428331494737529105387234549233165985730450538287849995528726066377352426228667459448705493810739719065356240159917478977357685682035141036533823788583590286110194369599824476931162892736892786633660019224940331582273068057098459992411122765315392984718760054855028785647231107935353972620314514915253323989376549113235900305376989178629131296896693458585149123710268750539505201661538368746139897862695655159832765680315686977513233148205319340745987518656907697694967661067736669481578187898586441191472988374881094901993153678947814757166652860398031473631856757639216241434268309545946361608895592981549390258188008069399676309572483733643240494764284313851600081216370719830532005349325067215817785777484103774170276405017853665863020078904715813197112311490650227050876388084073955427225747534819497700715490622081783441586305622633069749652283155182856323719577117227238141378701779809831886111546095989538793818884758076840641537097215173439661050667239326747724841761652460884409649565712027498046442493271761465205746782305532805641757135038766399757420125765014416812237634723878381205490220678806071851046782045854516971413822019546067334238945214001523907992926217372634831599326732001812919716322092143556822674116209505086509022116358104689217442366866841758897398371106196736957384730499532290752864737687793764656702951173330992411783104471665394054734055570102270316969465613556597002480720373709999748230560278230408369917706061612652992693007702320226408149601174818690615633467451995817234083504590843974626749247516421518726765400328535216185221645042601488067871237538203856457879714661082639697842250485050517044063041801282752426965747313894023730089675807008123125972464092949367776415630104836428462861424896156068210866441628640003189056948506358551423561790578517136324431966417610102434666086361022435154402600124365300524743113822253469362161435349932354880893613059404235858991401722551189430532840620585201518353715819094178145192889428925485330520601227604855819692356390105483920316291767287397098532210410037033196522578905555193162187716643416344631295232176900959208807236498299646044420764451020148726868828440302440119588243065557880203861771071430514083882817018964573476230337555192158806403188306859096130100755512804664505797311952588947054217066310096737466211870182533718712198734266831415664431127037843124316978330513577242994919716382462962878681184415400858687565745104628690405694407025619594680229490202812635959457686737645136410623058825364731841532208391093181685489890638248574843921352199936663037356829581729497094710680660256103178168383440354938032929974287144629124623659815714678390171163996423498473649693449332309657563913661335694401664024299148792542194873730061894739329977424487193029270783148571009104321580380482599398937062678442674169969085634254930704609127877485938384464181682828561323723396571573027067794007516517891944650704896137179396319489163842754766827241874883418313839193244731845285052362830540795668241078132455805844690397416380162311897146792804556211902292859369439203744102195848762679933490231906699642391401235291879359088831384767069348761292884382601686301657444737644842156754368643396916510233372553668279334264709708276748714350794060196674835118021726882642088077160055989006222257567653625151451987784204109775669416661087510282263388248785458339825377848965150703033049111617644472781365753846071240145319690529389897333034360208573537900741048045652916449924194965691533925984604832008935920298167913972700886273977089415300220397790562137616749702668915590700644587731368353909841335818860890844960389234951481408273034447963917127391738359310911718632915302235937475887720314962931144382595864337196771629813541477205898182111011460977510827665239046303854143785214519011184686170274164183603384919293216478207204181349155027299213811989098594700740322078761443048361474533210722881139765585181877961944180992035623857908196919794352414632732676168346251160316090681375128718732749869257894699511822303880327587743533463812919431503621155413487222243722322353351083406898624674584048395750353852949448913660117861716932636995685801675827626996985828174753280443496221071852864139824467904845287029957023362512664786328733974769847421050831374621672736318981806923872570273171810641955869668882744606970960152177633660483742160675021253867897611191422643972907316872086940298620089383798077442960273391119968453317760509502077262472858154233636396244088239582806909932908632217289601961483349651950230339369357000753464628057155408674715134267283541596405631951859452783133262853757464507350925215925714277097530323743208868817709617235840333266932238511318295899212096964161265957205623379868808694293316092414647676434981836004206764735852867696404825276242750572429879321921317459646760042174012720082841782453706780332146297555389288845620203560540781270509890738309123996526424393502137765915298497552499763957372302411324207982597361665298954646849895322008819054917588361877600593640369144163533229539360226399418003477962771646027653858065158118437188708649970479011255959347694409045963400693227932138666506426310668722516434377529767925448656574789923780466110257064559655235754964557655495831419388108536605489494736574240895092459288659646394506710652708799216558970609414050538340968179918552498791967714516053144496948771901205679185571437009216657111568391244067042395405218129547669093927579929838076916393439997074869762715692213814881456621679287761088015820233032013400459689417719608043763996449154507081889969903433463172508725039477195036651418540791153754180442882888628471660303173577094939575793254162691930659451936454929033895956762712044975066324426606616650587142324881323248769867859489579214315282230879683523943260630191546156425928906586438995130953892586878303773158694297742666688983886012358403129596536565965505901123646313587351750007376696713486871228885248060259960128585993237803581241835225254870490649700066667182061790694205488220439247371092601845826426681566925994037932211328781283977351297040258264318575187598930310237606065824570886498727797724306954126827269607691170597675974454404686529324637555811896734115731361562407193069897441527827229077095416605081629742290734704954184395770239757203921695053379538496505999044206155989666121268178984771242894529689172336564607396530201279509658570263822795133046256824100546278029098609839213919558070793733347258156640522179610496206159926189054198647669233694214884945281230505935132493160801543084503657306180474631865765021076567696898807495203685736726937301681721113907833433521677560757764476581458689722754251674432280040371895088461538334431226419294336724018317878647588889223914196660976745009692312115786282801484511548216771137644141254802184008938222492550249472455991602132495428270761320624114681213449379777235187298349505669181470323443284643814840281556217471730208283232437093112893834413357114149502476148239820232305393459049421893662482783845632929530072162750548658779505885297488818693632062471423722867809995946950649401862561528664974072359525439293537482142593018221460745211475999148896966756975682244438740701270542531116470390928114028285934028457239516894097074437555247003993962139633581092458706694773551120448532387671142769941577865812086629125708200094907362402036006907172393642820990423591047860752708116792399424164861593892750756937399496320768420104664247510092817558362521774394646728067624305555688863972623663766079444659329951019346991073968924185044567579200983665102357846660600500953878612932063521266604761994247525575022301251576421876810960017125337231302110231731706051800913347005398288287585050875358973977032324707053291771232585640683277406843172140016948431669802374641510378335557965637757976841200047116389462014480326290914124083859898267344395996242546107404421338370397121045515697141439248723262055865118620733805663603681548783800349262662306009427197023781997923673614901222406528204356140964844433857874944084141695729122887607241649140629017658883941741280310553438966464099937047601537036882874284800404005737685073467192060801532430483054622999216148433687837768998517652169376016514140488530494834582349959492336135797536456780549894832419854114920646051854931905913262616353141078060598780536541817500286961213389032169716291414068956180431742418198397863222867138039767957009415152337683167415812583612195456739563719735720429726108444815936004501373721135338890264921076562767245960919789671430868971565322781478793121643052882953932747256218100234018839397441500211367039799198454262357815057303840444661432296222580050793319821867177701157486063385963699561522464929642457935742323863273080733065356337168557587604183245078083921893034745882638395738672349841055358657430261398475054270296047574908139228269996824509932430126951501355817939600401408906648506521609797328476464427736309259225741743178590492581591839283325236795482392234662950768064921610671051806021724957693359986890897119153907386385623591228324037983037644752840888664323214607640700518190673132441752885690395570078397852272900410059684885449126017291920836655513131520040219615821168996763664072777568748621176761015642785548551562202765382599443199627261623249929036711041927693588898668995100078007979897014943615515739013105703968934475574874018117427205503313866325155693028250618198753280000, - 140370856924269311064190877275143111478605494610150886545366366911466556317218590218984399110762626822355165307258850914318342221891181783064189668014661702525609397365389404300496849090772223363242322136774612127576796361097936423754246860003878517408085574243646726669081209050170726071851862252653006455613085779142026931140934221095454582548560637110340217495534421405691605424794755475904976615835828091048991574293546120707113331630576432373773641486809933756515748580510030250008603399752161703033381341569122151534986062573943315351530644324501898946408243834891180342962722523734434104417310049168609365057593918820600024758620356883958514313457658927695524299648003959094474059727408251999873366899931596471044268136791217697436943998941485958856106232575219637876290778450461240662874362913877855721868204285270598278414202949833512735824630996773565478338990107062394366710682578865859129387417103327952425261345527389720833085083282154468732749538839595718539136203137953213050380039701126211961746075037678043677036978924828108339199090512991020586596886583085062134344758723772470618082771204497755087049009789679384293294810872315777234457892686975650102928806980972975640487275598162476199361489971422558530334948851365718997093589400148436780762407603254788193016991720346530488934769464255496238892221602486447560039187372869426417625649280360371219803790871606894996350398189269737058257113164957265177770214634561891150295067425677310616437954118647406048116589597245218734598516768782453686630179967179582177089359876935587887038992152828123741445448257278763512771165739241687655791025676629784535033609757725672070415846722218607325400770437851860098984129958686177943565994658210688471434409896286716282812927448463420355722970596089189512032489782561091904239426223410974438224003959236965788799993574670990157387501430512927079758586716585066337061038873136889830722663149668197833023373167499983397037831571188096649021886897816965543273911487440068210987963829706653569765057998913633348245606683420639121885814688897850379668181878508279971097536265477782492829293088142508373242468404076757964093661685396283900902731414446501109013477975785229422910878668075057433622320786859971047121851012847777308622483262914422231644547673090392476591591529589767757635977621057938138539202019395966313360403879385308690668180847995669589279391341060238121335662830032903159073174966294229342270984498941823309823172330763578529557282090493428390645631097281845844439381262021640712087528951316214403523294040763042972753609829281497667133427017326477534345038865728545355894251208211074521462382337729464509242327352786298016561810129922059305918464559447371069138420858083818881699486725458024406382491871743541238673386657745079515159607864986219322281622985319924310948376219524334702430682179802759532849196264196847455005053951455851848793637090842918586167470666493890879815356727662087741195690869947428293099553108368074693487188457758298734346577401916806103217453371964192104485133532881921194424073762624668331234880934041415009624411716534604540816374424961458598832946033818709220992520232897503088221376857514080431623846678606584546597332737686993058489646780740336775849401907879658844654396612787572604765436768755810969249840664993144540095097847352676395302252644177611116920509047098845037799089700364790686067457778712038828864906197634670888419906989970816827991098777543409971984223275514204931841066795890691950259514618474743825010853631237577156502401026736269995479320256865191855391885131667647461584268525357067267711258177471526226113772608146622984266709220551802400572794520254066487211723497992681407315076046379881726043051186280141665008422904744660572714880329946577943538156911572015802578586934490563741463277380579882188279463938049014094414265831993126962157531811912149178563235118294554552904951331716409090641420780399750601958302845654214429599340252602309262101552310542952895035575227167241783615932094375751626432632478936732195351179462190480426509584863443828559195521896332322840980960510690889900653315816488232698652986585170622290509783391034929174149470788333476952971010896694103861296024443800767861591292278792799346206501119453587591591491508731801323837068523199771845767573207204706891909496617223432748802739909368879822333837750425336850385885231519766794468073307554456880271136274033627188274343469438102015431918596377879925303941094973074475776378256819916975867518260065692750923397618340857868222151165376975987479249817309207998827719749943718010202187236653735831713082078350175769223873778992088275167235024466614764449260346998249964261226161858496187569829798946055071374791283350311695089216496557115867129326640418546866477506360686272853274640068289755609427870903194311355640440744053095758066224030367626248599631426595306258628309801302039313525129049157675078617211881402827621724821199732739355350738973671351390503447560472743322919805471654380498381306279620625767317634590991543843229807500756431123162760555319778364964143056813518249395263210409319433338400945070546084223679552012168176963520629404899120035524805450356943759271891846089155750870829680022884330520568154756359566467557082186109846481574371442950086537059431403868249777849260909603483073034765529192822549583024698456449567642066994207672268812716290292772731647884361333259523555397147777996710659937424226974540234349889666942086903694685203210701995933078844048571394364659692038871809082089576348096786132236136330000882049055852603914971672430446567921164309272498884525154362181431277034783526948244987754632264177230022829782704627489026481542372304141460382257672017674910811292830437446946095882566556044278974139781290916635077027892225169419477716818681959349555071810878014065219010882389095640209482083820924946457381644839528062570998464870288733456197555142484440158168724795210875281781428886269690215619234944885341117198233096549070547427594071655231710556453532471680950764815781554854242540719550278279933921328087630815920570953157723618148553635968289236324314633464464065659516267607172266667493302070457610367593063622304756897034992859879615105666565222225028402668966004952074820855838730914138488522492950759199320160551139590638274362540742159546058388968440303606278074260340804284035411654670526315163075208399796204016905791495008128495275318094963990185582895522396736797686931301633335373817631034416840920727381715683329059520824982015480215437094059655914807069536321221526722882887266741817750154302738274228440759816727999204171514408965454728974566609302962643312331176953602741521764788816545498772319678335037578566500691678232703902882753806081403838850674967742616175828721012990153828653177973703604159596774108848213361100882607830043235487012354010199044895640406043555777613417761482962856509604044110184073555129501665583209083346103747195980429699454138278608049254796531623727615323539862051166380412474954149487905109041072148781784965842223497162404767129883891158793597505964070041272449625871603327235037599381760044104913192340972570977722291359696518010550161457193671856328111849155531523103954004689125031958238168058386825615477159499295252784682212442733039942304980708469867328293685056986639324506721867553239731756518747129142943157859454288663154442156033509747245015113898701491230824984147455215159426188104292664690929903049797250169887148448549838322333650466193537059977234000507689662950486587840897271305148477091602212658963131729664238095557944330563326579767945675995225408515033486246618115569359696263278319055551433834346393615110506145153849617742605351385443898615968794390545254778111180134617638680784570674113828449190727828612613457441266384724129859395222282187536811889526808968028730560362674627838270915176030625467504470214472604063759157033968429492286955132542493059850382808250857768909333988167860639630532464603958956613622075094101918362179875231547840711814977630449502575417248277809186169213038865499365005055356797243905424354330369758875083166061207787127858003253062630913894650648095707684807298694293668796074875673652967594323882983619900631882328568858336439187038923561528926535651866971508470851925994612696905030154925850060572919545619456993526370378342956838934137916894136468110329576594364404712405255452028566026037859347330701993231405201224971007254111021456944725912631231526433412874316105318939622162144702368225186573503837000007848738861403959492936535996516761768508965850740167832236547736028109607427501930342479494082622944733001502806058250360229194080535677953687511214629306546089752788843071928900506988208455574328341900588881970205944475096837283160569004607927919344001331520155655377610707036198049354278271792081829108159698981715575542587302569481096792954518826625044863285242811702486126075607843059011349969652163441657359071081413829585958245104036321163200741804383115457068386805705721527042092954672423256742024853301048355409262435373932535503080858203360552555481795629229384214811991100692594645077254681634766357295746296784690949464134046469286647604784820477014160435918748323798255296700733324023091343318536766865211032391804969031004222646782152061698487214135198420322777126834206461752732412648688715808923302753296749319257011020156703883968414552156627499837877103330645265663457947960953732698678615338651648014549549563683864912143851224816807319564622759701544655376938509575341510901844447365086655802138614615967065061260093549104484353634816259640817504257541643547274610137900664074793310694273677010906839059716286931823083348364624643094266285356099025212332913570636477662403877745798981891593536383936229521174091085140511950251108512455767952798484298780999983217964595984733809369423162249573824073484383316194407315553185996554460620332076712384542961391054400644978266034360052764662109321344793986637145001808896595762878221944910400170175078760782224193626167630713716737628708728609759177209086965893222395854828550272469717412617276819968297613693234266967617716537996529519976957157041439403992634922477917476439471849737798748733440000, - 88873156191829371544933825079804229316836026205059601433523428228848839631784959366663278497265728828725836440635327814733163412377642414527226660802147310519523273193615110251908855532228115889127340927988647886067509836462985227412949330224567386670906745589587384584045653073935825361013577634114862574659852151574971652562594035942200116665939861518388800652876387801163821695284699496033186236624764767855690146708103707732982949863302590148024314822545189547751718055374436359569152656417751736195065629406133015258468413739201592984483807288031721759728838678780115107277904774110066829229288370477451136852483701215321801698323001052010461663862467352694488883562757473779532961190548080095527650644802573429284809532402225658431295333234666781456085754603259967725851148439515220445698595176308963524155867683260758657204157518777265109427062242011821444672868180957471512254159082653908404574225774472916771153233831078990440401498304147712060177995616340722507269408785089735378274932593958982163697045771773241171395566896282934625426151904668949967504251898430830580958551993392620496551722875869831585258802640593549434356250016053475479266216283955053282372081136456109295922762493171588756895652568983031480624072180488333022963977317860359140480559162706084081159952569398319585741120398441971277150140454401436571006586716015326202531928805644654688507066582066849428677601417103997739171002735610195451038382680426518722179554395364999684757563127475321515467677461270992443522185896621526378742506697808285522230114802537780571331100412948602379329413829517907001874629734564352108309827044203145757228999071535472092630130331166564621564047263552804466752686376376369178782105990836692031637304501411522863583392011917716817007672942528205249985191370333795852278145640349045526868880944870237374821668667343854380330146441482715072972907354201013316263567332705901946786308491183351630783884212836696289350534106305099180257238600757560126480276975454902222908868301536436217257976194720889953068474849559159587369537385182017350410483799126904464723334666168826238113278550690521340558617613688458038726817591775453835703382448517151396607210855098117106568170393908952852827616706636230262857212423225523135705908327467988823529188480097490163798669586737830473192500627457457408636281815654653787869318669843626898909355791835325879767265779091263624987330108303475583512073659233692955740049115459033068174206395049509366567069707818929140867557528969629849134632185981822793924476074054679533511453538473501490479946993931292275109666410871494058070251591384149408246394966124410765722601792735062605614949466815116853348211296883768203538095789223143098726192438527684445142469883534263913366114758716156368677585616407568374482085315358432281298519096028079376692413389391329906499037712876125507593617965607668230397426193477413932642206530140172437673207358454970262424363341090927949728164090616358402390855266764729520922350515639227175983435951855061049852788272846016005606730083299216207016090545553833787101148584028465969556077558023554873641201584557250970364451374465916970300676116462845840307889162135447121877096897311129794585016397779804423863334964292163801048052282909554735366197735946429561458856970354156465610703649392537070514758909433399948896527955827654969167780191650317931764216538938587393521369541277459368250740181465266307614378431082776862657359734981904366415502177698854691023645069504799774696294249623204588208962812612272922966571161640729703574637329716477209941999615217861119475977693400511749715145391906432478038601378349123139186934620063251069199942525926010966225189666686124798444410551206339360130400872619848961437387937248164763042239856657847693350784252978300938481031914510415705020163195497103374067430796991594135140086245000389154007891003943975902679721902415697237046229629280392814074277354121243811853349201629078291399201338397620133609484944368097752544770489911243609351584457054708388902736844981663131202448021032486160595643804775329653723942740154954911879866297262924610233781695521436556807165332272081624257769314477918533313713408247758465002633311066347916783378014627749323343013968900746494778709214657064321157365452430976061889715422524383774791023498511114771443063343754185056443463857296067724178818568815660364681305024384808222606226851408071485144963340118246092534885243038613914989154490634126909609706030456960269003701981578563904253309992448700036745720738080176366153851007524304950318309569424640769682136009580146960976831040232425651968624967753166065860477134787365922720918542675873667428978356931909388606772111592023998761117193040599130277850169173255098813656703586639717053663130463978557756746632568515325597434572449892777329955794441250795411462954511196298680848685499019173352119033894436166374687849482172703570798304225948994571357741773142185305838713342194939568126753107371700352821369502233251253307530282451346287970401714305919695615611945630870141958524276388769003216068936713742860818314595517605894608650682951614630310750593711895317143075643611409967917606314686673196716932782000148327879310236850163013391770482162814042574050380812850531160025137641288485522043202647230987890302383355204123239226499707283456474797110376787249280500816214901812704750107448180394349552902791003366438200577270537390476167138616200854570122981461181434015231848310268449495551577003570247864251910022974615352354961308556288822945231635715557814496022505055408125746081215211547381653606692908529195019011169131534295418971686960767737742196838722432592193447730353686697995985205156861670263229601399200867624360572543695226794961991852488150192892823808513628820582559986533539658904036661267266853988108927723345702694549196415326644704053946496349491148205076597022057647413657457521487691329122743114434138986975139675350667520619090079489227347462321035665201431538926789706179392014892568646186092613506957485600867219465956173855750070561462483066374351217215430746900281094250029300589513516575157862925956780754895426889365733199485315627862835295878851423153085202843211752378814111405318022957455516565101300917524644747387685202593885919318851675535259366476104859097657987415151786630700019303215311179199631436424444568728526114805471272591670164555143762951311839666290395712989690275039786916247077743981365992553448275926420560358813031006825259850374346349801552998381135648382813766168852452672704511141037279668112365542174496076765542325413852150971633201485743573695431932926602446799215756277647851331032820388984807214796465680893708995025758639526256323581501327844935401669512400550907252779935848732184092764242789513436176106817053458945383655813673098053185865382177706451968215597262291548266663722697537969969337304455316892594616156706393744825718680842738659555214583698467753964290924967083050787108942478289659770737884362990762272914793717431835504018200566963410439286739514638811789856975334535125231413743736507749041801993008059353091755171705812435068112279549198400088379505445078218326585605151063992397470092456240621407267275137140286431240616675754388727835780654032091402563505756328990723275982659772959513561362507173544496121949739435976840194841631833139401262965659369110989869232678889162504977436799511681372717699197230348252284453380134645094772367982698107815661285123680462504437481000451667686819750955356835124505815907849995559626694315091192022152676025419935155479207345756540213620877217689095424029930318663406392057491750803235392459573791196205480937288867519436852828698873049296867129234550745218876616896510434940981772098603240011411743898839544976134684840362434732410632391851465964845264006018129684289274604576751194799294238274850162206326924220547589655969285155536502470277246716446971618843445048741798653413044307040802554603221892232330489133309999824065299520608339701280197065916069647174598458115045368924396006035578236530151980446976981421177377121687170472366878850951774210583725811019135278715720152292945826739586778944148250531440340897245287720506970623192788942069324460327607824845039605074614248478750826451994343240987201433515899296128781062754813299229003101484224305294608027852163071873869087289220140699956401220503905322192357893431277661338701841901176122594621619733174562036244305306203049720397370215844686738757094166255924001887540783391590371211381759598205630161768565152199677318715306749563184127975112422207585458051874405891092411304499518960191173171069269818202913307587915450277410228553229065113463328835707496538337286649995880124122292465338603486430169649445064332979336861628474098497113625586191899075788503164662296857695619090259852328043421473235680610183204579088635823498620328531773030574969356496218056232932171466928710793944201373130925075166261160638156080931390109311412306296995639898642905210873933606845202367644139426151281181499507397865942268900344247088378089962079917274997073794731646213922864201052842315344467630539638673135752929768707408326891325805109231742225721009103082764005403922067550802196071999146205291781273021838156937881620881885457405316679858837654428954214525539265415785719073582109558846123815456766532459481904000125950823662353227854941900255598148578086332934256907880349549291246128114345296276696253120520763909184614372012061575116057970372214985159525319509450678688690937004265606332213980597181281942219488119037286356168882093545589373400425905375541085748988214352288726564820231000673413522366395143286886582395447917253302536953545394329979869899977275378998685431300077351257920563667578129001175119255113694636385291707512840121878306168702805179004518674754275265611050258788386297311357989430513463416503286369285972814334815372878304287543869843333131692657714190378563621251969867522888802671782032013209031692825157079599988338315407491990994212297842785039699920736809945509226516164006931286094513839909702465364783460690033166943211604249904358885646952367226297236010538056935194809569448792364288642525845190640814136999375011840000, - 52082095441736586375400111162964518952687656275317967132370947977958069969399250559680177296539429809059526811281480427189059430609524244357043735582410126672057376679210881967333734837997477263299917052863990942370367548003497687982270873147835764706309677634543672578841011094009470930107078878948300831827166976465994130245250631595010388680465759816298385097733363468221712253447366208958667337763025571010172970021179525959964639591964084794087291601075510417789371437540103259747971745341473272662283258875715250463756109718019876011890903503502084736067379886536945128365522028919222800844953204951601741436775155198162211374767499404632687196428593821000562990751841381442451356317362654073583127852562615578651884181786213087259052518032147017317968325975778239343587493863967523067158409138572219112827683789061518380458607398274653153876810823984256974513886453902329305583511287217298465523748999804831227888876199045866691575854574888800682369542790429262560943315638643325085904047055199726186757461826102198604345712698971221847947690483900142978483030702669363438473880324980249678106163731753922696639190824682157028929603883423272081010758964867812480048847137067881528478723833496112890727059874156402409281724363006587646263158208752955819424530733530168427687321725914419282462741969710349706981050966619241544324020408003919375817840980887123307854252342219547784604223920103945181659094293063885311340179942660274110460255870233699675272236354831586233205821411747491488343405858805108071519016953559850889098870134230945526581014606393877938470648680203850488963452180266333286379830930429013323429015272013259895698614592451183258268904508617299591436335324943174645945055816333638880582291257216886063701920731553730386959952067232267841257318954594176855511365469296289229233310880159740784850685048532256787678385846104642454577495940569045011547455604075801750949005569519110948272457409555858653495361769234587248813467238884226753500596272289561427071659943199386579911116715720839071205411368072504001069381208394787878768965805686988846384292389373021352096445236345626130626333983637581287441318755316086709453507002680554626290534487613151962719050348804422171393089693118706174440953976138821481954565179665919025165489361999493104078206984633937925750638361387968278494662639117525909052611027888186758692311350940343779751788239527832165673229987623064541238653740405362938854224385512001002172910223656476817782416816436974909396212151104502689854531144324402041119581167745607532545732979873581024682796639295518557632230893871841353719039669976421457403949859656950033231935830742622562445208163769014143701328263243767645520646635976500807077677274234715313004971446647878500798607967937784687119711857687824156288913789814445753817081160676446589264546952743608707341510270875041463238450076439605727033423063635478631582836530222370109031003374280236875175535140113848669546211585897382610213155195007046229631716035823440776235681999591424759353844570138471030747579053174799580130310279705391251783567852000934262846681734711759325920318859082059373949688783049963169971598565337134418298866029891048795210373760621799047057872786373631861171499546642181560735057455586830331165461810032113141898938018319543030126186367512262660681337892676161836157184025046181683731059403050369086028310105901134656406263654439887178777732405971793625348128755632168604083259134693469629986791650006032705052043664134226259075511279011280685772072050523645658266481689948267310225828842219271446495087896872626969670594948603483043798650022776082455156992806939294562878754966111198204218628088026248581177794271389057367322254470270726260709095693004606729637793079120834349039369183725306463379676670755535753773327079595609505243121526213026291118001024686588158917420760606958504025484404315795083698775139694764061996203174025838424993154471109357299538729682842261792919718226524900655008087596438471391681537681765382592865536753871100429343628165461586556190642240656579261791541318269864143432888625368678500845411340153046935099271752767913712736460420130268840373318956007867135905928676344826338040763400843806892282246066736140903604733491296939099087491463231032986867309037183199516468444647120386873741973236175010201810628541142004880671013142304726965323518150440565128698873975614959369176118364975424999871484737203917131024351622422242581862383591907609478616643735421145531797909067494293904992186573955357209997204027464672013250785928153777077529604200408919008316093076655387282275351373048680171428909018111966325911838913621497020252245167130073391267013010639213533588677309930431346246681469558858933827889295480287870420658207243132883189555864478044061702734124702341675790473419573083542765374702583766324245990167639971300934302165755202194208892358608885813962480641942764433459595188475902488616108545712802951344447721976519677286596625414070060293842564861756900757952075922062157102315677013983951562660712732656818582005781769166030917989024442065446207206878644574971516377159164663536767894495169657554276766878279499869140444232072705632480798063266541027951506046660754974542972159179338341650392547564371493247715610689659955081976341308476241619110806101948802744980833126241249497903240323437325114027472416108938762464177945396242079476583009170540945290821274102291366423632063326516996931932156405254160609425953295840222559162563543740934024611381107021361545443113872765624584466277519590534243603230009103716626459734742385604938426849649961412953902630145673149953004932968332703891589257548891412887474162604794987649047853852652659540112878671401899181214107271845552056825903450137869002469397183833480035478358279259404217555498026612370323956506157754125180561475040039663098046520603892604695731986677641173094720797854560160714001599490811516102422952269171119544535049829086077838998881020557203305208099329989566986285994741980073007083417793528070848183901557388958867352207062102469010625344521735124586821367195301601717900006910282563396849265276122296495754828191932008188451771334977500329271261165674982384507356148353590841173113862256878052356605605756602265040833848764925944123716542137250923959549471670686309079280865399476734695430311181254882270758641055213206821193038513129386580897176793949292673143891365564391577941654067677956413868531520704141381813868066087684296235792116957632887670434305581446312570859948732276644878088564311979772327369509021988451842107381344060053306185363171866625295556157490502795360347760969530099531828541555635191685335499099944392925402457753773918073075162117534488939376883967470112660268768500247914057149985217027094816030750181178808874526036959639097321744860596794232208987737032731006619289295379629239798423408136072865629117261536992042885835665771967069599424016135900285890796303611956442068377437904841396602171751763112782339243967643976364383942154953513832494460933502649711641090562083328824381715228956090862335027520806882728867434294261183277922321337560948933947141693840693188316453144314342738707478459440421607207562041521812533365623561858248768140267899771757764574846994146935334384915595494259538528136428700603050200281257866624039691754864277424000044461510206293867257889026670733645058135136084344244491245382005038507154726573278880806727405510581602136075316416519061951498915686283999576029800718336091494185712793790608438378361539580065390764259449099488446925492412121217930426567934571922145718780237515982554568216117842011522284887532817340673922589304564500730075484596000058048012286381439789339483088305251837424398224792360997959309011500721820527070860123411347872419740011398782960663391528222317169354685258462435532536325755492831004395831684777719953915518302692772451462291927237032901021658264252736721554923323267880077100339231751135540337569313616967245740961450185066925699206174203778346995971163942465663495190444993577610436044553622902455804906153539735444169585010390952648902191042098053539811382545624084287909504720112309444107861520592409144247170743348729621520453029653563598226923400769075979640484714083613134347387746408790311305299485755583362994949371640051668441276711356239487418250781749569298531960728967198501881661961059632523438510033315939054839601409964050059425447084889595634839632839145940038981627431321192820632280659078240674632450523016811210440984809135027453670647753910522475697410932386750200762024324256136044409169553986918298885778635139023140945611550438689074843867605760342501796752211842222277803838261488595121154738037640159758994995766889965496984503264091237019062834753174909590239700202015616225293648788370829079752816112508469290171630700525033121396465250602374557877550232992371490206160730376036652759186645703670790041536538566077094850623329065709809442755633531793491847500323447080733880349441166596520330928893653848677971313659177389589175222597215344209524150900008494497391535314774684889166011907114105758562582877502959233446815680865737383494946702815679230700523789585837094559823423318089505721777759275864210141073645046927774831912711049604922282236185545583783628302392617698101623138188472918706562077695187811057520306998999175366554453437274189841396481443948107056031140518398117751927917285355710129701834673729528036831348675003510547155015618936656162047328337966811995237003849465419765830644995333045831225480133680915347890780697855755657008796640290603946559209622185856469196346313945287669109177333081851787419176742261721640914652212141491374621397725095881096808075075445219177856092724407226482179355371515486596707008369904197210739524555432850022549092976388117201633050893052169225405185321211294902990082021012501541625478186018035287290376344023713681554953786676332748938377805904551882076529879583764917353543833222926452023524911989078268898605945420779895776725855607928706516112855129610967670095202226339165287810929170327096786313268068669321202338423974982555148205132269372142326896107433554781603987481196650397622599680000, - 28295848451799853020425257202467878613640845002439252895241144048913872497121440312125664692154485951119506236722833511954291997227470019852110289447200589785824562769981893728383819336263213801523345668045945422508065725770862715152626252633443705965006517671352538637120403225337995178386891225741971717737506833394908754446861670868790944137304830374106258586708378108489426627981281068248294693638769881527063806799286569859198867749026842320073048815376642113903934848721672485924451443178602359468778992625477489926797028124894019661188237867436939257125465641317619159767344255439003669238148698934699463618889619220422135187716180161275521917767224838760073962512705312875479130944927178945036360395555221780639076400550884279432129107868111115956594972718015076760496479221765089851498707228761541375672513514540710845950636144322135705879719773257315028944081134098404620463110093563892184494948464110735106550926738647691711574864916903258775957589525547428294280715530102759401471983288670090692555618648766468872952890905907013542554989304534994578588229292524671605298128437368913490539068884919185266621661914309115951486753363140414949395594767090987262110383810105455501577624121201285702870384282112204625448860148097655815117865656676935006087579342359450471502465790314693895190779088458471492466894124342249772982556968645191984867544376914324350078647079522546670024668708940772508052676365253503173428721607034527487957047144872936969438360125961123314956928447242759299887105822353473776133255959546548840898580263246286194782315347656029851385370789146587139607260148836496574832658213421929793820971733573749424641954365167730350969408901474302643242299554973849264022997837348035055137677831037841774763680592744989037155884021620570511450988422800800536436809268377535315554948287421677637294862476569523732082694231561040780202032314019451942702290260463460179053963485944342725659133177409115655748589561949324705785468088344833953859894016654979978938599477520452037273750408096857013510418246324632266594471835375126943750529716647724159356437330085640868596453132002733036347974062485295720509783866644568474436051337088727150596689157266744595877569495141369260236593450583644977408367821432211913938137970664581148786060400044914914528660909291597618044284927378193232599770361058484069509383886041404190200926036163210646287483205702624485767974877217164041793045474864235118259714038615841960179626803399984845947108042197729263539889901565022984921764913906447019900663450355452155595506688753195282416409995460641925917114582836435595801151496791029806461240795309319261872800578544068263868575771170841552851195046849266104445941991209096556691048064639276716760139264527604724120352187874965427899747265222247770073025546251060384188362073816243121556988584537030856563864340711636076694410807605862126318669229691873053193514931843501439273743496309488718690084531110115753172758759715239990028637390168064022566594322800471270567003899447352584794291865251943776370966855805103179428768517057343308800330616974893845608293813182338720335693924210781027255015477400974685104509881706437316230942842153223968003754133416535075582310297123601916768727789534977081793847034858011254187704347430290849771197212723063441290222265856323155499405244474339540235659812317094674592767038882859675862178254001207054179886714397922097145033117047975032977614780083649082299155427553990999853815783927527221945348826898444953079077571996407136151207219992366008646394116961926204752392511916623910389745078909564684646781449238357912994498984481067859469477046406432502803129395468989117594536717268888912604552656506723394416001462773375013157278044769970549835145217105836978683784469900884862867983286696115308149349355504986784595108185119029985991121983213987059456552714477254034274204378887188998568653377373122524287397402017715264979496494873015588339881177248172746246336385351415275539373197282342868830674711509135340037996968360192222630056667545692031430073771068008585390424140370882054880284181409553051016407734773997372374848536836221663677507282835587120682987692307006246938427647995598202667159210729424615286565096952132969947901378478485381853840238410825829583398096130146171380224145820373830137341329680148316737307956889777240986626799754361327762417532687429803564665559351699520480456730025968985629019924095101281564381171503454863730882600468272002590297986057315374946842602358270433623367366778637495089098557495747732634770159339489466814073440038549113668689894873624479457540619979174553368727039366558405339942844475989517748891507024405886310206761156895066452780875301352270527788996749528902895338876019242878149219710064188485130542951456764936071628380583761579540169781601421061565080576106307403451016398143322287640578921856335574335170663665597750655798043989406411542900575602093811897656001944085670389087469672085985357354545982491788591756026400343464220177087804498258904228102670514059708508186191589375842601160540939656650977133810869077486915624547715501812090035345217099322864059082187554320093540442649141686403689683827867316887015650411128052705991367287001008807846013610108061502533168690487272299565130746933760380365960831283612179304544860790267527882893051441410028934676047095997283494715134051097429652293427485790111004135824109722053728715495894032397623536436585732156880757191544923734502480584591008349731121425393523319034859052300810604827782860945425375799008133616964446431071517423925722460720545575949340352508005327708168776377793617834869582790213354307518863690422442271804796252978639478469833230283988796782655286940355226050265159909315977466699385391927728668421494145409596272867756384522661015567662791683558121727014908305180440745517464086879848044334146625825555266184272848788992941052806947362433385548977962249089001729193946730681251692687292698949764674132529939245460383235749605177854834762753022949119532553186911108655661109308391858738200207449422119110688109775209154681397835281478938026040744805137564875728419757390887578071292357581628891918513828280832968259339324972394086005374602041430893119613656283515592580385803199818570211211548331650860650853232315245957350696790010611526497569177855691599516204797366161539924362434024914079833551582129235848167210015936306895802086530269761282904377844662466894457494292343064357244687963010416685632097907053518973021719128873854814423297475641862159481984685960412622946445258555711703085062342579616566916430277637143082126015001111240990216812765768589429817468057810303582968256977905840623460888285765824126885033713239703646706730334905706105589338878708923650026235329159299693765509314604186145986347526856870840942304017551431698980315477795881215384715527542709297634019044168559528109084680919145753662754043255713276042486440068726643437782244017411033632772819307732960522203180819616888373893411493262763638565715319626939716971932357829109767541763009442553106333476995713461478949407437064770906642346775320538081071320748658916378179338337242997569070177950829510557531719786594788173019007756029192800979779822126407703836703240441497320945670296311739580453765993996158049626580330063680701736420508528766664946127166896749672673640479577476220583110505786635554897051655086114565096119157336869479043340615640673597350685213081755102926169534295407932577869747836918066101209123506616172307237671675860609030725395412792959095074810013905661224013386807045607263640268672140302329850960559781053832332242859611900028806659544183515146274407902511915885894372812046990521676442900537573642580183165437059332763778304720254560824115707509363988273821494655729489183948655254477230756506575265086022582938834918573003204202022084350606859107008391131134947337934541843685002238797418764835663581283567662688293237098695779597593443941596208196997573600492285920740835184491610361641579943561277742439748140844641660937779426163287098180556642201189029311912019735702747980236393531149614447113340896199984619711181146289825796475014010631899916630251807515451660876641653286048260725805960894504686746142189948370472188642887525719535654234313498597377889813692403865659043029198374867133371848390162412828197959840503492973249226198433791383436482632448561048481194436878790570235009022319188409313628817228933726796932991666555763518755449493406571533125660939303722401572720737795760704403263169426908239914080228261818790563237546969431910532190580007626395877216322002739879412112055493642936645664020971341822739437742867503130149406549605767467966256202952671501800261268771956644296146635302808553788968648665550353060401377899742785925842978314373077376907816985847542093717020795797777278705017306688599418001456748841849035483467936958503742655310338411588596736198987824442585804708841418334580261228999051279899573130033753167080153553734583454115680558291799313691974088513549101809864520499798497616938675564271064445297128592448428575360475345086268865052703934875531092644102842936453815880864461119807824225618210189063152694367560386870194821260356366996650470432998211194550022990245574921534492903677827068516028413219129707997420924103655932907359001199918830535921642113052152063976198531667838667901695079698868067069032573532521874645794026460701944715967580514980809590281868610661696593628071681167596679911410469673455269814081470198204069325791129691331238369188040361477018587729998629596873977639665580026655039601102629421123803992444649882642189654156379136360508428469693284022484418261520249937907822359753520450981116261134734533073536929916556086259570334535540767921166162333767157482953184172072502590455820649224393752037144857892088387996411402287231316376778697332461266920171161743750538931738965882356696069740896842139516451707268826803430930365196113774594514334624024465373422491126296195904640965237047744981027779076607719410243569674150402127000040096813082003548598500819312962819812956578894311268295738616116031240208669786701795871582721146880000, - 14273314583783558964267192685699243462690921864867341863290374923485065803474200541683822972366703764929378683096696949160635030869634379969192840155725414480851898540557127441988352070963849949835830555896037455717951911003013696900577080089989699043946270814212409331757419952090706523893995891840097255164791005242529428083181088578153416055343834991411720550107901830331231968534620919979519257819090969104913175818606868258126011484722259714010492236930226645930953959763058866838466046646960295907267974424295868868396844487148105800167941315766793005858399572973420777901913599832080193996448941638711634614176568839469528339605700722348193760526032052630307765958657544726039987295340198347819610884670851634096629853410019625461466621217148373336505548725258101013673997261944565237917505152701164188012004981717204477578858982347539799126458501399819725444678849567684109272431666441866920984191549897597723326434013276478608744576674557496270994529457715465615243421513060902908270743651321470636494201090751608773246509518858276886695325391729313069390472470388826825627207675661230010216470127889866929743688280571436979572908875278802139858361047861629630429606284515535856705520247049444453572348964729450156449683547773969987773645608129443336416756465695033291891612089580279878625840224039840660423708363045041465982832801764678845507856992927617601378632445184982912167283549954133746061470762066165802942689109555821085388803411919189487734416041878517084045204009543820775260779214211593757394833501299805181875504648489037881023726093334492471084766940563543193158924361818467862078231301948518247117816460398000001515125423932690803708518786312203037048996909959790507246376292736708532588836699272586359222673289051085266194123119154625827777428887375398518297038032720570957244600345056207032957166695431497716054588070145349113661616086831517098107875471639031520990151488955435661417907448882403205610737900851985977512520700356386135626447252686400936623804334853304844211677514399651490024627392988165034050508275020061200857708135079966200095073217651750854619479448092731262825570749526113619241366369784684233364844262877931097721240533693136269886187286274688357632080743180288109976614172079245763614025225024224837607108671553307403500747787958493768673951052339743798448071135660435696724582626402048795356037804913193969906410284035235247190051895872845701262535931573377585585015378310344034252229659614349839198393265125797793567422250519943129149665162142202302102908979396468507534196197842401942884193927100705628337547653251907084767024986407413718812766767759764990337678302950715034807065983014317955820016091328946265080239750467705135998985153353670209951792639686199615358186794532886878467074938940216715311371627774539030296849071235967928839730770422321252861502093166263380788603205644249117717623139434405340335001706408460571311511047180009360524674385080663532171511918345731060086995319597270473007808860940965612404946758802836141932059078372915590567480010054622683353286367503866585660045996833412402392912527920636099760533665160730183882158382067170248894327339258945031757502540071479951863695096202194305583503719397049457513360266404474353076518985321780846038377652997588889668906393101577211773308918723097783477850033766030747947142820653656232382907501932270580228557214149424473702229315033993889310487831549762639499630766876828956684784993725671935560511320539162256811701165292995146978332703214981646399431259143633652188025815176725914081235433898694498252627381973309009278743811160799161318575157585329177967228689253829537088308229699504377630685952614977370129174490552463017729297335684261839422781362380975767542154660800572209206777249393096753693884936251648029612642710213612310465104214432121755168645546405957624593577305779700790964467156800511353760150804910833203066269229011019892483326177867597523208450505683947295586444763289181494404031258016214658371639172111309844114574527118879839412394104728224090664840895020150369287456749168380934798527891488859874990187875629137229211434017789074866679542875470643738230232978307980034025676816889092788138991073685929167289174145840242458412941006283623421054414233598423823080532490190474705747096505449334847307988329601996604453897711436182947888920766814576870728804158325291597012616281221230799061156692708730351136481381444611342987483382504396198142446890282850888380635626477171405522130877028653765207761095753978055211972874769366304539438058617310481272003235283957492764593799991935176063919467501199011061257315079856194384889916190088135362869140999240801617107617740585124387348017539244872727445763912532727108627506853481462222168767940709412787875421458080859832436032908984054638524899820275847839234035230011882988784142498758136625812622697094989151461528815642009335424429865160873803121418746383958799519838827815543623499632507324295750416756507776155976879134940537740052618227624362775399595724603240111694164195184981815880930365650825950125668284513260006452928532067739787552187007944172702683702135271135356625597105424770709307667779744567107671492523415798076608052358517647429930153510688208542945080399432569212523705883098191786256548394108059213922541339454479737589009596651400435535047082730704211218720866407653102533833938118768385317712050221669014686551268194491172369931196411065325112965544942759517327670415164011507477023162188145574398398472976480574184702831695281552045747849627482394250581837854402918709926652727053176931880709904476580948994744737007693029570664933345697661971047260189919223204865947413906458153938462786584864239380763924268953132546663064180790978377684202244404884846525405847105661103680037119565139240944550796566922314191026962597418916664277154996301949233273704066511311832638378677759396028529384149646153148684886006748140020442863359808617242944808788149698282708248764349335301976622541683869287361520380537866430170380307014269624099240179249797872205464486007532678386921486931274266527094471927939352154884918078682813084682867366058184143242945988141817550732180291003668365486079412011294211956285146324057061238777267789240090969395887758770114080291850113326525902834025686955834835509685349448322987024763109785183795191494969032018301097992089687572237195522224836412906998785834009269616781389493228442040063012243397124483963193952402220399044298770808245866838826618340607217015032864963749593898591934004604086971978331474682052056539762897760438433152487221110752084074586851598707534193770723285351508844979360623360894806014124280376851494990746423655212927276498755864388369250782391120282394419623835849483593347847923126680089014580026270674481594236589772288669400387420066302787860085935769863366257885627582057832358598678181689883554625120000714977598596414105089950945395706163823833580526801275415334308055800866677600544447378274960774920292932539452035257834384822589371911008586043424730525938318028556229836596673168840790025490771738145746317862351791502021938976541020148977704763986117804913569233168062722335760844892118657703985836011780677506242202566036532313327853164619731013778027469156576843210516791940729406437817187812809563669278810019886065574608789427635000405626088155349775209596888592570039726782951752230008384865119501386397166655553841024432852880296059764319461811956875740717862905446130988633670388702554723798858207732789949034485363870371741260003630745628779096012559933614235087925333532009811684599067617815530890620604119184627425343706052813450250761513326695278765240331657229443611694383274205058830313488178133070617559626989839917784382954095724455214487092756043203287515654459210436796526337106973012443413758264127026734850596168721693068465356028490218087461307934683673056822201292532978810521091284373289123645920962764304749776889596577294490410320791128260233580647289059972704164802220538410052460227832229936477854417682880146772400668998479106840094857855665857927692156675621949615379485088641416303416618834427439921011804959743283262228585360063971674621407571960544487403467404379638182278010959188508771696966015648930896043716314785468617368999486674452679411446667906796642222316630139778684697421737957130762518667468972737776397206253300627174998883343976571190579942854449962436745500059067957259061491525283806076596092629396523332660882434153669135610401768354733675788687724641906788934995672357227813058148064568489618525081633717556446811106626748918005267152461069644723621621698628794805714162594444147480659258134097708036455138728353806068766344725549956171030052610198796580544705768434694262727321443989566663697280026900698950036023746820050302475610028131718059014615463343802642611308252021714721470829847766867298954683988165908817052666836548445211261598327344631740530059825868250675348487393317714946203475811290192211018566530219119556667608236414761080263499491737083371974309335362519356500631905758734687376865058708472239445164377440399614280731020544944196846223778854365977023078191991452905965459915530398254780379097937489411425444125066232035799773006529604165054733698917205720828194264950405897262558265267029245122117922350981538019547973526028688285589497394454212968190803177115505319502276109607700198772628798805955297544546013980112481695631706378272252402673286476726790002224760747296309433315174939711814875613208526132834736334072681279921912452829852862895985085982741445927479886937970652161958378430490930561089483510970284542151847910743690314733559452598965177255669582348557934216768083017765423443298098031292918513145299124536772759149659575668489616168982230592975729646961216540123296938541004501975673700579744880205153434660260582690078606056000579402149309826729277656654715711588459007416566471444807772711107393539402398760208545631728532532657068347400477316484109612819606222726000478799455638253650160840287950471276881664964383202850386214457973444125172926131287556036612801491471600188925709835609047040000, - 6694349250066328359010704070288913420086959035851140242381266796199537397994488805957579210889010063180122851190372549615528250439154006939898206234656362004934907677214172484278986203531164841503788405798050686839932744346441628741329229859112587082176689293126835901323642315561669463327815222599899629549522239184571610471224821423260098243346746677010229235693075077491925183749978274527650095134916918294944559458480929910835152307601935304912951775148402121661415031930206769186743257592302605121062299081677431895072781668954105542471011715403621028313266865618722683004786414224044393668461183736028351689657073806883707791659976338954570575765987436421727045739650205299772385976588977884733258227684397834406208182743501067237350775318585298253166251613858079172634595099967281340897321938529178443096129972882509135590893466579003959155192812721957517955895581274463815085277026872452885053915509792469186118672298263087531640421854771452805594705749881374545475236854675220739863218846170253202996067026257377905804941813099398681803287892725156970612082377288298093627703200879623938607132788685550833827470209817899133301161278566941248094044855472834750548820819831284094278434077376226132486246976407964888333837973571177401244642505214456938494040528897404324972955378757688398591798487177765033525550273833581815397027220361698674970659551568200068314619601373871459639949082098599231430624252768226728360363220726608293324935353851035201324607912592482337179433960324965454295896931467590630417427789387853156342814600816134509813024586029464414395059304647137655714675797850859906620886019082929810841857429736718649737302192731289983910470466559376381765760357188052518848530238487852374139547847335726622639639122375559026772401761763896161043301375116322109123655656371017664810615810499075552707410660236572468925765466726593591531707323843036893391335022918425750783667373478325494105049104655615248891173865758651443376139287946361429690975209046450122387950653204978928317204373776184990471035539528087909785382914613997505243370558158679222414359808386748898704185645347047784445252935719659306955629040572914554258394213827112843683375496321128703464233637220316520392652303968456371574509168753822952779237888226212294064437739972031968943247343576335107544681389054354376464750909488401323934334567459853444323223193888487656193969719450149543126223535883561950863525771316628376694351773969157641643433495345273285818441612940817009161148729905110083014115528767499315315875628811718129268495558898122010743896697036593504708366672517430642041912287215988593660120342062835008634196889983814776278704972180425793765296323273415707371724509655100959578472364345171849850241075823758902527124000725649450526015447606840646098312787310728749031373409351932756123285324440704353056048994481618559572993825739068163797463000663492012646070616490310746156955912744282161455225104842402077758862402459955158114850351341174914215123230014151545439476126968442864089069051449045134269960419377141064701672030458758266755078888194210119245595312978772314744645252557031387627476997346527656709329486095378772825923802501471915995722023133527745764863997404394065371792984919179581659883972615624315534461930866339055078183413539401073729635383098249086427127455685612733829051314201020532583376153759522764087773470028686673138892795613311152974896047161495318842769256314682722506061357037757506669162313509776217914147930843945986717041012665532195619148895248005505421512369929818213866673579952807443179988178900495894903055029887970319342628323383546944821787413623041108326825508554696428449344649004448898631070026612414253412304332345221593293538662353667357223622008533786471666214595338819531558174758191937270765611324839443187091973617254279863115017014619597326226636858159023795698733590488423693070724280354384711818269478048006690497095645377986228167620644811618811147122145706470286260951738180981825296792918886337117151791500419763499762111554894692849246355718518648884419901169790604584607895138040497135140194187284153231178103748401092120290500540742588482397492497307612910711047695873612899955111853215404643836812829773660500778420133977367738017435356774577690671125243402893642999374384727264132063887366788889010474100652237157115740788858401103741573499544282847971918564114500086422831829706090438545023741733569180133488106154714696046842883028004463782104406072494625220623782292089755698158029546437385220152387704287797048655345564926519253543121760869823907547829069906490761467684305609111188316566859220897269778032257508329145022014125831585473827290829451125894173069300584328405877224986834712474547093404372203487997844118430977956741204067669013982224837920340005058812132753232732698067811163642842350547658530394925705946922690729097137604017995388006565723687812938515670221429279486762421097264974907109469546533162109698910191995072384819467714114131546368741928951613777142255024776034327625173173434628397132698452065822820967920063705687900677605847104282251848153488304364028971886194268112263201970943876674840002688642372842160781865261271184093367185128514906983611820868918151533056596465817538411021253948818003697832322130680578917861228372582974267145850836300767200156440864494424758723457112179961154545132709528258036143330282739453068806985286487798033096084641936374686376702657812436193090048456328384416092911114819679552954795462945089804874880791249968467551804336607790596517023680809149043923566729804906899238373519870471468181302938560839899611224412111987106415306872727724941847795302540353798667402098770008089997722062853063086628688354781393142456244774560830547305253903094707328754499639531622567833101484001575175260333284522781439593987118333936500045555142165342955775176014408102306645233656769570953593619164893052038916074663956524547389010875646959077913440866816849493676254869858378062513408556796517728448959045177958865386821951403879336053813400298872404808268096045312166117036212671688491032664195826365688042516725590734762297115798619774342002511433734515879885768186767711786137759746939593680732395349156685657347617190191128867518538861461133880087444482201778764044569605950910611506739534148351124935470073658712954750674297712433231899479883092483009555782886464614308929283396273815834044491585871303684230808638404610470623595979319172898853398995762118052683102898062263069323984174508158274862770476771392727877347444295967640456457274245467174306266006134540756062683720248866437254846572786198984855433197119793289356266091902828131414086395680519696112032760239821863471167900262206146060423444510925870759158201067354385605704792610556535327841879705863031792136073958590961172722022252790316188740027339257770061474228736637727527152511867532073048442732547597404808264126405921048723688069605774801503419235671721113500281913255937280110708451088638839090919640141495596712874455463027235080104041888394913289467683104458188374832574870457334265800767858105992537275009024441476655059850999309114648793344584413947350055634303357190558753538617292729587605023394889538543971970906727554246222571822530765302966539914682864268607749637017533915872118326348594321508556059531336862763510872718592550730261048432252628788154050091473350922199498117963253717984930409056297294357141241104421093882160891580895663610425779365601879510295032303003563417805775378573962422994075426860005424965066585615985615884999381631271927943417557004085446858996101527113493650936108364582285587133971004298334100152565175990372203437559385763310938624662075648495503117858503628800522787972911924798587099272678932782767014845939266894808227464327865440787127594496165044469613578347396732463621559391162294321016903898813848075214998614161809869189362674318883371409275545007793554027709310309573311259793028462249425796096250547164382801373623017111301036668563468710316251853632514987334038642595361307123442298787850543156644778655653022275149170233112759824675761178838706983219459225084041621899548605400959640552710665369780538669297509295430258416523005104631593229983899766047381086313503732623931221423695537625916407401637890358850082403678528910469281135728998535105145506457588238893481891234931217695374570515093469145459314747233936287464302718942673676311394974243207007129493669889999991421076757474635373904881601383243696606845532461674887817326283915618833677665056309796182697877713957239442068925233323476645624615234373316658952996618321816353773844701726109445549644622758504771107795813853551428553579979815880174817340003984237992567585943930450006526852604328713542383582313122103095053653737801945318403284979362951814314833844283901786544569055659397536256111352806248186542725417820145334898614443202025239317108780611650179537094994784954032931357631592914190037443340442310220495767211637239397844589416858920012650440282975859026948572585229827999673889440143698294938623390675830665908458487861356212140713997268914958022623312643683082888178790015006326102110136506046804787640851417543670780211738218418297233381473179937161895605115604068105562990196329193010800861445889617887130294290942335140049361934796652877027188949306523029724119934963379612084482736855290071320099287980181664967000019848385195021388935250211566269041981158387249839776812586982099475475308799976274303174298723125090299187141117260258910544403048397831268588518845409223520851442235109818895979393948578220043850665834369189200729839158166093539196381530034653511100629464080116542435369619050924895154487890352360175207511628084754146795172042287938413079944430492658323829553286872831017532689561521544602601865152301757909443323525924997974471085978647593687183929925662303557747071508441982793951267828847499559208783953797706918679030129801430714332113962865566601372674362125847982096904858604257502478392649950580592730024433779003738586643372907138624752741042257867963251504610925719030984713588262830080000, - 2923152051120919387963803808282839892165378587246875244808566504528855104928560510657597076607364228003051328368326295701470202728202859911807308970528927602855867590026619788784176160177578714211015434640508923414209237466627232182965165748091269138414484341583690426254817656834538544730683286178088010060690508646390611752886081446151849663859646247772951142420516680732408934680677975087759846707420390626743407152653700271803485238587842181054245183981096148944718829797582864336575194853559803319421910272653951427235402634391164625564807264793861246310069661331240408965199177951100936212938006951915426808907785053102799279990485026755427920677484019841024936823318208402910659772602761580153369261611159896406108581921278037949464711536768604939601537097727657056298792326832929351819294281908556325072415282282321538652225314206911701850954703995911817849613246467607513252225399936029727884239251503026870297849237576478477602909039384138177660737071122558598513458392325137136711096953769593534182869887430889866263260428519233068889813314538898465231964651237502046474551253473843734527670606455996976790621127949720727771340408759204942184051346010686858998866128423604666478989725429624817200172542130961234882090686604808985096449225038175108668999460044492854463177848750544207003421239636584260408250086569231363092137807394270728313122376113053191846503514443041247317332975967047712607377991740066073174001028649604122832596818761762565356397311110940523308611402445311994745289024742111943721154237028689235691395620187835575525510414635537247999667708477805202769523114356136280197760385996956973736271403396743860005794589463038063982180085306882876381028299439492135276280256157143221303720027532163624444119191386187758815238880951726488714240332007994826943001421196594739680848942219918246345187270321907959885390543915915584217521725055980957539249912935802102119071274160716274804140846678162525415265209789521802571208343437472129202417415259666435613295244574969933724811133519347584058323727337245165882265489626268762617407394043453989831203387689769408322150310232586519156257212203456696752402335270598565273285465285039614858812567642139081609971334387913048874438099005480544134799100753055439341128846824961283904807688178182329678099174255295983112235287761965898395417749751563328820003220402759185210540220315350595337220199753798494547995415848261766545287646368101149675028806476121591141762312362424745236699784387571538994529106266001902679636414721807994768147480309914658970453606621055480443853780801772566226135571732287430375057034043341276604226229164852301170204733875797169804402856608644007584051955608447058110536261349625893795773725661841417975160742467657651449384975624041183444541784404264025281905778806451957414996043205063209992685379699708759359084572514933584798072405422622646468300844528641804370917643114253776630045729755969156841638024818391033743323494720092886366535576903316068120612691459572612298323428249070978093644975114210726037138034720056990238094105270447410032433329777071020623516248731577755617245724221265672241222828505383563114669344547074789082227402578852864357163954726853979006885237843554535338325822373428081155604479716117638071560381801589511551860483264517224883212209793749265601070085927273035433440998398762198998406744229777332002721329723484041910373441107069668145012422214439616800959952689138749142758672967484799478808597232200528446724038083638800831400083521560268352578712378838256522560846348190076215904161508584439478571542455783317526147950965750413928126268638205762217455447130033233933047843554009914943409001749958365204058865576594213488520981401169687237221420004330964832029187141597417634536108483914872300977539769247085681046202676977151581608239588066079408887469003656959917703776072128474766484689322910239202555597056323474915666715201938938006455616619124572770876203322694410034103350730415148102348168407653013829177578924296461743724603999013762793109752956828289743243861425195312589430829123011197782587030083951047703732530966898016183064068692503196911590747909188773785364956821620206268532018542263706990061125689307661987552460788765184372325707369820028998272214464245015882122496476004330076593306732349594878145156749494694502232826717663955873528678424870187241496470852325501341189307940341198626605399409040771449479854144555125826774562837603588653831183397328665837477853923635545548156822579309617679378178861956539191559923049902325132641321689021990565348621076785726076371359051043277704700407570226937999909991907327607753963471222794456665019430725945634874576114107659495209882884719729036245023021514970231326004480484662979960632669509783361295565172755988913516241468421601775941708147922757074131663701117149614565921614641162818747613035350113536842080820480603944163002831041069597534227804146545197751883130555235888830318742317317272455384261532515252165748753298685277717162266905420219984010900182971277342161640143068054220999816360883155839944450811721608219994646637977679482945924934231854054629291776852784416850759372129366889618077693368182752880944361848088395369636535833422064253358221155240723302872544804076440420542744985272476920374532105648113350592234689052659903952403279136023543082523803324324425181531911149184888070778243475051433126259010183924013425536755798605547439219689367146122867378624578338395181222261812804068703789808641569539399861421392434372886138575027455286158274599478411358993531265173371587706382267109102613345347250726276023678445374243881176026741766352828452514704316709447519067986804503690051597801041454936518426512810104977957225934139553125050472239738125602067400896054998889090865041146697207506976508346028220004849195742763765464313429650673966598004198489399229998386165481055359724401203879980893354524235558814516005592420855645395246009474764384502336184745736461008357113649165328455351478662167997196142649879832989052428770296841109395338220714395909868725500957447240103031445515635354760845782709919425080510981684620571106578907041249365458136983702271290990184032602963379752677314258804425717716914235428648003370278515264581609675356178020562602501185942552468661448269061113055370563141627402416798620678673866472016602241164552742439720536318902411850324277043446598389294327812001116949647393533969491343434090131216198056630826941446584720527397378045158105081956141284818246148632032515755702904274234034723360676328511572855978453087200881835981593415799911806576764972937550377045977737621462900172972884315400258381358083021321002303953384644940200628898841935155535938520688602895235887112345563891453199224223537162220827037959055196322370836797924377849398340150807124452378801807369227769341358624064993209454196453493712475298600128080762239629430213945779757959727197819730892255160159896896150762942683673206010873487424060579596443225820359283175476906386942120678149117037596529026375681971135312134436804212140050959598863990148215416021267145199852590729407122061737868197201598112851652397633041752633844262744515688895207840922235046741031947693814811055135825996926230865467032445361586092693701603700421847322974725079490755656816983001545855431218900056174529690952976311878756675882985620984971001657150130933990008496642525598268469858031390320765507232361159336880200969481961600101556633412027961314366331377814301086595086862341495207910250840544415183559933230682649435456085043885913969057178329378051431752979562405187792155483990801545084762464278266517543577779420566720804635445199511313090118441666655171994584397498365889444864025311978597175523915149759424373783791948030194264142956777703862353334949744846037398617013143856575992843850944347712817784697489851934098417870469127347739570783522506828415072934661309777471124859225671766742553339003721479780803802103820343441632851839963289225848221863346883484789492825780190368804400419871219174412735805557269661607326776605827393678057391201639873695333346709367768962617139652485909556162399047562997740640565388154865141684391985361501120978697170536949179318336084700926533639350498219787142404706502941951652509386586169269230448918165778822990148112122031403810598258676644167358721072263212357753817154210756316469489810689342462831593552643428273660037242566442077133223091033334742297732290796775306758255715366296213327729152508135908126634215060159080560030926447366355856179899807611916936246914001595439778070198683480740700910213064171502689007113274302597074103150523010138841245242985010701878876452172144178670763399889027046281118920838076803364099767507313938953188367403756962627051690459680593122658419699522519601787707957974680158997519036712488046436402267390062150157433628660751140718598715402030889300985424305297500215863971677525634949934892625019812199967549441234856222793885839149210974995155622431004729993912277810901715855984912281568067544564501978211668847195578015085858206959409027922236544772978727426500897703427920627885475829394305364677893409353901397286273045209859957951154324359535450502724236439436774253493874337196356244286275403510575612391655479104136670846934083172691184559542298143245447068439257079144625913871948869972281536923767820243408079955533670028293174429795273709944225650662841699971000137718083895710358478507450336152208919888815827668106790348804028075823001252743990499041727459120876755598366725823807382450757549202740761756337597621893325332781454812340043026797354992922452230290588154771468988783786771602195729570101203597777877720820400505790853279614915569013634006891760362999656816176803963097734323908328638406126508243322846312126020098965854672837879099912044466305439225018094104361433750966881503623487530961210947417163618705674851558814311206310126874717816001121808257758679263537716068755342698108270061380399383671296999389552833309560029290204836633845410479532765884971532738093905325828084027736719360000, - 1189867310213067891996594033826433993825939445081663981395594402736289053973492089178915274726105762499564844260071798998959882414189498838283560521637094381694681647434455807189422192588927550969094717165449725571865167119738723643687217427848879192898755292607765463583347532915021361783517456811144218510731399506540174601862456084164488559574344426727324460096646146885649222524005750733998778824755869264312657637913539336243323195848428135151277446336299705677955977614789968164140159702289531040361260277948749816064362411361169993987959988097942309647542122628460322902698822635521790598817762255417292939075885372987837487428293545716033961282300967828293890716416428930000065737552493312216968040502176058415431657980621726111342493172427646052711382939565676323080000047960892948380358277324350822868493542584113732626834423643977752210226301373677885083383385850040583817934126278768878065650320555802789837999218924437838250898684936268414910596348402821259063648318665029493048509348306097057245822960908870570325075410899413039589775452235751484301070617081643609796389457257208511912957697802860031782245374237700579656548554179096530233732905546247724500558436673498059091636223850612468576936360783738894988108732799191606379084929659144262340081372558293119528140139798153387895365064291770781523958088946792453957097334087735314509454342742313780510252063894786869525203951233347241181157919611353080908747142733992521892356061827782456408363163988021340173931761484532682268792191223460166674385884576704223473413177840207052198103495716306716388775539245275358482635846380240430778221449473192493053819372549827766325425941816239977947227715076681100354433457293905236649135606291905069999489338372273531214410957825840198166092545929818170963120635409134543558587258079722449922939354538161015764049981911082502292848075645964575318350294000596434924148724894477127409380581126175855250024776738808672760786289818193949496069854391908359104953262969483296735065445244216416193297137518899412998687111066888220518316698250069250360695152818183873589544530406377233057569798952393534653158877027958107470195019528657080900738503693762451910924073431765240007367825870094430400144841370163571957568635589302837341804528850364151985129189004002193754354992803523426114848614236608508312323632838001045724519668347671945265880834624031940799578294064952813206797477206878935702540579274576461810427613588739893265437649985042226042188365079193199965593197443497287000480477583700714003211184931169438205031269046379654731433408000271571866442681496810623003724472249448085518887563826720408077883081639544593545034550928073239311330135174917000947761650853916309767270902048516903884991777920100721255992753599255707419383126811360285220279304358980651397801841237308622239831806569175782606104728680374103488262944836059284332502673293371620955348314577352676894847499970956244175221605138028169988258910948660808106374313780896338587386577927885906947977171095853002731907737523359950910941886557208389854979737576829025334994839567480965687820350939507716564362888873123323453268591901134840796865476341423449966996316441832138596480653507377094824027935065815929179880146609024015242928977416177655715266006953369476960494060576149622489233155943053663269800660277216789802234576880844343825364122091312323740654603845248487236949730059896019293869083395403825863823166919380085210560925676975725463834246843839035463919592560597718754086081091972840339785772728611631916541154341474598511980179625836487929218336314735900271634493175324004910951485649078657596452212828856234397538026966030422753543038284110471782927944680918247292858031228496875810040927669377440253279595304622799151249556757002375744994592928316987023065920363686836190142635813226507913775089302914010057486246648105661486772225538314062095983618207901449626268979297922762961208639593039108246495336926762359205702016041425807797150559796846388573657569452883518879722478843147399191598435628288506636477291043108426517603090381992895516863058491647510036345367519099398090057002676795855471349149823943587840122944522456723312843782775997356388432347843075727789816856163091485393825691047817275956697150952127901747747602442564510225046552146327617283173321131106418825054489849184362341597322412026500657351030286462803527896767630557525965928897411744773035109510193989316920715714426697695408328338187908095019073840658044658908156122881253510688336439547847291120357624133328497637922731226367886513412711067763074351330458319570607393133248241744743944016944032834658509231788516101654509067727164437384731386571998077132820110604676052057244231999640554782854274987275425447961933670463841685150409009857173684222449905769304652129423083442218722416783948903018591294587650073392267789056386600355796354462970294231483399203219764984981357391577461040150958800897633261703175148112406376799202021008277770985993394396141922726614640575220010522519087151589409441811329680093799600226603611207611074249839732774088202426517997918892916111970626935990524171273189309744262741180920833607382808418728074605455394319556787387368288248435112565224861488860436057163843767412242401762641883974203330643289379522434185998339206977095399061745894585944557138967908732992747692565039915063188966602963057880301230311677867219033952560189880626905886837840553961113324781904174594356279968572508950188921432044295939348133426947671475134281462553658742836825732395970674825141787437829379716003080197074244765140792713473394732269180458925013527016691080564726145405201169545332139569690056429000625645293715951955762118744491171381619963724946450341044377571907184725436791795507263215215851998331497411878471229619014076095362501581415864025010420248614950987840031006689877623529551009668157574763964989013255459387747343028481990417733719766521108295272922632534553394465225092119453595837588377517725250730608000220408364283516325541997466276542803476626186648582342285652733636453542920551182495156131487339240476927584193122649980810673821194622402500614450923214517107199896787341197419571154049401848741143064332825285588571739933175448348741801130183931104775113250355235542089068865247254114981007448166470376983133886524824060748757354925369820514148146014494235741407812481243322565781824979787325619915230256836651278366534396678919156234093811429227695285557558378796975788386143605645397294366598156069275565612919005167980648650045126381031896028399619440890577080673437117339922918887847728024656981902982476775280461930833497091222831783606884906145701443537611893343833213027563653085571035219101013201937744936817644084157608894272150475628401701177106320908773867640801041374545041876397777172914647070754407994669762738814125542583801673692921617027941739014533896460703812343937847657568535634033210795788775067634037436205123770727549872536028631640554878645189108839170144583727747179000960115376620212802991279835212379912688597405533681260182317172585651344487786306131029025630871126062656423594166440520008962258087309459115866609691667205792229256959502921681746199559034841991534348701560392966455550268669990673560815121924060294766432759456330603403637405887626489719799830113242617115977484175570836171689273175305036677172373419317134835992106943872084847994673703569186171183601316840174522705795771460293586298634657524269601815330607496224173907246089123756898742229272387741096889144398305170074767964344509414837643241240910496164910134017596040859302354453680984806376065456546960919484430523569654427420651900870005853774828706841845818304610630959918100561603926274922445744076393887885849599665313246538621102312113946688246268013684351122963168787856511122824545298605878876527644904274432060393658652076576295462508804272411369933491633578218102286452350136928208611196531393441792754352386379667557660442330022006374780136658671177749732253984629151839340277251378977874123048767801142630023799855742780986512397560717772178168464852949139613704403415563398444333544566386020875084554640494414326783370765690175373007459844703361950785643161378433011842149528931525499381875538130398095125599060186101786542938295710510897541006359375722777955334899160763212742319928040581578216912941580981538410915142458484705547555182700756536579555801235124955271281659636586528792779061246962880310629130739774518357730130736431575222872489761524820177347322678969654199554144368703008025098799802926650352006695411230612468926379096667757336381172340295399890336268316165744637390811846240767884913836529603466978431750559040346738951742907595779997658050951680800932678589028893726426268508755202027637570947177773753951385534391961110266558715486202968631594457225587749886190198435132488880245736996196137356528227265171707756187379577547685706167984333708783304820418044953062924362879425704710437217056304460977381726384795168393472211137353630367811592558897883175702777862767904764502911929727382634407161276355331163747885945351316129386494870382142649224263166708920200994377016534168328884192679909602904790057044713308053782841424819478566961567758133558791145528278763955455028764375039540874359067592559287473811606686102015906874264490620982933420980523611572137950853578970925656825848567077316066031665459257253065747816079758593210727710464700901535858996737942460368977814506311061487360539183368448234074826305876446232727153213359056724802289772756670879756157451288044070913315812214602503709481202321783697103330257638566467570754729580414194539404179924157993995483548642784929543033516799126110783060371268319906041444111189714349399163926155565560702283200536723602874483784014022632787521703932234550542146696949176608843164009471427685432325867742940274434625576720401148573180215180840085299654574781565982221369418709109556120622639477391336037156333737593575038877346527274765360696985516912775234753820772595450180793815531520000, - 452024931290194405668211372520551465034163716714682282350419795577185089238913355724592794435285285735568485039456200484010948148395139065687609371311887839899710932347595187406936355968986361664328951562572735621619864755509259302853295360034852799448571210665919753460682255650771261163513063833558593931578993500104836101647355552160001228055258262812554012443924368429990061919611447803938799804856791876405997745089302157343464775266554367908402930386716380256454302692727345314129289053638246205912599502926007747614575373072134381792003178850055427611431133700958393901837423219365916933392138477766966960102742760538846316199208377348203644416761880280490811639506837488989782798412475079475068077853805103761192105514429775667760234344741317328130307720974498195978322858471039741769208796776872677209344993243153188169845761221466939866996906906547571843721738112936560459761927597607298143721300892822680379730002075918314953098189891325479194133806628588336522402181694301297606905403039506391330137347505850209939078822007245621960343044218753892521544361924428886480213800867064727190603383222332904198251040217289891587857517642963297831871048836747321876702699699123703438885540861788923317623860947392535298166818472670716233147754841451660166029432842959671347765263271786025513629791720349562985301646525688950587362170047135874826388181159968555461144336155302390794999676535683483124518473872145986768003639717176633311785430858942049562658672063356899665858693852574177625309851316476761664208156471324007941862631409555504910927649438096506996823579353443089520022981107022840976882995666172725278833236347788398126582613922738783767448288845394336714406686181071527627356494101706375785599857250619117608438703658304658056176230130135041282593512079362099909729999441391070932557447673828371528546332137316937476945282630401347007409035563781024198325041583424677026598512210081171854010322501262963553836132953809262019310253135240111722133533775553882081223330042551499874357189754340825339547094369175100957232986505993840527604789645006645865611326315947318069238180163102416410659850629230696117011253974607782105160832588415028686656887481909683683591005061018673413081752091945751004372875584866560325685585557129427704352744268200945185185624856003237235081444150465738559930111884097178375643093657509512050591437442781491428024270124636934685898523288970823114977208554197486646852589384105022766565324620485549865139841572829527613880947991487483513341853694925580472504847332227224182271325832572885202405620022704843105856238729580538468578102230990403781699119308079385404515890570775765838816502262967036666873914470707610069542613355781531159840541474891431612442214682738256212028690109175131604582923637282450682080510325901942395836182208094918455256937142140753348939012636636583828841168695402202888359771687301888259344175630899931002054015872992206980076342441546947170056778908443459046974407723349064426183186609292047816186724197108437537250012712600232529315538960825881486659526429686768544031630392660274811473846654411175642432274968834524475336484538239550514624478692164285471074728076201003261936084262644828449764074091288843962542858836551519982504839962049796328091074207105625783904983621122080118937844036303457141801020998296851463288703383100836588106974735188667341238333052985669756642351864081706455482619801340708454917453439096793967077277468001704306444469556545474445627056854591849255753946041975300895435537957153223467753877244805562313863877834752302005636925287762422326332731053124245531044728144361124878364769694011236253172524629287363392277104296771123723652245289777064675137767196233780727782557393673609131054806368633368974539262332012259307204299806161970441174856385430614392162294257862318362922667390978537269187069400941395481166681679808767926776562226713596142650327534527400844214601241921111941874401318525769802238402304898291669949266068986735447937966131131477254518129160391653142064581685031206715133419308924057699302424855055881375104716014224896482946158711793507459841429211241460411351556724614262176904086385566001846312885781585621177599618372350372458167386134265174119205927946335026024253529800295433997808815575104757972797091962689652347209765748213025826905824042225604303727487156186782369452071428075229844710043942669065193829482527155325188003105679550307682483796376373894304839598177868543581254009484916788310995170065550751287016341641911248802311483002664332487927474896092237748149352000548575565531864833302573021487515172092573218038786585576233785263275483418440736865693611866018867161472193619265052888945157801794395297206292866999716579241881245695575957691647599357227580813089900642074493910795489508746676729213710102379371246975454500495454757701320504791670386961521468242501557713655554729480801661621437595002314461496241555453761888516454960931247943316058467769312432043442274143672395296143953265422204225495260721157667934995822660981163463648029066099548102708931816466425446546761390335305718676473820716853171576887288189681878222560731992993824475747533911838171967237487486626539805326368578412004056662523454186775433600019590150837961553161831011113367742433770778791673904213273691858440787662138147965775170668538356491468477059665146105732992302623397394510717015040631230550331283834285131345473574812633678944666245824218388414513967520779960415359146420533289548206948461233070796509716063886418398634895481410920180648021118104878265373066497009572303462459654674514726932382077089844767652751643495217975281149915238667656577371034926152144377203888779571569689287822940250793848752539034009774734261766616741568554396528536800625607330878409438723550756183582277935120917817042439406913515461598216402168403287527925469452478160829901220245239721489440986181532902351942718200548287275680793010908184243117446862141195153833222863757067277464334615467075082061229809679885270345695191147432280976366982429488650235416525712635536983474925156674838205418508399870590677593354756891328095100925749666135275399035089125905108435062791488269233198697380598389351721127412028818431184840501143238267633701393056057805381335694328821674179325874961239549823329765631533953605496579062232580847622967195497229569889482967708812698100387046269585963640455146812098005608153417948630052342271235829307027739050547907323915335926393284102645449973062585076881538062182909322825464144725866475751850231780766430985462705680962007582735862311970518039978950922503878510989030452593354225545670358234394151429611622833476628791760727714259739762132725776249122248859247671015959195056190206143079005435694746066420577326102791906331912315021424269655991692044011935652518178489816844982411051497074905266641887025942976499807653622093381829622238385675784747298494653223955051085511878581857257986962903271230825051987048762586324135687341452050577403376550511912966386935642106514884539449346911228135667151813737340265418258585250002106871154212131912034812101051682237633309931763770937615767268964897086031417909827862568501931755279454037999391178938245378288474463279305290440185155312424205953389705093718908164471649939251045866649309988867336019468190682690929478460070733149833164759746919370883648064052172015835820175381434759620443107355876169654624956503396514482087426332741713348149775687136972453590338656265999747807827296773214026855208665263626076238425741359445291079123819516179980804641652915588777654661477436942800943040249372485704110604518236542228193267947299965634995820450278113171313839167487480661391554104851399959550892748949037039469456602590612582656078321902581844045555554214556556550062211268742114039439371367538902021200809561745346664999293046031052172107603383093029796882225525408948505922379634386059754986676918799900293980921332927612098657373949914104502983666927666102300472079387042476611585591262400866999045621115940194002072758902632028583987881020291912916620416688946617409273967696283608972908101723547514375312033153751953729531816587312738413633918006707885600764429818340140610036991447527018127551135206463519845133642977255674586653833082327523424916748325938953122936417017130233487734865453147169024440110100461257169905137087811548080340245842416345627316908823776188443079069602202180240221872993690653138727355657081651072249040134180184629728294864492715997186730842343084330466938276447283465508992413209780881893359053757957404202898520364953568719919578653545059843747658743132769921610726508241776865532454844701839986462734097138907902716209801836347652500315824853564860732812362488875520692046780529894829665824388705795959982330727760576029527382016639169863150622497001672777233396824538661470484246478619047876601210907750936474574113176747272822373341305513569154679447121473059348179521591376725837389873115769638480124304229931235619487139852354939671637838123520293762853275013405800470572559972185764460824778089587892732868684187391293579763810597938088451301954725075083417761904623924433057969552253447714228451593773638631282801171723182166006655894873667299380936733680505123931641542445944449481861289229267178744867556705015549391464314346051971971327491483605950019440685944632510441467804933880824312571710685889570988794236703846250694954863168239171469188118327217726308728242750543554589834699172205358614592616960195993143491837947977633107224691991197154730065197089510268131520774624234898294395400353707799445596474859144168786309747945565337868172587032320994366887978431577565760340539787374159752060897687319988749395277674583489747380816539444709364762024351803702407607977004897120176821750530291423235246598748529097625513842316657761090844145634060481047208363786963751810668338036826009327512548895362461849251717753077689682662353361591825529605469355548670650077317342183371975427475500646429444871205148426240000, - 160444561356124790981171274385754131177246042335876692436272709153535313361746301536538047267169810201517254518534660899227585773379154881288205175821096714275962565883555860563118385339565719546734920970437426519442827696657990164252904991381472415171636951441074257685630521299083737138771757912591414264615960499817336794042658113421922333005735762664590597634506000248757519223069208017306178869974383795975065503366008256175435057994529096813560785900014260116932558565295797961294468814746842365702056996904137052786702750954746219309755786333387725214091759694629959857603588703919289053745884372640771328417261584140982156725145239337994231928791158791796481940330188773094689494844507648567161273248428860771581764860096914054971136243346973354140543817159926960191488192847676691737435426466395428363570465260817694952357091899243713452136709545941174339205289180996083897886065780096123944624382653930759636221004987748284655084235841830641820681622897166569248138468122312708000881105021624335508095152357731451676359991763329125976374000015779339534934330423848619133675544226672901274519028869602519129923989662807180931880984859585205692010283930291356594569126201371947107200324144829966058933308644611008170267140694814520031771079325926819470428910891512653739895212079622238229456456896935353647946444103838258926301996046791306468853050330145791061027179648291826229783071649401103745659440624880530634750489855756544898097189870486130015004751486094662164168182435179252451998069095680366949482955137236898737301178583958870658125816586385576935292605334877778368493524518227646165060087996083774414750925364013435551757787227176930227574706001322593478336182393904571729213237288860731459976904603311825995628196037026360795765447344908704257001793194063122545478721603314059022489372627808232908725873074345352161994845850860231660040445668947529853899060833943929796585334165310642436887563740695761710730215879397070576015260882439533290725493326837031467862319530891699803450584083628361665735255472487605948294313201172613717231638185949870916673403015404913974477851986310587827562361612078414121148026343650495906214226363436244219343975673020239757405167362845320974042214617713955350987340574791968153289668266311794279162182610523415866067530141882750548649993139712813430322838988104987140038703862799249224630975114280337829061069764270954630597943916542318442618243848198998215864431363318562461216754244651461198578431305481465480258068180518002958493167193585417168096690700520773187570634574332649967133736207673302983188423549768152347658725048282171066915192787741335107487554988702874371265426152511510261728034096403987812542516578739931807118082282275278437636623986905649763033956423287284479112082886840069216152520403260260409452993659533522155067591827447161551928314404226732976792240695388398071264511070975692919320511107725000041851364243863351925451339845763125351381372594302002803289567466089216688496615201001035721308217317255960508500191639480298410621709981261629602544944752122534554906379249398466431874363886883031014985339881927515306608466146895148950664424562170026794487538675609719145731954421982631442340662506007859933886003148848390025880505149438567920698672295418692504312128957785077401507907352896164364032517835153099487195313847813261587458923444777198425774545602710825406876834323000568423903995377306497857567020054628227197841231788662726228890385823946079533394017665886316415747893405526599217515993109029372774944008498174822433366289951222030230120802293014925467162238553259221701006548406550111389231546157597819993856527463929316052288681997322010188459834981951842346121047252462070488726465846683080242048284760711150802848085753580244142305830674273784086349064757704830422344703221896239620311460322644199467987684286223799991417599735760135373625751163335919183228671924732962158203776327565708820789400265907246902860948182358237902659902812664397173360420835549892976204610224194262118497890173345319942428118210952666678985804328508259474580872188848244777585366669438179721872706419486070211285690338532257185056039496795328714362622446909637046320122241355060725173184495038514508356750488231820670782918278418958983002028401479864870461249436256520871737775116558720386305094448708916753103613825093182265625645871196235259362262533776194079889649071026538723657764818507222033212190280917631030118035248749851660660557753609469803361695376909175199771450908812708293303711614334748123757307501806027910044860401362013588242734622128528600571756463604300569902470964200160906424529047814182847145354089095826183395586901781344887127439979673053607227821728487433600601904603344412624979602504255072712079039192223868410243434414724201662705718896879888162704461095177414315261088205429238281687479346769804194388631721049001581625327071384084848358364237037936805276483411807325509287205286062968062816177022116743799601079007490973483770349088145706065862407324902186255750386946366475892370746949967678145123573876804028795539491584335801765554985784763149213598983464294084505322008578902688800404733320114253003329005942311778450184025094697153217643936198779648059693732806852833439659343171392751795180188858814988035450552952634344171721084467114533013006340546376379966416434290120901738306817194700228271691956637605533343338321694277699878287481389116597553661315978637776088514865071779587895602942726968176504765743616524368084291149648387506917365596157277536054254020213578788882060081057403180067164457571572881286881820400466711501744005948545782059851112713790774538075743096610819538732554268993477006337506475043307927272334619601792346092002084554812674456977906505154018891886050485868693217420165182638899851533863364339800754172071091485004635277186838574331035373198406207789238407353239226081172779665761767599363611090593465038203677085759313356275579549831780945211762494000927980991458375208009668921940714503660195375662006773130606957806655237776098116795571482932907149121354817479837487706913373648051516920255842483729791933839827866319385396691213090277712283204993839887983198607876089094975816826474093736512898363574113132605326969810464296231005461394408098509414424995538142091790164455431513513342147494247287046808129141749619219185847002237396107871568479730288869125721254976335059848750112419630756735074064458560772506251721550194708750264923912460743338290464852093685613081368466695987183250638446000996201399200301040064303685144646645086598588028954330523715921934872853310089014310109589846877814044379304728991096145042780504143656301774617527234407446393293240644802880511545765066841415939334389721228866301826008620714099663930176568686133239102784252083043799661548821214596885924953935070774384206218685258133925041943390765153832969594346003498060046887659249867364382113127102204649809882803705422513685483075836219208974680006140353706600638874311273335915033957220585559680354653979081431599511457476201059200038165840506603516605392624670617168594107301618295524882675191275921477582400557365543884380664936660823968001454842958222875751141211565787477065035075648074533326881347323016801224702213609692195162273103562747617571968812939372614204863025382186081569670758353465220477239620073221976109755387009348904530147933164418720970869498993847346770177462485002821341094596807436854001894637268027948497749626708570700259050899616170328597183805739886683984850950330554010695184131738216670170905970339657799465030103654937054435761780016081041765087405162084202360483031081011513901854291973243860186695319049068078678263510201715270406123154818448009369656499497681880614937806653890178281128254392297574889241202496326470799337321840403574744772910291307402509168864506602728186259857582138071192492052672552209295015616985270899458050292312627316676822815122075332440062712887017302721314763409301549937474580953478071561781505165417768198967394126797685540367671989233399478184169818969667121953825017312489190721693133751067352705265965536805250961642935814747643371662307510747494395371444857788719220451695937483604827995781885843058880501212324993353151458286244923830528621257857970950166410306613779109512191462268301189748081920647745608625301147556258852278340585937188992214821415154985366359266458058685668265676277791062166759462261596838039916855050847649587930556034597258742536885485978321787473827086364070788288435098886133142037061198517469334562289043944112878321326119964637074679586798914881901654506847480392141405622363153956178896171061770580901488419307352099482723760736019748574212435857584563880469330524679989779065810878277047114177418930553675687780824847575475797468484603413991873547378357381351970234568279107576641395525962979580938750283817058665493464016450807761847558785131725891375654268784363925065659138820943503189296879003444964181647874742354905408401511871915238148432755179807306194381632765440473601195288416104088317844888690433356381877343695041876545850221772389232554175797090811840844513491222995063351907212938216294430974361135474164487885502614670169728836473192020765377236441331284401673447873186199729351555359494224636170244498949195467993150870377972163810117752449800470273188764374480572525016531949505957061242303158428750468899207759936902140367348823733672018458269222219546044049907479506074180898398996649948130945816613035647795612976451443100949980714343808475207402789817237590080507780644408441592453839382027226300970190825910188700353702969443336174981772253915914088299331830391359239193069544495581471319161380891282942619029424046475594073637521383615404330721378330204276118597795552518176157349187516904648510564426222226703779350435131178790448508040073025862295440705776400717040874844073528013657709111788211630163991600268957511545574488633561060789991003389774629761307509218848276480000, - 53264624918367286541790474539360052346406802873629319560944931304075147150120316076392839485415367605260451657642962922245030923551484633313957371107062234847190658920147098473056772417346771747769528331904015165521883847827692169436680023945148038714162783241065906248556570716756714092184565534569725980202605718458132472796505485315540489887172402296204527804444051675564540420115839687869188256867953188692600872706525012257408820079047385616956237309907761347690999531991494082899095705440795687159183509163329586974429358822823892438396315566076489051907711923977861572612115306560865090621561272151468238688074955166289266205449740866044988705473211530632779458567652061744596108573144211773998936596494542640770251713797943527536172014537194167581177354800308695431035572924561396594777881369462869074167156758238977468585874097645060982994927009713962311000892109938796085359052499901845993737111298070466119053413101283972282083099136689384554297142369787050024114890786269564027765569418081410126527146054499043285549836825378019328513087123570439325342835097551462357385666596288721283938917835145421756842682940325220079264013293173532437436894706974020011995697500224397047745019665667349368928600779224243369674416375171171929677005328031833241004521930651444758969255718623005978380412247586002317945078027226372285111973487526634590181065164103929556780554389503724262900249465160475656555096051915568330887127496102837871178849028559959265489642936936651049029915496149980442174307994873572910044837814263887725283662636172016057445358597564030600080678653595948743527623538188280078673152108146598003527930184305078835286350264482414973552877667987008553411344605481386258294461774923449121947519882069212734889861170923109786366540284313527761438157337524377135662234581570252414086556945179793101014487630104838231589328899530365425956951949256243312507319976690291846365630615715034790601522061354945108038592246804690729351978699888054332146117870146287269749219689635907929477135679464984790624609156509325667712741974022122759158792793356146639558291268209424167927421724142302265016317129882907406249061553448410756631377420910157482160593128093473371884288774236675814598496069342847655894067022061213731562894333229342320080260812189178029370040157600659299636880562265742657667711024360600101457354529216169213173478750635655341072966756254646094089850681021030612985477067091377962668927553696887067378246939632109858781730173177896454468859488362619257466827511137372713903911658198601897114311419251703843652791634669780012495291485907955703715270913861047165294129601945748416941376515357401685522678003626968440475010676651627241778012180638852609888209820180402167436685602376464395504812618148528175572786598043428886265846746487365737690227511930548693189493279792771128512643837592095289507413157405986243598603726014205119162796563390314798637247280572833022703017379737529484800098158888712638886453512240793541203008829592204451527952518864020621001620684043781879094523110929086852588714195535199718941233485247823391802971830905631536303333237591927111746593835248793488427962122795742479750246275362902550736212899218925107800848639196519560372296932743239541013322020886354899959363728172662892982026840640841641712953907219210003734764917942727260156491758511378557634597544717439209695106698355781581917436463007793952783913310574980699747382028721756887248235849624493257630691428323081351952006954067525195260921684928039179855068689807047463880937501255951055369885974590619943916542376241295687733607472697204710761392401666107065318981126221555143236708538826921119641238032187439277278541886884088878643085965672195145686803989794031220249915292406514296909232496100896080707770148189645547635879784594485382158613141840296001142766231616949180502473033760957438592795646253922743703188426507321927049906986819289130554393711790457385880368310860058081844249648687187329267793412559485749840238017382145545843468407571317914811679956248242050773394772507918946204799179329167544772761441746853800372056278171008323369405627254959006062587387221325970796750633046317632396875024860741110562165692058032664674967463193915651086367095793669076619271357814282149327897958130197351614041825813644391129693330487727809316431186849636962683964837284407981733570336492890880184597737478932908644201313370875962760089385649993544025076876435227521548164097322065499826693628934059443197753642978505178723124613954665301248516843671157571043643254159133044989582285546973283576597973061338739974148638750864434265049986906644362249043961287417430549092023722264415428552806031065378232227732521518888289341050326865238147041655158925984993689201457537971728208158988046051243885569554476148845340714819944331770320535979012660772569807157801961540732664770434638143418963339182121276577145520931507619861365875417488754041084419171891503508209430210972067239872841701848728301752646621629683354090748087263906177166095381573513244506896551989737646866509584687435949158233908487553581803038087054953123190198242238292189245960881407707458621070225764789328807208107802954750321715575961748988554991165307483871831246255202474268509954702104763581887903455066253602205832807734076623993497717559876538132038077948168821815960112015321708881182569339171287431164571907066760123173094740399962342924189147600435632960558928064061400914733818718927842185256453218462558148850338597261120756050087937492031006961224950816945544632063944143565376987787302455374563599291569749848420590531069499460037654136349844391725974888957456687383315099246541052242006155475406670833663646058764863186650355295373554828245455773511168070080392061672354648524551907030576709835610311370795824619852161780990083515192521234868224771097651912512213297801899233588140025214136942651639788129640569968381430419707035899064356511010066462744545700708814009412154464143023299129915442927742280229018622253229605047591954618708031207068237260959307252613479473966608717715274471494759779192599044037485083792967467611221936644032129875032053846407477967452954402066651250498772746454774516195651350088321027104648786432233468405206606881879652324251697341175922477133180193971281329778234592404427400954089152991784944332061856135135035221485451376134270285769334113194991658241905925047119434175295050579301825670559661213976259359002580948860074548411451119669083300955310907227495719859019370875561730783470553736627352671540802230025532968194387437483674169419386143625496129016756367192582893104134155738196069938577426795248154214470792585461108674950593410613796697275590895732072524043937468721777024650069882221349194351416303830893657471262056347628835877414913849327335261708278683283679904784232300787745937079274097236272309726417509849695969242632175445836144282027977621549987111929254444577310229210748373116397805406283072914500723780469092730346950455067264403368379947483497970038845358984883050748743983515980978864645337753145691481626619819825379338790113825613974283066770603391401162251772903026452814733256439714535629952125923410088238739809975007241471920204125167381678293391600075505376521259290930709713585937307477059045070018958045075825108712602626595151701050592504722713133734129459950346438212704153386096530770799584805510322738614383528346282384661351644157050627967070397904008565906716224143994446745013493598150539306261248719530038961278464828429562059124310365877046765884730575712839632318930364441020776701422542196071057264461190090780871246472849073024535400596789367884937947805673071557933442976626802544405584017799710058606290380734754402068901562361148842464687970008319892252683718569230102729401185292664359163029947322653617320082099813803893512114869236203358712010534994949516117439058930102021076810129617048647685104214516586816102963442594379829773914035107211892038734168139035659262593443939382009935867818033980663453261781387777356372441379092907340835814693381778434262772693200647769949177071167534160751905554028750639828892981253183295406053448089604275689949959864327454064157845424729332572439399236144902041617368400634783216322327900296534751668629223428816616621910767990917795376890822625387529787254232536567275089345227723225114791633613422446235218252834622411608844680080745021370550835416394904548909420567436198756905668876152519305155145248299303274209680705596826160449147016303997738403960985200927256108201532180195376347398088907976789114032819897481556355119569099070381409607332160301049310160282105906126647902558706282401548877719952687383344003102231123376061201951888401019827237094555656010094702842999308749512456567112925152280763701798074985544550917652926754156515297656435679917536800691062331049942720358431079119582218289042074566893953108207741932432823936377187809720146621913796898437124160943804795629662629927558677660795809784325427757444211720295470934762407405107852205343798188034771844377264948753217003383664604607758750776312672047910140893104931953158471831579448132382259541417423395284172759372657873092652604162247195094916025404264642251688900912940423136362951451966174015603310043808623237333363544755125424974664448236445779908090572211075666113512841331408745043777589191365389242222575960952062121103858556920359916224449773258291354939587353897934495948909411458335864445064265554550875541653269589083785234541892213375682326557426306977695779318707035435101339907123780133161487774540352888123724956004061196645009028065592914867419241551293503942337827551727183469385208733097387290445794085533283648861512301959276771541709933458902360962057895678213224146243464258533965759959986188537629410406372550961991224034171769888942639770392124605505280111625872027510121829683885466154845874074867995927054901883085655993358198962221217443957984785910951744869006049280000, - 16554951007077468299351178091414822255985738632697821162334568878862108094854023209791279161209713970029110207650372758733004515705227713015178351363110854556741637579159598170776989875081143461097369484310722227629136214046027786189441649465643227538740955355123903263813397166919772832304910825179728084167781676541631136416940183650051014087680157636570865198552097292100909151505522483707611818625851683185928028958630409860635432167738588540681722379937771737737512804688933570409424434648908291479986445799994643219583692256187087657465986837090589377917069810209228111806896236560452109484599495663330980744180127434904228328864766770067042695359134030800235262514311996801262702512082423771011024431692823901354557234483913862675820118708918284706273238743567236618859277440703940591046662745828993437669217906535760477563736746433486723860572688265208234751966350628291414779459248513921505033932889427356113549263618303094251075855152407586778279706748183108992361061859195172739704844210408736251085436269125590676745715393016625333637147465593746424554016880637697858324066286418845999186696444428567139544893202840542638889610201944724255294092461226023408958245241299190151789252639094351565134144080659813563103636842758043118498722072686365538153784552968742650432549110837759358581841708597693181948915818614383447084008651307614142477475737997963212855472201251972923349510773993280246182168675995950071934424114669369768625118714840519018552340763648260347522704318186924324688456672220074127409219987428578071598173101181783716463011423682770475499664658978577387206510445093642153910052352514377533873395566539058318895509851358487381439160648015066229429704209678447251128154553244776664202818881288985401959528709041855629223913103307872117320140687155717390624834989218664372060720123625585835535536242115849084830877620391029007499010145787230875601945122818205579324897003546372850520699935176782355395215110919942168154498631626955935998391489948997392523735994283413194300125099010618631657054865004310136508082396100857193276079617151647497269100543905300215676879663337868987459297618386452635962743449717515151666945013558557008865145653976097529503627831165637712789120093989920305548858129378892503883919064005501255609452237869803162426041149814502268344214339664733006398660870375400188761637790134695148767678809497347442584681862846479191039291235296158394740314794412026106155501725665185057502058103652466282831947823737065372762226994053722296563788039220950016830345335316406383848078343262428326063841756644218854915616146466919457929772530190369767136771055497918112911860757586825002596228300948000613250054666256512096999765147599347329791995192210787165381010552789719026355297416707033711146273557249767196706446657502403593530544010026235217774696926096489471064159947069691108936121440207713421699179916024364417076936847737455392933279296961820631506318270971591571087147002929669659459673632638702654356911419320167957094403714463890089359020382222007388853925300734248070654732930340716226482701923816208227077088679188852532518272396623597164319198246660781571068875092107845617539123446731824047704310888041762279703008026660860819483778870945280835427100404164418575240806793584824303458070410974787222293055462128961413405357429982052867332439583829802202130130644985184405559774593362243094377816931082484853931860122841389372170222534005306433898455080735219916737092356248148627582920753772292399796911993955628268641783055997620482524196869299280246938755108271633847724873865456553113252399469391393951383125175235712921733706324484555759699399947472893154747869160862021114658074260483825600349895464488871720805476947679641738970521864098676423818618698677643553294747711496146076538219108112043610044328756567461791454892068217995148660816319729104329033863371891812128545373974364910260239892698595988375388608966104624762591785096695789694953296544306087529889723463448206600766587681589118032222142227171901380571882464585521827632657950476819629992919479254288132146132894001654459012811965092790664706805135773960456599932406441526487836354128712396959837952623705595103467007458014096761193913851423361923397468846997261410823766059161852936466204636463035336655700000861283095279614239397368482710233432952468569554485090313990764078321672934401576385850147058122925641583771319309736026226714079590564272252645306853706277245082010166822568661148946013082420493175431240761288517694938540142387326921003486459608285838119010825752530497778446803694010356841421551073622953856807448893900322192030054986333349995092506113946786996238828106932621116460121430307005886360688755656214807954769993414438340234820850458211355152045803547477998080098026730712535251428242602434774361108983368593543706311689197216949230441860680629248583842898711388198857938036668427843523947290696821832269041551882506473887455672839156296606410922704686893124512061130926482695352971700065193793489416725413817932416757020171850518660280445305941338810843964479978570674474140853353265440168816684495981775260419808080702479182156588969173024694869987106618362056699433098769967873657047891797341324980065450972871528098989487024041503395580163935312306020832887842775824709952616419332472100904828364260218822766546539935911694014031402129704527955102080579279971673561690748361578860441343045854161104759094324961044776141802871578920248573173805689391551793739285146164061334960072492092824820431950052331999316602410294521282227667273796986558006005664319266765125637051193433211526391541077628715774177812916373983045116879153511088070866474250227385023367516541594489580239026160474410495919227188906625089455551077535822619464581806630354306453442983342225875778449516320115354134433399105201092976712383591280396145357432402224575835165838092492934318571703020477934081624350719163143030903126422659432379340255597094292115947579434371848127606623691331244914615541314750276557139225442145006538631570630312717174490501084650080110528657975978041427814156841549543805961578842786102741632604017984192545188167930024656401545649582668230728910517768918679044887742819609251311169616502055983184903637305723153966086414282231111266329602612227738249176902216859489490630375465227562022609277303072082330878900112797463672919121340159902471498716199784478111965653142940905742709452553576187449488071899699937840682940880327525496923549911595892149482837625761063542850185191580747279616553932134118357132156339286437842994930473833930578387156924348809740786658405703153641843108631519361540951924125298152073177727896847457292308629574275636081236881236752336444766053085347055502958322943200569751298486716162351349590210661334469901842647795687356463679498854584758198659279045224861667224049710209037303965533674991226595336131094390082047276954122695664095670384935997811273019899919262508670422522467806652813993153074898628331898473176255797941576040729371478255653220063504709786496511556067755035383496487464351787120977703177481356539286217071884625477446040994779311900208630243925516346846276832208505739965993503184599659889239676793275228534703518791130591112141190452809856623612231612365148899942923997305927054589117421959130864666084627035282902349048656623521783755126003809093538403327257951209397400485697606528256715545564914313664250889028745201913831957272467031827762753445097710757348821730332960740411927398091897406101776430832654928589518919795276939785895375211022069871916031457014987240480078520482723192420259041527149380550813562917389620370057702069564493369081663070295163269514797174826975928546846103454361453830838771851321040489814395543010607033608533323299364153548157836210545620271506923900715344799058469464116742012895264821746005056021553525257057394086377753397317894440028703163956866656460309557393023844143391691553661334682782840799588003106674270205075534821839952270335665870311688097858435891279471911823018931104974787125924435116427763501927480974253464779898139928896529628899146198589187612150969760295497271459812741345251616589965958100836599735133144059520801419403984694208604514745568854241460457433869017292307720852519639277589510010228533223401828104889028970050980962475247072827619413422450002412231792483051991883125287677377530257960043462601246704312545910224757917930792374955405679892116049931001157913592643532162047486892732972540110920079416025363719274756333809605528154216082182455704802273431196355790262414016732301383934324011189580109595398348425665651732312303688735049043433057528209102852699279672344973858868099246245958259276966846896977857535484712119759227395724472153925372251354073592746757108418511932784233285311348721303099266187956542891828149088403359321146466245673339235523036986132525297051971319900287482732198702499530102760736271428229934751049342907551737507075688572333065998511105259976065829086581936177645616705206817413527711710336427930046530834753393501718176339350532031514931669492533783392323397435079245862375454802842523825367408254978967672097124176303513782625302023832838304908336950593839413427579413581252969427363334331202665041530940782100835732367705204445988258345595757174472807927943798047310552041753829444252767941634697795370824170132985911554626947423459075243561849395829100133779322594352800720468474569841652534224057033686807785990568237172884436742262662740150632509755817951684451012292363301764395260226939066760238663166902603064844918455202677725950642602066895021025371105760387048729976926278281361731656562383816899662980120729279055208271332247872734297830162814607434338411814586703916345024659626396846924840624175994624914402154441002072844292578815323609957957781635308191146457321533387553160742917923387853844976952031168672127586501268279069753693244760666983932803153920000, - 4821565856007553335225272907475916029540959482234577069158990053829420294250455648071163416595936628563051836108746555030551629751453601975105977652151808655886679226216203692993900908853342281833549128971028556823754146993162848431210209787298191604212825101769316317478385645234840461345990492014500859019125403206371867847793765264621659975048777161009756814304428429443922634221094453436171958960639392224186265551758889023671869523183869230986846018672206548998696157674055834506863601163904703787875459174064527256483993346958518244967928396809851294613400042402570328610690318351781815044869092450875976395587262452624625534515441356725156836614612435490596271046575727821319308187265802649908593550863924723312198401421656695415893681977217722523904199434253132047886141120255059843132829273211965621819528052502442659413438186609947485613463740493269663383659065550490372943923191773313888017719265150092477467852590916443281060645404225543054357897908860835031145204746925834583312387352161540099635050620515099975594421222637649497206337798813224362583949409279758825585162011581597607030219767726892379551489937574039125028197926166021347010547661808219019406692642294636019340629463719623189855352414876484707975444757884636666509151656879963741285702871470116825347200705101876970467564696474546965338713946606600996813516268729920521596655161193967819424291717509705416308876093411954834770340075285269500615840263911496613442248570511068362310830274860623741653188144523663789341878309707617070041666604461384923757774186497277144955569356395972044030305747072191742202857673304885153572520476873048337226591680901802251493299048639480159967576698799935468687727631250480388028075353175554273301485963504081078529736978194880613494708634681534381697436032694626485856113939044232391140817880351645742306818902561926853476411881042960489482751146011551659001594065823630570843879212551402703531554483742060686044816485095018225745667980695825582286396297761206185835700231210435806678177723361100838964206589419978606651054894426802969390181905651142896146321022000285095511449304457139718610686443651632020997078909149824190029709443208410572368151578394620701294762354918196931517751916837838963937281191300331427968093134047091939239723961348235001350270880552314100986976001306757574090351709353490646219733054138256569236880153723470361032742710215663635665727337351356718871921581035952245306731928786817556828364675668434470998905750786964487509842066740946200811187002112612839555415535573757294602174199638268267567458318255433029913250901933324975690629377560358026804644852730459775343778812813967460066829666611614404724553703183264692909022989213541237225363043294362088899382012947596972401740267350472787361848174728609075533887637652762131844418887193698030714132060178665845857850982732503603341356508989885466369637525593483242156980040061019561467683090521807885667458702383607515036363908338697633663204010524368856513760409697034938939512397345494077092080127508197264464292640818488300809971375064403363236530460397313125978803145421701044074303082071834594129659020115543079764072340310160840486543446748113862981795858653328012160466543512382391596347309055230920593576767939498226776287144417742965575597381316674639279639370794016181512279576667211084040473551365590898021890220003193341487670896990610129352933214452093811146553982090392463167029421133173953936968064659763660705968512349724101531304891623803821496089666368339277570369997016152605578448619154826746562704104664869638252242385023759819347321080116790358400315559887883906076930244662785592516218140134089374637289718844817067764306229299160645929040335282042861235608796801687196809556214228987708556765227167131226314033646446315652125567304459915412538794913125641735219690189669917087094492719239827135070274493292869128057247585495449726979744341096560364480522793415306738103706830652092481051298083506179539649249306038072685183786045255333446004861302596881498467662408348646099477712759886731581857257165360230224359294163608446457048773936753633265464235031319930631067668176619994373348054326817411147850073851976317523138664230889728795039142050127575396424910774579592516574730477624150637423407271544850599279863211408470367090835140628878650545571760734646134442089503979613439418009890972990392745654786965288615101601421277321838812713501780790633440981585259665887361214534347246221965836702925757744513620164338170685640386471948572363673130524468979237402932032387405950169961490208980330479944544562823359877682535345899000592741710551011088624415651544271934736258115316679718845832761008248763809841194831338284574158320136819466817831737051981038517140683762612584609090651356804606430381716370420221237813856333101625402763052539220611848287280179297600873779362047980321969125292429139114192663147342598051649984646129253611722047913673030540683014658677697383152663318099101138928307230013122456576612718785606238254587656462073636149041564490098146599833272789412542603494119391947898998145867000261859364060223792502797115612457195995141488975016306777623765738241253351995783014379952592057740072575235346841542322868670488837288819854623437919838386018596388785775093805023698994804135484006002616600252257161840707706524671482700030776163321597572863010845899515674830225714346077628156571961031582557728674478831220444042640832122046773705760616922060383690268457161564815056430570201435392915155082654900269298104788860013423730038890402942253076722887176028652848720829192637945297922424418714300888793966307777273063227120796865928725390253455734901407261539713630929669838425769303081332003475265527866999804428086297912414266070253863621748572118532725873630086605708242303714634891900059309509604531519499063727739060396104451909978759580550163437345274719880764544085773789053092422200069368371244700718930054910410856290281117145889373918606578149337122223368655596488866404080447473239173574803011899558811981914917888118479281310669392910260391399203194658034324545831339621234720668756141068954379829215354425403821752739004626512933957711388256276912301868141364428157415351558461983538085889800022207198597151095456277882271435217215503171786594918430391777341075224313442020911006531932802683388868208910274204714386002487012836510963257964064881753176762168311812128229406740976184911561009002610753537497065256837612222739372728849242299616350035183227323998733956857085573885171639508411351151044260669554493922630812411532099980532718501670694576218700810921524028844048650717373011076580498610011954920963791340698952850718959559534060783188878478938197723342135009358047571660310475386671737314594628896802960402007712238258209082229671103797956253215179280606641343203428420987658211496916656954454014814763564184012254874035044892849520336035739097662590383435478047055692220835752859311712932677604486195864207471395853910297141405227495098352747332122747893372717078083529261834476241072539178865260009234698449416704298555609198421684905551878554583030587641758935257160628758919158805696494474152962743308230192461727930725422015744939434958317192932274894541289069352689218805486395154398781098183912193604867829519793209064708230343887693589270025473325111663774937255494481831197456677662567141467435604890188838638408789227451893652806322368693200443886300407331378448161424840000911012102316357778260711633956472267347464577540131928956497200562791372108487501442799782176612242514074569978577653155367349032651288861087757121466434447066801065217434184609732489296612611218885563185616397881109836601548315479949834451707085460285794795922862198264775916288022343166234385174311891933960439915993237014646657361499806383815702812092643049573864908062690772394983244659839761026297578801939672185001128895377368896429895797110589182795910578994525060123783874880115322728729659593892203072133062624142057975206352605043314488709642765799422761638528567465789569089664887512479952347816179691464983657975935738295034108184235530558910756738330707205213334935874257921761430535219204714557405327960718101559636878828590454121149467822513852627269558525817963443714516686123028927317179605384281865053160215566310829965350292329422194913567220663075250017148088148743647704680146560183353533143279723473064243928864402853213820256149948089992641544462826943022005164853832969174189382100419341713210434337060233791342437904810476940923338523616893824564455074042656203446956027345811470227563877525214091597826452939478157627036015831626665587692284880964900867862715239241387219063556501081948111303863544711663758374682844091257728784638447725386031777262384533871174193572856397001366269321503279363108524864569474936755370848464273105590356609875819830355127593181498488890445023294770268318510949054818851346016035562712052483832520154481537938763670426430556751369648420658058252922981728358123034932476676729926117765898894861665670313706397728411644373197029747468334680341813156863220072681559565523168274386123455733107209151996648020473483422870284014901964701634885264956861446834954539439173326871441527099382193788480474643201447885473991931891320611285927376353615310562981648772881045914940013420406048422458492914700544868759973852745655145566953059663370607231197252101693268837864352355682954934561412325592391604021396824327571663949564352480125718116522181037290501503908797535791195371775450891530390527391020078015785800666330134437302764274937821970771918120018320865484441086505948170647813219217544955064632023883303372319884633908867200416256747957792716401576837664718494136177226760450106578371125241975212071775069914074403297733448070329754709327251080058063603431973776115992034029684848902579401637750045024497405142247721150437147603787929951928320000, - 1317007439504286526902276915716446806828092095305216283809392273041937848013784691523639078908069834318053109785716650954821498776636611187449564684367901805197755258045784028910976879417114963219502958761369887329559553102765773325798090406846366373090692966445162108386957015184291285078198577128220238376733881333821621427801599797121209758333955758641934990538457207471850595295342939966450713818184306147898601834986707439858838893316306699535626081486813423605172304571578370184565342030871067913588166352013372450442616072698919001453853711868711616989284280805768205079862658022610966161726017487839756122913333881672500590912924040176364008576570656511667756487623742614556375744815203527608453543732075073314447320245633249300568453436754605377625227678180307801062700714776057903845597259295339190425389044913793986389437943705933664931046075243188730389145016151083847841945383162903545858408221738307905967538471691406535105110272355443339547958722377247584995514740394972727402422879856070796923506884377917896844882370317094351431573167669722173805948429096311296167831162095297098704065822415188500777295607493560706095399599446109484365016119160094808228855954282222040739474711396241294279015998515888394515341756488783438961275055243977795493400770716900784816105458389950440422411706281254965085758614063461851148136475087995422822483267056867358383411580557056666637084930051822837809999923112701946102481560547763742628424823944068842949665248374963096082948025227754517013239790990941945037187496916029703892143066159101041065094832189960919599190893015342342296687474531359071908171853865308997707189989439262119175980317718252556327055651017803360301880750549219028799301440569515693546777262948572365292726158444905372565292013808611937120421264511834237392064273844602492056780651792209388581379473992934287617425585656145047081090636973491769288910806803304813924570618103124370376008947717017247141318318172224391780958776987515968897584992119956354631662562441404857450772048618244739387537892332028105258652978041831043678964218977767760524988087732470868690915755817639461600562829483392376810884841861808525437964558481198214613700859733524131847582025145306211855187405204193612784471820595009775910654212188774532344342753746095859970037101329919918447343049397726983750218885786392764160254793767485607884806728201733132096638129681916777324148152928287362311880338632867445438815064079844179983302254269521736798309576653355926389537885631449930070278535009624898125239909376282021295364748519882795302520689519156360733529575788992100157492351574313745857516065032312820995096374015413584362610101762699521327967335899307298628463394910441602856350323814350415365181564930088147530599171789378314814645068750902721500495678758921880841396693080423138394061636587488148533929954105566986333311877560152417129832577285832469678777713035909815701953322961321634559045893609754544664149756718030829987665214596791310401393342376255969462008840684420389254076708189900037588107710961613234674839787943231627714905660587330752676063534463775716748425073505604308344653443056574887096761211417116578538916430620387287835307283414933364250954762540810435416712557932430774085726324386040254367897948219754323957892048843730741895744419267097289535762237742358784567841487556762417102404507014195491021694126020824091121528629678073317719670699624958979827870538469980719809715926060039083988483110104320872730714785748813594461156573286282757940974883355474343024334032555205280392301016105892919255526991821040103387475385618921225367415825228806106569621116049394487005645965848169915875536246541994525863089196029804103699278458921400617818605338248865714568048252524764342220532768528973053146103313231406710531398600373300152798286391547143663831895078344731268776561911250929817932380873904075270234871460177798988646766680254082916994142216981449518832627198491781500000245117066459173864013952289194013312369038461257321030740727814365717323030798262930077012799081237658672979712693315875943031106494855588405144628164726665590885966299674862687653252907031597013182817565212927096147720293591763598607320015163808146396609055644320037429409302902409696787112122258381002252359015590315899906513996764311811535548657884678080597764904151843626756326190254030293783557116987653467855438979082992009065133810394946705816161059597596726583928918132548232655406469238881528362059106401760537371918588193675768337055178452004243883403330709291246677770944536148668930945281866894988768240998385772224791357438480032931585039094602661132137844490543916953317497041678246735541215526492978144443168471756704496064760452446495623338855170976560181259603562482749239000162168637918944498106338767974153141061245101511320048477766595126478207857578924632497511430116647566947528880659048745391176675507336109076881567397465354912656319520369975140998996046000461742572058438176291708721126078240921625186540810480418652967676814738449341909743597698377014492486374936408936969475721798919076139549202831914891561262903412228650501397725524836917708563404821070725786064465547594393205474278745189917092683104660287845441259506380438367271169223330774924753021856035726897200594139859806577049608387040047739326663032075874439295140077407217653597068545920415095794464717301255237164335728069388856374799254590291935930568115561769520991438217594269434828070709318819717221210842391252642822773368975601499151801227492617340139806068542000293186234456746212422816259132295220461541334275886853907572339986853897531489159293144999517756472135924936698267179332418432240790246460203283042509835228748770135805925249839416924348543520127349117449650796149972338335684531514311390857446796539584948706571129846046014543790367316667554845133020038142641803030252766079936351005546881659615384871215207209297872972054571501992235340491014356875688153296613570276615475560414854425157495227001858690298758864038554435436487278364430734804797677514400758279029790941909163622535597579528913570365619455550677917726217121112393600945703498543236478970858113317344598777048406814970079809062385996095170648887004475041286474043298707587472727677738955484267006377179043787897954728899601272583983765986282851351063244549192671760261821518956653362679408525976654926943382292482072193224213892015892941978326562668688101155495568788810298708181649454537801417876004215080960438049946630620673149398501422978173788048465575138566582459889995162856090544900822779083112228879875188938384415383094208383796250999949420458447480139196470795204129734948411787068741998380162065342376309204005337372594078496145884292443977212926513683068679414350379048193879477670079433599320529990861163443030455231822800755730984399369470229053229965367417343977384530906269203388996500190209622108999677596523001049781380369182257096205496820643667972806104305985632316284458963713716500005245007380493515975334451030266576680784412525003278301401773694030974040798366868351891222201895869106040824208382494518138644611046534195915437603119149695636808991967047952949579328249578236509837140530852748687756301958244676060026435957193335378767335772867909624659271160543183472425820075035262360577263197850376539424195347291113353488129609575127060223829867971261943675520705993904056934196121233878812095901921583068354551074108187919005985625947785462717124282072805293322815570698242446742761360301597017520138282528974063116457940188976138973022049959841501879053452485885178300842930475379868268519115570416519695883005319846123498330344461080961728449483823520083266779485001130877440098637690759760360969308352702076090561739547332394323558868101419879742556867836936786169163496220988953085964752832289984185832967587077240671283540902794472425931888933576900851086075573527381671094418839448488796487016652116055436108963204520726403483293884538141912121733648430640334810374339019864958389866438485859155018782736911191133443445449400677651532985151146132976052921448133668922199727468429607713265066389160815835331602651196776986747562605035697886442696403743621775508734621710226399157247632253278398104203177401154731249254710203496284366550390556126221393749211937757192778332139761702010908581586346171716868839838830974979792671185796853780159768515492741823912497634828840546946829374837700753446720221694990510507853646117503398495092374019595155008449169432099263852067436547489980560350013011036055350539726227369813918908409645829744061176476075860663670547950167928601752296148599970073364804811803848544015092816458046541797147302511887340367349152403475395244803851232566702385501326769969548591656396879191431013951408801032272542562163901098892417325311664296683340424861029232537020725689353979243064638977081140122846563648946148535029864393620915983522667572222858101469670059295537543199760132858827356212586269014292589128413066362048499853997043913717514279587127739478603482217865512708198751027761522170321638508298735481905188730794370955384152987385961229609089908438371254791099254935271558166027445240151107662059411165039226325637744314719207323439353295283409919678830029202750131367181756486190584428709221905079406822965261699301117901019108311166706643854804480634582198422028609990528679129421366118167047142127211199086399844239854687374054671235928794379751117093457671328421492131445826448200920034604259639761939355689458559326436799825421659249642374457724670055962269812707622715530896360737898690781037424151306870149561842529141105220825814292388000717554416046920035603861956077633451966628343221645732667736276585858696971145794052591760675054028093185142971571986739795673945055488920007257497327917925384591468571735136051987624111487895598395757710932421733544456355840000, - 337652671159204907107794062253767153721162031768890692023196149482580957387785625563710257663781665755494831527026600346140492784261693647177708683075200198819224414198030512277775432865884505345315352175411600239801485769140921164183894048053151766647248634234954294692342245887447659059109723495478165649662568331235195229007030037941878884361267298373256529653457173958150370956523453898693546827336592945159668104483813074002564190941302917127578311042218551044473125820645482378412793430116990560319748091460013861173718695498009182549393378903918063083504615713896600886723781832266180564944147169874876803449124098111550757165828353904233159735380208541480639119682471482364652930627218008943970196273230633687374861756727921661836627059757097089286056405302556050569275591574123979799344876384265647130324394964351608080153083038536753817527901547234821816413091728379975430018596111346841293640431570726853921760587793277936424427633120144732692044179378320933783917327193399540019248756820595092862479497496119236041112247617309886550877227321821366478716677274589213040875523940168248217307230467560914569583834869609536559935905851193184203666927075956692343839699589873412661107316282094297635446064158003764504864517056922408116704706290427715144924860165924158440824120467738288822420588976163715883010036499306395752271812752818992409709554903738865346664064047299330981667836289141602547663374731785112282522642455621883912912540705293300197458005515137067042035778283737785544748317577218793673892133981789298629808624180785804879003825828855924432896269880444163595339722692942601323256110721615680997710864286396356244561338139190382184778182981952018884112793312947536799035129293288416133804294820359798738483555242871478838878594937557058927588570171563950339829719601233951220598485693340015776219760510450670171385730343214291487041903622811366375908744793109119845209423331461938017030531382025390201832528874031728305954129348281871052706741491002248480818893902231952493867019677275383347982695792285402049687506036088936874059900360666486181212809763174886549054420328847154008577700477768931797375615429941193038041453842273901297174171277290687706603985889015615545039326109731517174787775827805593185704357566323443114222506895796917664034648311725310497550281105522708789561317805284416481420817690632955116549031703991390899887131324453149444158929655436574448379100768707760257603303793473986592850837879134690606402839448449365535658289484129309074663118688428731926834303085953141980756632322472543378629228353664550003328896159935701423645489633395628533089392740559885619762080995886939879888889973921514955786045186414855587269067849105219777658649773318694876393273544439499353471315383695808397413584469336624229864783339193083298685331963310784046453507599168756851188919136029054048272856501448666336523901950234571156691276341904983513279034036158057287338522299212780341859129726735574335846537340879253985073869522671841009571801242317766612985339424717856786601781294701086256139911288548806347758040932555181337723599780664437844166981219270971639958537716933706630590820890405812945551037588223624065267536416047996143237564084156498310534438692800131480110969442373995336525314326966807162486037430724374783417960067388289163129374020207560383447226798014244904950613732166599647518269815829579945950705879173219480019481981688544463659172556936236005918019658575233908597374377421197743430503475778757518435555554511040844940682520887993692190077834799396383077040210482410318840391568649744022121033817795918401984513349122513403272463534203527301410728949517351003024499753915221960518391099851686371052561369158408171974051738386408351857932143842284016170397973437558983590830214314751232896962277009914420384883697443254929122260496566680041936197678503624556073057944139217303045641500019678586607057371732412102026851019806111086618085735250468429965415816798762278137651617842427612549220722506579592526481725800323046991140474101069424267676124875043399886669013452554746383571792999229434688043484473052883518429970385794760000545572294213234192488608928896398790391847693430338111311082536550636651617826526380159192164392737477666129606402864988816223842575167655156127113201603665226741075849443051851208885336878917673119060506997770351304428063468555774495496300714521763682398397663597566887726833284927955344973627776950063753401813335282982895896280071833509032992813476084583227709840216551608043468581448016707304777848307976926263820158962420117545600692067703461385128114984410405085580370554322331533103846827138052879254995828438656068805705753393716630380425201108507794576045158571340620884803261270246868815151078178476835148001603694726739088534868239048028068701744812100972913642916725807026258750468122308671494270579872672341586005658722636566466663983937408721408792676735411884995953212392720736836050789221159720150379487973085794740246123907278935633200154296363847418087152996959476921835826364003913857661629799978529088289441876992723911052199954504674666726945004584596748332797991177905551891577272244359637745982390034067932867502205585983831092589866521548935771917871591383355751315563623111724336229400463146593145778086050661376240004901469110011396655887098289339626922687384945292657742262142571413360615774462173609808777601872778587347494018406357882509106759874092550314020235700296123281821456829996991331483003716046328900735430917022749309163415901657611668434188370123149808723644309198684187493817356029572048043877312237165314467094217983722071853217617920329493782640378039167829646431999838134537100252311338534259695774297318923404056126489468780946676848650721822940787650472258921600563361615235743935593506387148579704853910288543969876314100130702465151981400921946631478429941665218383804916343818131401652227839717000737412925989519066999976995422321942644291417426244895312218997629745434733612687937087058053615133228298411203438616308717170931983035572538653108368130764962723650959756542833053887062157888898978218889596207157242932840847382450504864960605258059493296915825936389465310459830534930166226373019739708027977035652252366631242241415848351488007025385181452476439826803791007346610849268512254959168227648572452160885344263164141323157956951549942064228980221132604900151202509036481170888084486926012439909105443754233567542749971517866686560250813316485395605657211781500858643968217920023807577214655142252726122343300790263845835843373723009139949983643111155605123902490639759953786467361099525684441543039356056029810045198974155937534354392100640742955089272054673120235858613719624636331603690737058648321555049515221734387514054640530079044200692661057546729762143330956922986851541148608744108863446402505610246742803609402155536097502375735666280507275294689593072232279920029168530670445550195268715374125259593981922651172684102370642506572135748977547069296174126006503450300815271393277066253114724181229072357306365675352518353325249191528797976867784778099046596010260632092765828700859399631799778695219040845124877889482369739128651482385063521351732841301030020816006306271982901623712234161299008149988453075310838222023182981365357481790458468490653129669708661594596664940250593550876932407518519488042853892276030599754491237508854605004789681074242195161747265474696902706415736123575267719525581006714433619653428383500553373211284015303503015922990972336623574736297530496512730189820678810864477372457622007458356268895012370581680178987836433122769913000185523910808525767050067902928099805142331489404812741691288658310889584471469709663564947398054477059134815311085135888908078628052267096713014647999189772358254877150105615826057615295112134542217516969202998067403519430677494755302910661730909689642424696021971410556314206492871695098327472561067709177262096586735703487911030294447764008353968044452192607514636555451930732325542037491863169421514304078836885043882044099965481791522371837542174475639742079732161244587830459877128327421154550913448509007515247019544963383229606624882108929589111896961849271966880135347101965684511876595986720250686125894846653894512162092051931295115079018582844495841230114889477122945669250718345732228995810554120330755946218858401700072721418349795054998462881663570471199815561350892377258931000561236034370719395107317369674933448252009130757560692430115954939010647141820813263542656228490927226969961975828454530259403223752376601146768239268609337258408784623915871560496071497190976450352379197850752372951452239835833070543047632502270956237626400282289762181965974534113489952746212112051978172316047220532101067060111558333570667649354483181798254081677316367165405885786172717705221039863734267553389253055461897534716711439162055697603646106480966214941175495297099706168866201231499597360141621839241636028522695430327256471659484450622129970723350197009311869247302588489760713957850293865915155185008601640972357280611469629612056502219188257723182701744213018626220843838308569868131660530544995124157030676247202910419765496810546558873453999944282808758010574347427544881981789989071413524531135559511789701172953938793812215821977659362639837399733618178443152541428588208817801623953659578061088930354774331297239345942962594747167207987714892461725597496840187218502444688802763071137815695416111580484458652139296625593273840025195183056817739823387496576280648567727221555703719050381192955419184315317359963569127234927356859784744969243638430910770943208100881988908166848876143603731242339921495418981252558778596660058968337804946953588111097579738758913745205729378128593354652034934656467458085200226294385820455169368270527280080497992714126807940464640000, - 81311012144588157464737583081093212523888636871144621123195522677703293331976295479172448627446825173468555502860719957902778001896208588928061946867588129681931027650425854288481289413511619083536698442261502613366367427541148179128582150808780754940297612896382188388186889601092811340990199006980604190487594785714945654833523751885867773009513185087822933787027287165552000919648702694877245951349726697749841343285513011493863681409444680623676033859618244336066708420032333390782814775752906034643447451211691915339508803131433987521978675296053248256245072811074930295281913556716155178271751462457108922349066793883362526478104466942111492277539436465638030641538895212236912633941224922441214146183128009639834933684059838962941685036308766407919043454680242271297785823979397498466177848062776938054306880433788250074437365395674142853914390606794512569702018126762013184088033553303391712498372135424546458198299255795956505867372735353632200674993626621067316581656236998896399907376409164410624344620162961402252232719342273457282644138802999632448302320662703533294400028822695490026246476259333500371527884152983657945003160638124443758979692329981373045992897930791442660958807208999167296399540897068337346848558168618854216317939431544710306062906660077470326838508800659709380710095772053536041194289349822041456693533055027954860578884132329982189720362970694071784243669098707751738993092946034508730616675305706287277961161574280598563101697279084004780088686486506980247153174418583665723655991031509364555796661058716292036347705141043638601594293237685731858535328902312459917392847302914809239459399508704400251424777407139574472111021794820895547497232672563558456108873460214509560746770521862212967635105374820289292628682826249746479112753833240343192482639469700737906828145279949597097029410611846035882717298879828079016157650532432712034222709401948012605816121235367114119612025314994545953665537775293563839613730837774828845118257049188574057824692851660889300558083415157265333753017961922373394266351675543081308750509086136674170384193041054296150820483077966242163338038580315805438605491318784638786856001461672729217529500147463171699919049734980973969344410110611905536160867913269713839961733883503883857820102955411175006853203225104098890917637162316461489135787875098343446291387885049296343843923009612819300845782962541370459102213805754153481868712939385917409076316257895895240357888909165700324421497170955847096433325312349752149771484701799265975232499261988309821609339689516694253567074521291900005117323943654903569506918200022895691278036388737606700081051720809529498356381562538962771267288992625723515764932380606262225985756077393961580107581162124871274504470464644215114957246203001453744689513067119560987142193659423885711302480099354916836381096736103137040174706824915421291268334234409673296927017879974614277557687617484373953818936500267390599557766915963677236717164995565156576350627181942478402446364252200783357781546449717070730351851611153799157723567571600924747787480356207491737209453875759720535810980658337587444653928383760642041276365345779091524641045199486285391446968483303780779870188330575955991616483306697977613904757039483505805726244659622273869794216669988666033817726502486240450581065990261367174336719969700801353810580746376847256500347773603006561815924372456147549390605430716025351225846741424462319417115330018090902030077549202147086594282230874086654105637221059025789544173969985838456103784755496505930123099741051637145958398006455144319990427273013396567353299404546681380160574058941174490229529827458400467042674627523746983674813058724867105984240173384507350909571740613720478970120141152705429156519214481677699069206233445119491252955462778092716286890600206150277128324341564730441109556191878779489666034450293112274280024374195604857398087150064442083184070306180631418238906432808456518309246796507972706539539306320424630569805676002816038434619409830071853506144438806579805770296557382635925932523730349802256386583875055447138215739640896693829994597131871340068815521879912620343611193713558743678458820282094487115261767758488639809491712509235043421714567912836196544100163851506805719503400304454981203621393361865071160790853374607405741337828437623956628447509715208445976226520935244349527320162340484384482776357187897165931499855707896398208666180213328733564287842806808653613717405697501942637752568004035206897085195888129107459906618002029923424207316879023478537180663713298601534321317314729550985421086711597542801492209571244442343680651980409365162045339964835387662496225407915740486526390855294915896294633559556124439416876083635083468494164015201023026513775479494508045146628411988707290672656761181326145881925313730914747953967769312701593047329655293456278057037872111089542791742478392470396378351649043372374431339883527054249066741990410388483866340609526166165050241003384927955732209152977537966677762129040191176301963953777696031488058345276911970672428894152085524981412283968951742538403225135497194743869423932649868592235623983874937414617891622676727907271528274152545566894891602418158181741664912397915893511391137232736000483836052877940429244290308448589640770106141765740357352569897962503017542276242396061363477467128704962090446030686432536513589420272081343793127894031978038376972202548660628144903490063331016384520395834314765854718039818802422569040890208746939443101579393966718446600530014984308104265024536751503351796633911621878393393041152085804268340080101126361805397260911486494990717991485778205570976694253231309260572314206801506897919079123436036869620243626467415135445517363944529205226498210053458321444546789708792455132091373072425243484150906128078192372218413569975892206371385050017564378459343231737542419448545369179194485842562248038812943598342152332341752187075878295426896481503835298380908816437962866320029668038361918758376821360968100828553138980256145263325582635384216969258079033333454852514487660584660203274064342855774230516126847730415388370354731255401746925842488400307759106811496036264411876860224258405923891228441774370960290275872409077206004441500125854334704415183331472575194286455381296001267005901973279124137032799211183746271804499553069152106509277121002090855252600176245274255376969792417498189427191265673190931933276905422309557435258511628121848110409025947390134713643721804843186488443919189755668520937671576417723500832392991038815336800872005709390615306098303201619988509433873184402531228637190884838359669557551934573681812602974275530342313417404996048235544444602427365047035623025353529958119230542692838346650004039217619495575999753604174488502195548908627239370244635964234180160319137929450413509844194106385876307954315414295900496827994245189812590384657838769851632228798389989189030283928486718754325774446379853729007671863356112778687691618981357213234149044225066500992090188748580780435252639760813002307241796035209654557972065518531724476844833697954281377841459776782268086439443319501694121851726988228988504122902363182342128150738168146327326426767259809517777391376315542718325437104427246870216666968411098550767478929420046842478588259698203327371588400847571944240319417277251491292333854265949118794092772244445057855881055265298594483783138181928839855056270083039697033650539883156793080122789037897252040885356246116658824393812621800695764743969928914386494320421972814045653341677921641249865186523328849061320360806740778774283995222356119349755747776052513353341050875495243737084604167663015756776068506174452890614415337241725922215361387331470422213315375345723403502030701501775571761221471661516344896918797951963143588050048847683681190560689737179031028722607224143988757324728166642247050647639783398022962347070429647157942648133512198874191678914630327754980456303832091906663175729068976394792338154903444387555518415000199916539922046104078592186957431597667732676921349144458427438215622991871669777454835042280268037421649219482868934266663266042660620179799055082250598584790182797847386476661084898687233780639372192064311925330104511617179309164260498958089843672163433230647754589062705766637038557741901623129290242342929329177741502830483078545629887187847546231846280163054005887795191943690764756933958976565748794664779415068727264626205943230108796376414539805523092474863582721319818007461876496742695533385164250851147846997064100508279592541490430696092985305305442187147312011074382446692517723156857140004227556618172639913329690111664407072236896100757107452335516324615420417382471344260348829686063839362912309932038950060599002059588883137936308147623384296395744402449113650596594624741980860515667559505364918978684959779712758304536676414161285545079365911497593831175470473661908809319569394930992691080144435583578826261739851111390620692088198899449190231174990007193443713977358954278704444428086603980479748019634932640184458243621759809932665306232326543282516951736869452766817460263525893154147177496328633984183230692808734109174131373085788327788275525736961153641016449952576222657241640005572391827719475181155485929376850808786262848601699782281946832788148557467443315997845791225479095810513698696928509532590183821983972818389407480873100647693201508163920524676623443673025886351172556373048848752618068698253410076574508019005932343032040870342778422360087170187468888131050223715431190308080017474915681496242479575792420967618056012383737125534213351150959961919740811334458925971102156681693717787574735873805355213809997239294292472199659243313226239028801787621729751825318141919332390786777784633564217398190749117278630272619773952000000, - 18404106713624626152042596615667954686645040564075102012495787336597495599848720815692853466635916033743784272992998169983356766822415518519687281862719719911915760121580510672124201394271909643287480235720764369627293640242468110965476142565343078727127665253448856220681408292898032416067270093687460130546044783232581567360934098410638430240171952062081912982847287982592490913752290021939543082797372275637763243792859793678775952166031952135992635203385503568751940525172316765183715736017372436420995358469156554187607674462134048541695566047628009386291880792058691279099928048749500259811176505714237930149910619981907955935190749110706645380236353174440625923004556681238007696164171010314782955772435054602157012622110077210423508269308536569630950025151821977673797896799265024403786667488380139074886824936621134546526301470609329410530301829829441029678075071110760059927139090055962059597779866866961652009654243009577910459438858565060180671148548502018340722739589665839256141102949496528724481113361242632945845954897448147390189359471613199732931429835387257989451557747481001385848638409134987070356282295376620390019730550184319142058428052004077179278637171815627439711576291088516628075648297619363296058185511976454257986508191284337708796497515629986301132598565235396660070878193616304714167692982335710665648704009747603456663507694360324548229261988582315486004343681428411769865994546906471835694587392379659798102637825031682123375396874440328843664501486943878258606110910254937130103749260186280744560686264756151453136889268861537117934438579815827136871706797735352101760321936706378730047059992184427336020095887971870026321225275683957872983059503341144435574903374436770478809878120694859433712078404560097511271309381695731398230462999504093062169719841606508014367523075835324951313491658332749150755610747100596303449524613373705060875069938218972194663231290328868438287914007227601702280045082892652902965793355252134009604384154899503657490164541499834511493053078351188897585420208931460453346452941233462051423512186288591802563889715479909507500140106216829070281132696162065005904298716124093347258033467629987760315309172035978604817707776262691784615639615581590706318360723844465775743310582989220057788297218016014688044006398326394700097031992610569166234837196120329080144834532693148557781641188519388196503852995701239330562416018600323740217361770495421744542453319767077363859744985564160360486792812232690185534908925274976325331680155814029481610326372125755076048541330738933531159525762342378292514464673398954731161600987026525812447614814695915631682921067904696313821851967964371177250110665813185157740288436794455097260162790186302620868382536544535599867477198180028348650042080294459874098116416385160699427427781639445507264030679455657494306731841010973610509500628042097948464818383283898845887459127387001111772874692127927463724489229007481561900735877389412892431392975755510963484091639057806923856361354505319800833598570309722963452517953075845338102601506570139711363817553854090636758575624212068952090116254320165654336298934147886392439656333946643369346885570769335536996915804693045335235196165011500805508453100313004325369202065769479590089827232781962533611592012440869315672329031163516376812281712395688703361409471504757006536673399226342575649196306636689033185071614974774501588378830096978244677183815077552423806128107971459696951426100211322390182066744112227837663599385290587938542979329866965757366100493811966777131879068967701859311046484748858822010239295518903889332340880978562277706687437431463748576106720406537372307364145380266474333840555237375821213796213944017216226391911383397495031267351126820625279654026055231976601810461191784728630400792426139223190349770469720673385836605667789301477053731104074661099778678873120613127254986943282330893367341835087592149513331265637052000077113040017401202927792488524461946798836762225046524659268115046398123679347697957573102545264713392005443711875556320882466083513674605182800745752802321793464219528929964718551124593105847298337647288778198827868287931547760035453089776963658488579187682021027999192749587477986967353808668079652097442835456828962358345482130588466789979528642865639861905583309206190213749937526928238059035441296070343827998057022231999116453060190115186112971252483391304352227548821851803760753441753519406639696135321980966059892811505760223606718262110558574670269751740015176841624426044124945760915517710680584726056259636881347875731686061001060510469491130642875356356220059309773353258681221925399350341729148055395597283745421659809211743765356491346644384586511784503161396579020329792763253281339439766539201710916096345371554643350554153187503567267715882918551163315070921317646325537534212294148918604635729683779356644397792852728164027647462358059917738215822636990594375483032937530450345315981666182325820012888886868916979609024210761826895624670255178613609162573952403971606360869002734849069370804486830046067656133493186400208491890016992595253605077615774547757156707678830483203431110555345530409135144152195719075087460064755542260153785252829098171284952790440339647164644935015997309765382414356475816983445561559312830328011031997781733118891117273626497829349537509753436349467394354264637326264501648132148974922934446686051077101644773371316476202406432272914555614493014247228578241196939716438430124321942058659445445368214805420859142208228168042636731926459729085991750789615508893385745661645254023250949773391773934433643371253588480542289802880077866590588842928687360991464385578288224613664837274571846632213611216290453478180294588235198423762216339839650782485413662829418937389371507554447827941424619944871850214983950300893940821045683303452136573723914714564747239501867271801389821105042865934128661968225688716651378929543346720161656520779356398684171753177980949845126148800726744871535760766458578143688797303630317737162980016171123596891006412923614699580332583910726682765509371993264754157825811842380061673056277672709951961723438024581916333935795157454244765627078517770508626416484363260399953371319629751562172433265691316945992283412328711294484859925331976984348936300931307678840318725977655150593907961499337343892524774932211909929276056363985153071285101683704127179584212344105852514230230713006285567272481699103747461834455182112574623648401683317332069685252991239538311836946219013752621990514186540405850266378855052082145593317037605715293720413814348162881001886610025244154137984178616962407276117845660636996001755017712980726313247289678073734752142707488527384948174173010379793023201008831822660365301432357254523322610257280785501444203079406682713505121448869455591409966477913409780083186881375195986864597906734728823104941746611635913263206239035333653609737821792629054518253663232053758618794243968369260498217764955332214573897834103139678751275791327886311677141268609872157437708667305111218809935764939161050826306481462063813241498069647975561225624530771616363977916839450660714282840157322968645832378346938351944358962660717457582829836271183028008791324325672839730941581163426425891586791464767575945966366420092785792601059050823520550756411059923571485725079333663329035037805004039963774711833554898251034844694038237513271474763225558401109795121438631692537002469535948410017869317840008561818518912713483103326575156010301326341501464066220694192100031915672705732068422623747201768392910026823286664592653229621827349203437700549512472329608571138059801414719664615730339826588694740017121051946246869618824371034188492047052669717926655637352160497222768574887386269583132828338417298722191376403248795059425306793299949922169595130288120749561035041613607128321118231803118710033621566449406935295921287292185473157312116695404603110134109118465031453178479960522970989546591926270495994255150541631983735704473024792366535658713499601529989100648357776524895945726850478322553753598658914968790018518027190571089517436223592558951334794159259110444339751609392016951122192937231586933451623218488259722056615445887657337105111462316015908932251299282540485558271566508151806440707035148960767569105379972843975267097775947101192866353665884107701389655174376942993458767715146457601281972877593293512748219207355118797720047419270494399243652848211670872602318717798152530729017964492631873040663487049373450374593958704910747033460446499871236131306475973573050730459849496810137478426366037596298452147231881937600718192401638922092014901173753250341457000324627319176610438396227496509588675314379368082391968458687583022856816267949646676866856986013426562335584756484811586664880839377000755037293251819641516193257247066889821327514405952863455475721727425138849798753363186376991699974176985846208624135675338819542251672592620882109720452165762991222132521666200746222617565968814951334710398695670395958004535658884176452960612620860333091576594038180650000578383085545137133040251000792779891471929839698625446721493010125183769751846357130739902107560183155678927604041037598618689663269748331896555800378620188685065234247816035521267975921339074079727557407587434332211273832858002924427082827844592343944896768697784240778893147866802359932541033638800024444760461591359420892348878074088840286334897536484339619744573261617290350398624725519203772936532185508685638858583742634137185336522673214259584560448773228224164561275996779120441456864589610955639900143964586967470188038849096466697863046512010148474186503246664474602395654977370879711864046438139991534424430376642433450005881512205859299046251438417268994005166684044494110720000, - 3917679164486737240713270853572767204934427710392103003712461759027322791015619935453133195657788209996888293593688483453583630990466772642426513249054710355789192498989004680598399497480703739841295296865094404750782208508121818055928305283222246709367208322995510013547303635784400735813225154792783234200839525189663260130607438356383706149120074646013727078374194552339132392472387628458995716057127044709570623150984676044896663038318201631715336144526483915785656109267266946164013737496124697577892201972182608345230412433827627843585864863185385793578069097774610216446509398682657064436336266712527357412357833629164166526962527784537878116455116902354059622089715926760932112605438391479441172067742381807944011479002434563083123271546978181175671794747474718388419072456732908093806588257118389954705411377224829561363644449579078007149169384278448219294486492152624941599160720381691777949225474845486874582921332525799891222461184915530461709901629953032546055418271204419280080561223619091314093065906192078159275850349345161319569339421666237857423879525435822668431194880508552662294606064845541331439111072865954753553409214689018016067211849070018086083170757511998214035920871056865070257630729778770156291278638683452605778475892481636155651553042839675811264528847983213736056846807150224632898520192996058514716269236790988067237712783290998325937839837141789194188872226104030090056573936736330009503477966759601423292193734645732762732822402282480721887445300311751034565167278524441801534160205555148475746733548293696841212511724596449629060544707415564341361722905478729583898150764530523635588834193202032927737214100150589053033696986593217966068491646597576194574480425938887890004020296482807140223228835066965094841061124629506066550388354961473680612861528503129941005403945997611444317393702795966921876807285773966323487433376155141675248787248599887715251112780828524703250303808982047983968068916576240395804129972846812156417535816589550335844319052670057345486006388475140047702255249237311602590867636615339972477055514948455933942169074151878113865031576325415743760905585272465745071214339596981072766741207373142974495527909211254156224747398619848459059417419307447548456628567957409800842921148189067288878192018756898842854345296400707599314440589883291361272160270166889815828844065027310924359204370538958489188806213417824308201573373247140552780211218163717119913680543632112642115269087923713113151226702435385959038260023551312594492591792731598064173512714136309989872511780030296496467485087091022389483371908063957594582163522681991669124309976739431752273983197980094403890831102297082301296904120949309753846668229016844166807698054361932260616768039452955570860066551023544147455009857685616321876543933010793646133844046111224060066777488605768366868107702747377668822783341288909748210137824483848326339080289634356061500957530864337474099253597407563067858875899503723608323282538970392092394266365063945265795665825685988940492949770550687406715190768350608916068386991417728593433005831714738925894935495913088608995063560527011264617352488705929199812549835727855055427152605307649079323543377364727297816501081852121823122341776089001336275030695483554843053186810169634745174514824480522473521141141232346117502519018270672932604927254075648248644314588313496774967043959826925104759478027932140432005395352216476758445758804068412823636958557575935799293690154865392080450691029482779126074624183096535001120559453298520117471284821280574222952345148034056735536777279059988556856751973016112008955521497219740534641437477690898205376165071332304878966828973531023181412162239004506501461855496929150441004437818166797584383584260162319145787917397633520721729469813407941414159127588959079220379283025269048256381503405807444825729036097237039156416902074697928056943143243589536270788913333329305399861824020159196611277964575686914145743961549864179345458873857897215473105718307254277374496819889528544315116234575382499571999483806194539520947244747394460461002022091237525186388418845756012038607076147163897961356526002657275653566791646661892281141069032255440442296945076787647348304627881883747067526323136625375891543949016236469475377849568250895816689408194874520939627426667795060563327419017459878286887592478578287872529990789138896147336218340814212992521250226141549952321075062705748049176321852263603993989729422006767446492798273768990955168816523183924922344336914032201589404308775820006214358897255237069999383561309272278415199018439710597861195419585242714443958462274008322387817419032185355660788187399155818235187112068989883211140737641531845839509917773609092899194987371440038197463183453726481940123271067682238296709037163261324012374950872247735874982395504941098074841696544130104979382390746169113821033432192755259463616441471436463729800440746537605311923138871790975470858305664546119729160692690801937160089361439766900923842387460819487713315211300325295865853594903014859289501063964633149417316780110803762453800338903615027741643045894210424814649256115545597522600134692346769109008009413340653341544175559093721436432005366441940037386267218889951334691374878859802290183237085341053103738566287803608971395506375912906888318429674707740555890787688651182394357946968890852204498404322818046614552453322203866270576352383356531093364350140446584746132831583147945838187661574733472825341436601821889431238637018762209003421625164228799824464022711978453826553798548292850841817469750660795575652791820867979178774711881306855432080858685855058358009070156721386123673646548946638028226654149314097324898098736108778847829434329385015073114458532637269901301942832032179811174826915209259178103018768751011713085155336473344051013432211993569725451119192806168607858291051952640936458570199218830152656420678614908937442547540973298122587071829290454417967660381949036527816493621509191526173722652015762623291049226902876937642792458898074707145014865872154018524361053295033368918724141854254988001458244830422204117786196929806052618895950251602738138195336529442811163143160561104803744986734154526303713803880719403560715456937316131285441511999673588253975254127661867871770102492805550213382701467587464209157150123494307010662402064532593312660287383887304179552476058068252696421396746321322188093846654630071622916846718918607303467951379694385095351776421130411772704091212525592604256972746477584116848461371670538741227995722925114226634953663589068095514275828293906259290054172374834631728875536868902972109222549655754449915620951331043150677129547545413542895149373225922248857742155714161974355549571630270570450539113376242419901473509250352339151543866519815130332514632275801775513394273132121188629114497747580504766891185845194336041909824910304682861834855690182055628375254334899887970209575301123020858216973457499542876913361596491883980539809820028465839631411554619457721720044259972885252409445904512549460713636291729571973155047572803015882145750748518518516528221992232993028607961692548675930778201587047457122961864453674309432953234437102812794156296256919896682438579775083838676239553733453471199274134905209216966306889649121732833742624418913928828078679636496255115275860711564137698883487001735201787862742792654487973519840217702467650573160796530453168831381133942598026255592860073233981619938200931853809829740595648073928757249145196505919565361261906261934916287022291148234810020618814716878375454838121726872252795715704788970720095138297094858598786855288326238661872122266330993843570150146174884480321832957579761046372283325022827559892022186348504851715600085381041309915784991703141418697574194438860336434475724246262521641343202442361762229209735550582806646842925057797406807106962446334549180949813804551087369372758675863017521684535703330888662594335332595334719393659627165965398644694693333574386961268720175314011170405942721466857227127266627340940353027001194551135618419708588219549482043517852440642227560302100935193845488827954302599799282177758753205523617863536380646711090562578275704688462604393642673817738542622500136522110299237591425263793313638640139489153019394077159483449029512126415438713087410830094444111728515935799892247775065323625806190660965130243992176135861000005934296294254156345089107648807119803922482033654064007066163957531118987598374037408745786949638282747547227923555461639168555977526773181970304361949006362670114365098229770999341080001034190255489740672620990835610774323107652363614592855169601181826954465253651764432105262613981389217863661224724086374560942696649035884168475908337378045184413399716369430174747917859571088407557238150946990574286665993325202941174558901824334684833845088732151113132086170718209221544854172746596644675378740277280664552674767914090695391615093642523241769149673018698004758847602715179402830611413631854445281977605007407979328893739401451045960916253129573606036253128635130098512052893027646663171638283489187685148921898882636925027153090623281035028136837417217319373668477581121966527011364065227358157932266107554733630134557589815609491946398188283666729426704156532559284143498584635858267485120565018498666812922761334214381511388282807702697877815746139953890432022618217584950960627684603668432596115147736963107523899584501663009105444418307440664630347825763970962622748213882276808683247731237436189594982395387765268554412321489147761881363978850183306527789975104066833937609826417719007104793068785065963304343941896789104787593830668728509002051180978943244292054847300101987193147521782038642211533154989129923364362414664709088215040000, - 784743318888321879568213285919118724303459549608718814401218770437595413153928943515028287548628453482042727395441182310135293629856988798730073631061365014395083977630737042251928116818929260630674295110807756130256226245104630045396904468224720502102873429872214669102366218116361617798814198459826087039745924881212010122053063138845322359919909197990296200912045015257398455124014466983349498614718234720926046785723845538200876849243144321141422311903327800364507084551170933973643585334570133790694238750473902613722397826325852824346615639499070941771255956009540682302309575163696627077770816708590746596998463433655167703770161537488332530906545248420248113152173350610703427087888118089462238225212815535675891053261290899777180911775917098721934366676063394856825977194949105224264160906317898517782156631962000444201391781868488612563784935577983264746963005915993141060321166456092566162528617892660789283380827504969982652681763068565275921086618016652766012878597055726756241562303583804056231478445811046415544020795384894594696909539679854257429366885881118690470326950352616102540685159925751999273040346300600580694322269163073739981096859490332573784159038132046281710451061977448427887727226790431526111130840697969337055252205811887223019187778126395178081382937913905973876950701195636765809825416399476388837534114107766547591400207776684289704203520612549636594767070462335282703439993493581408998238031494485780086231617025047033837354600155960959529126188349059000945484445339670672328793503086436229083473313609086554109845692619697626846465754046635401535227465971818657648989002018503374605864856739639071565332315600316024680240870195417229726412450705296610412832186497464288871762695923086819046030433329805151576205623979142371475759569589771022899459564383064999062428314341472112456430625323064528233039487555213663998249899401862345325687417566269389371096778547547872640480912939986288031922708110828886468163165247798962206533017124467076502108482946869154952748046778196529564397449525169828068075942072536986241753705798246792423879542642141687268434600533253188555927682902995672369862843890417854941584949372153847237840929144161410949166423135358795452410707637598541454915757811449787784467677204443552288062587073638894660804671320607799975573024008382899430718751378550162762341397482450568294935911895022818762569408483157124567368426416859464756840319174102560712992951491580359398188396161152912338043832198849961181704368429116101517595352384169630926740775796684957416465553654338549021364762074293510746653117695748509922969082874919474174376637506486952470937306788660673189368356303839427172384639760141067765691300034913849201814649811192764489090909933937800549830675462129805923521835599131381545357166697363491689499807465457647843675792740373889403153879178616208903766057083161896295629317721841552453374016728986791339216024055023204707189498223865018247410732061662721755965890504132405229942991736805928246109984239449927612351379825558090559819019540939523345698919874021968208624081946868867629751533466661625109328970094267353112813673108922815145561340023128682512108123051166358844715068711366102249157358375117714384468895292336053829424833134149568236872800318908551247398777238057178127515381561316264263273372477306035166433099685223387107081372811664870126212436421638210530479797656485892295277788701996156066113170188147087898116030873091519968190456916743805076998472434230179588787993132149701850930927964994195818543940728070065016565800719410417448291505968331321951717408581100422953256781710915698350683894931050424814963389710084620834143602328601371929339530154378432042422679308946178493015868218684755703773141740222628640133678326532319748890834635904885030586273973682546138864701047461250248934822214984028649693658459427404964878466935131485033814815718113169862610177373067759888553012907016786080688391222770361853169325184184116133766891675216568338817390165459728018434599176153567833064708839104414174456635528661731155966554817725490854025148267200205641632501435959509633318255894791319617570616652968608490364114265552398948065585968895350508380546661125566802671873179310857762751761067135109615431573310596858562132890934174353430083416910082866782195298159901039971051943707589207014263396954912759000457408816281035059802564030200386132884753717564347693604036713012916212168565602955998685589078496201399968798062771102483943854219926107189007556580217894580868490649262081973077908311061840275654349023273915403264866830027857839250138857128888571477677232917280714353158083938483461027167898121919019941108537069637256015985791816042236878389480405981215249142254570129814482144695786335191979885973346766850392499865005327059302830152587149143673156463319169554750781615464265932111114805625290310798580989225499169640375943113167029267434854762646926208544537441129014771134376590643415453751199555335507116156387854458182657423786123828630422778846691669640798061034242262726646180021217505848540155777223015713869361834281559787627633664111266884747352657892240435054123620644347787708653284612953643539256422599328773525925392702477289790840909630094484971186563642685596240374795095972930242571436931285894857295293769956959940280410081157429954483113458142264524670339853490106673293318472182300633422036142136844510929161274405191281402699475636877192915437336994783707097339247067538029982978306563567602591309642376640495919893319795814848610480262552865565897649484186923923902116256047194777422047205552522801172134954308247694185343183803119490025251970140144345729123131200676690863408961276794548296457666698772001884573909921052828870531557506898076576012770828303473215192759365692398634348508569926878256717105496585988913639405729142147782030286895204835481523835415210229168910506457350343503049119146338374930704493219678567081757040460742784077265544294211589799497473611785712167667719160369988534966817928390062298795890967101576051403331518258363302038327564749173043078417032244458038173220516022725027528439202949602333587385718776682988840003344184155590960610102202803381598066400007532481011118749487338709055753458127300641007460574771291912969890261369486210569490279668285361810794724608980166425814685287047280221348421646480862071143134125857287566921503649281383105044014809232813709396818215869896065303328359090732491294293619410545718888571547884574976649328830068883011792577496870871333787027983634384622426598395369618392401438202106621908593531671938977770320877163616233636093665173446666323535415472822160627063743828931575326591204522071091445683727084903321707479592046416126864325864543982697995209765066923567059235650631414972721588693250304010139737737641795849279765852210991345068266645547726972835950087512645314026698737468497735811011750830839111736135182735434608680834716055853848530753912658770787601852758028588635025308021622263030888550948853344364771895535613112325371917458367911005258996844457465728417331070711342797522274701713949696938515920821911924292043353065427669068725191993560392375820206007456347863252547054964544169214524214619514777468831001474290028967435566828851423622254896795253341169073919486729690597101969375270439607777153102072868742599543796854003655833125065456736075094417908532228027945761336682444074657518555665535766654376555131728465038916464618503094334851501479019891350276646469672932788333212150703986550412676021419828710757517036022296768062257726911170697374086053108367006595696341964557623339133902447334156838969555660741491110811439453103073782561396943073702043232179206256565126300546186645615630937254640005231413140721232088365627816970922191931300960092421889449930831255536606413862123548096566402590576340356908500513302275844538333760888736446565542994332382539658398964480632109647062124845459203630117441520536483396954758364629559052436308933688184701675639096915830168667232360236437248908990290234945827820206824939882687995108808198870689549987952564918353089506850681895786729320176309085055552543040265640170587274027728808383741357668078652112379489929275845492053873630792053328225484659421818433182092057592292685766534742971753331028231325727221779024841924522464657817214738115668892469207709321316132031627247675686830826413770352857263844268972850891120853404520510801434282377649322046420043566168923881257184186647124070054823253121403015055857588742609645625001465776822293214150955081154740159341849297028809666676846052448848850180981801026692715029038013007692216482382689384306749766368160026426829162446145486864372534301398430652974268256722164215244582028490968057147805486909328894480873595731748316283773116239593995363293950823754249883339496784862905018676582575068845311813287359293222992179480883252275913262613144216580172638304397443911707441123258850982615089667255035729397742645623204400905704706830967046863207541955809139274831749065788154875538849603320983821266383997228245428355766731135573427073657098181153966399552796029222057446189175575222849975394245894066176413101913067096686334659515481857779398878964199488127712769450602290833676641835422176779776183215181218492419222880838726149149356867506282984708027655757474318071995271112746256918632555618975182754806601427467722690060845875122064993525115835278172068126830715053522702461609302714331087011317642215749397569564844716342639608329654058397167628008389322285581744025695809499322525827714022281040168753433060494424520064426820839504522943110779774127546214079620774587784507618624832327923997607551615739080910115497723798934497251932716816655031268802560000, - 147985714891077342811556606575839700584203046402938846958712989720769827780734534505184425908010829039823287402994565756038022128894297512961287208605752238319045817450994461678674072977226036935230286974715576154189305810844157021552104349433098132029152163390993642253709760347374809303924356326159056390989675127139736190721395708545948057154423019323817386937364201070037499667439389126196179352157543905162842178001512300469876568651754047932607947852089177440554736869061295616970996128096071427284772988071770618729791196191891588396218984714487881029294622430868256521381947097676920391407238136444066485568764163221584079187490783107748742017054128713992261809950388606018075358444951956138547852810145473562121828196723242494114704198946280043944286063584658653318527309967823213286680524624558112950990325668045357226911627409375925060197593447182173620739407365975967428551825206675453200452416924496028756872747742665287224828093520255952502020164504061889462393050316818308408912526475495737952330756123216007546646730130029010621881718211674584784160861730886314651575485668114789739223785519069962421931470818585787196755093171238724739876122051044447255677592844300941941903470666210411335153851840686352227093762209244851209955100789532889963639888932213878085458214987343856584513689887152565440299742211830390792656762402742148427104491830387746740576526593509910987555833024359550336889213935314730461492653135309961832326564907148824167835605589637438247739867183776565823039704316317521975718821376299440200877070301668148308958133536611837545870037755072359907966208987292660015476396979674348771153108980146632033692678732440394611841219247595102526277337750470156299895533689137244849547591989328676359534226469159837537687422538511536685756552921609345126892892172169616691159268886652538806603614760287264879018614187254712834514108589360236792603271934379234952840509805906733302624921960702120124630827288543461269248703703784181497596952479064695669338261093649114206018866099372409417144602436111109789024546237672602398196641892722320135342714071739411258736945412263408169142994016821447175210843383048290840854771142626608656116531594551580359663479222762490174530229122986351319177293460296490355340880866569555313776459305156378990437029607002279792360607749136413003335595746367699119166575630475079664430678818981950691989419961852824582560880194660062454527362813373284156382966866586448043184772057973306121562355783388655728339197292750074535289776602620812303102899518601734129475468560734386038583654434162059560473507810486720474239337924281096032435587043336709740731514018875179681781459089925260840058772985410745075522626386505625488133758008167364670339147304483862184055439872990378802950242915399816897014535527821745490522125368076348998340570390225870631910345495920512381445951041657386252711353094849330615118273460645200081581994362346447813707345217050510251241755148168638084858039928955512003608364656513170185022701169437523730896899893765373441196511461980537378463315718133164179138390292372905526082595257272586579323507911051762660188173394591385685898632424774058531668745429653869895285631514977486454284085744706380677782817669344727741939780271465321936160185423029119078666049047486257222276286727198889465898274410423274028755991286040186232478275294145122284734415257607883207029697019492190701220876738617569169624490127359020995034374237091539610018495837028158902707189909407633421415902022487758710661246838280565876468258649202255758233827670026727505974204595190412913384997856537431669042220072343418438387278106732912466773688281568781727310286515580072558770557276885093270625653905944180941264357452371796242259815662220466397682916989552725688424054538937452763067036067922941894748562156286505410492011353710944376626912695898222798988828116222756347925824639169292852747183381363114165290707989738406214300442715993123164171742082005590818758702148229479881250727706006240310975184092186850105123642306755396219531539232950076622956023700062961209979410065060674822203270288809270992495166069511220704698960514320798314028278988348842829515873278315845935841709936923688642296678504312496896386107649566203869412325522572413537139238536331053973212127830941208300049378942231939531838463858956844034224858627775204554957981181417750904246280387331052233521688155392457243868048964362939128072505270985991596755586909352847619079042488005968434160299334709727097667306619795677942292401127253055720047240555086678374799752696793017843787235842607296014273121008898915356692444208246950123108488590104453536817730603791496822441337970941341716211648428272705355981152844261278515996414233463976911601244021446743456432015887198418477923033387616092018809181253777455958127339033095654283019766631027430929742223805269881271504458725069029889480239262482139702748875968059929237267133101274741443378694555590991013340347926215387842174823163192026210718313411527494713608441212055973709849265906895182248684843239548009593743994705647338524533180538203318194216940445404853687821698120083344746302929465691540770833252330245989828262174860017415237190581314202317638616468832940625805722489429084425698585084936274938543638479385556259456253072390950311627725657666828456546291443252484629420093397457689534966454383530577963688472188813906460186947253911540830416513227282852202859720225419456432043116530664358988784568043903110264156350977360582813853651732790523127949722485711236474095616117026028854718586274531419183255644594333683897552598820834154732569819287556608770174995074217543893874148635776045028396893291144553179772413145627019888316155356396550411284281346195830583687492579061312122797431379693615045386445938639884630804725423354744899366437932190241101191252311513494292826885037909121099407905481000762755586762221459311770617387384294359862042643353440129929180209718523880849459723857445060816704709619672779732865628244101275064827556780046014650583334398200951268554684638257214843554267396032992209650550983508089063547296368881467989018486591930506104982139304821365094444145287159718399266462586511846388821526005832792159920997225283996545392390851420231462256403458041248579736753748461457252725822418976276630630259256363624986000358785456629045524943285915399807042713868871901218339710159430452749359258261181673414998238379450412663540304157896741377130512927572793517188691201215881211963335923160734322786274557295042069051506541361066992186123259794553311770171845500494302446364560395735789308726240528415014555736179045250665705622500100316525153013622930163947772868097837880293691426175077447101764154970029754445159494522933844742329204184429479221809537407166070712877556901496776715402522987595681531060999193623344389639135191414994945199440064645450194890744400072659412438588167080081189791364446924034099508375622186364345458023495977258884119883689228766794081226602906756565090118121449733551744934911980389926541180599284807909254735245313985161608343179953461484024703041826275420540577329661675725340632025034462832903344449325776201668341348106154957991876670532603019841578227755450854783131002109150384749510846226141114856081663050825217997584893315588474068168750963539655569852220271132163114667213269029582804241960814606561044689464021389780756601296496110412174927376463624878906637349734631157027125496528596505956596090340479565942242854400754536314109773141857042427447269502301258414933822738856451875707494120206575272288140398556831309850612046633637760768090631700132671516584214521671707743223541029508171343971835273696017084541950014335563910854688868834451745179614871727999378264652112582160734923444690871878527855100565725178284570886762252618256266032466772538558223514779527251729853745900180618470806450444930228815751743347633819673011704134039494241765740722704377141168647435596865672917010214104893069320044432754588353051748197945567881429061414711032682823901878818596704791937687942773515093174487258493921463379827146526994764934474362253756198511918285476254196381235921892089876164064007482836170286180788980990344757385519576483985437526706051577037121025785931021184399002102597168505890082324867370522128210572363575874122097841404740731355859497067927987165719090078427705198610346728273565695427766032306866976677025448773112179834157839332779224573407465474763248224776669430488534281342589455092350476712448698461519935821256356473093165590220504881335259201028933194425628945034797247717212087605995742797877334851036659688537057197594091433279115461475088538397805148464156040388158420434012307230840448207475116183140694762075932267352931772238028383170687475675699628442493631175666426350130210324865663940440718537500980411736905018098808283053612395431690774746350634367883145968594244569079640724609993033856958580384771674139803025296997265961103382852087976964205242737677070722210444477962650904468691971111133775960081894488513870869764133285989821053133968809638034663406468115994820654730992307825719220258851406002680151915175602661960362023484983785110845200648111137205837783170321555910920393278834228722341037129494518731374096556890874561649820502198698160151206661772933239270865247022829825315230300860986575119131930593517228357002615796477091406691676878293261945138703465947976155817660723735905157096529105735377911455151085722202701228320745897186494520370762078892819039870709017332257975547108708656748545997684007688011220586698982468949603925726917034433521189758621538749234328340908905634914867749983669996619153622511024471981340066676914257920000, - 26283688659439360517197469401351158936490507165629040238512761937625281028052471897088361726291820840399813205287253500254572806334020709379888239825037839963577955766123285778976055203635174791781152132632072754968884400681702344205515852644194125862918120829293315906294528287135396079749752996997880654501377117320565123899619387089593372721443332006777521519337063775937548060749925771611813982836214997375597618210744408781157178515074908307473278550158873504860382829585434419634650115284143547560898061302275493564693647846472551114232705458253755691655410368820609342885423902879158978853733547037293312634205492097518874576742193121608393507590676309900558706554108910415707658974227313678136637423268788797673143577166550145963570848054473043336139527237075400242191141880967758596100966341253946642141480945199909313472156880957772099448178165745712141997611799365868903231520320544503073426506967779172404346804033652262115546924702648839593720741605905481769523585030819419912874247240716398182086739430449787318074438679614815499280371821486387626303580636248448174133782374983504191394585327730803752717857044213700979983481822797985375461722502467182138496954623099107228222817405872104860008259792288106294921133662764750097113186919640088810374794796681435671414923876546508982536595629638812591935584589332983483389299353334030762134208702631931435995471987652733198177331586729835349660874622483294107480771995740341228733245805643187507407206983461552523256854608064643422229068945564020127793028954466559299901618126719784605545113249562994221229447414859450707735461722149109082659945045651305077662881145652881766650720721512996433535859391110906489957623659792927406609106456996176860720715125554964905818143740206030004044744156951509522276242667704227529020051401838252711124753944074169067525723381702497416582399775435829033195368619752758614226261803618746060656703094573074657264903738547787314753996334884020188631127764418063017767973042198471497051491881521376679590222321473544364072198351247530904809368991681561897781772795684767183284462649404410517635713383411016965039561334000328160325889269768600357613332908913967969684329797740561042768778312570981169815209247317792327485810828260430439818270604266475102292409444423366600794975031614682903220205946795782955400086272834572515574256630185523141641549336791401037813190675159295304775017416742049337806281952604597212594014949584931994508461746445784958535462861742321328131429617406084994689149207059631426878854178816059065587446699284115070777124957654699382491131621838685254274343166967908507429339338486687272617262277034757324882771015156088252197648916449545109485777104780365409838519181675824327980987060978935762439737594256794250354764439743307979757085164742276346863620759859757717563251365533581574808733782951301198267440630973745548415681199252901667042670108010873970715682669879107236643858361564030271393100506052160202800387484104492060505587387664462731118165747746202207766576808084485348548240882874622523467897362412285824978336830467193599237285544931059412816776278168768780881012855283795192366745742343881033432935678462116562593483063604976626372759577307539204934444516535449599236600461827699642875610991208780438348817603877017661859520132768676284876790116317773532572866272281032123632167105749795576862885225083307602347882992953053949900363449211769190053795161898943181436859186121987723778917025527456713095093130677670053111744211126504321963707455369331824035854829639455205031280746446433956869363399057361061456972213522788730919744221925481349712249443938529694895509312756666277892928486191924177251216293107025772652154384486926545404635834525158491997448058806092047180256954118289832187847662741222830505558959612104004258305664275291002909740508792750864731120529626689892573907344185663596797473918994147508863233149055955678166587258797618060448143384843230839167769980799238100010410513217359467574382891896955377057647770317790775280262691019199439354326472131305439562439480170404554314982203769492488012004614536408180719044893627977653315267164966861678619152181423765052974222433944007886003148463021939779351369803130297385446289157986111321939725590226329433262509637302086893663695040862326227546006280471268747354233430362612913247011503867595446136230512681864605798894351391175334599490485009636481140552346687404783174859212085602700200552905374338481516769149432995002978561107892793263981869645469039132685161016931964379204774098993649499017151405033377877733731211453039238848443202457982117611787823867340583548988253118736544497221791615781086056733213796153279117138008784880019682106519647376666305634621115069241841644405241114506890687318329648371787778448910153646183891395954986386479733458587204205525564082911770315148613209798014926602089618585451229300205824885105238739978916339944171569678611914202201014156038543862810925433944157919637194589499065064185996994743754730795459167560826042634548061344028078841903600499675805492955109897631028918704678225797993246448954286405959790862716167262181841960026296022227942205592842776072801472771010533692328447336922374833624788544464361267698409324262160859901085639155518834806287370187487635144750343884339289383383394995174662860187058077213663171471163619679795034161200424707137708577452758038712301226460944710042563163025453098374901517073181946764902470810795172384236047413416378337419304473469730255067134477033791992700116340918561331743574309665327400222779552600898575448508507562617015168203470119038411275020328661996640861520458893270902721829758878266034415396472158354286665050047316971386686161819038133474817088231191498788152563402339407821602835565639411205114651948500586420522488538805244441945907067291173509469181997870803147073934566234186601232557151783421305290528863948491760912017754838472122811702908167075835484490496833548263008822366164131792828233999985963647405791113255873688401004744013837185444466196411138027007301506474625624563299105738745038921964441611478928764430383623255697090875752033723192920762791134009324843559897514671175898411873503068371774205128648648723338351795257746517675198554778871513572840734376238242009470105319311008886412025793640996327898771782380082144276491157241684404475864120087283306718841340261916507415508731665174584534599885423961188357628208590690782732156728917051269299048276391496448402596091545539270492377032237590020512836244939033260423137613023162787768792553587245459786391198947977774371086493142651837192836891967008276044814277443527703866108082255986742992998532523476602705540455528019785581448808486394692241429832393680750971561610933295197722171237811100696737933292584048619436276994102417271797563384058413929427786516436121379895571572884211762742669818876689412390192750407226993331080087481942104354254487932422927016863432306638197792018366357670619373161154020683341128918243384534751926838747701523536847314984692889247189175904895328471687071352339835612950656752629395370603377590243564748971361004427949464538215949161302787177984664412619158853261007210303918887265567765708029193701645469908127485658765084182304311115675965542036580359996127942281165710064854523742496835045362913321007797378553473076619409828017749754142970820313838671591326505545640109400983936339612997938277634798882013904659143371620086458555693509045807214447352188164380810395043402276860966269441238978133771480237288001539303470260457208525320102566260210643505557856509061894845653182436338226544457911194299448978189321677842645782624773584302356734563622658504215647391968093712691814610398553071490416167640413737133668069611035428138157074617077662710555904034121150333143045147070769680029610931653095697391965381146208422543308715146753044879833720488611119493521329131845759656401039559286823203395592161979661426621725000846454488916017033454313045061287441255907253403968834543693327058945807513491169664132661951055336127563566569656571733928051932590058686942716622691768991389017078480950005443687950640519617629164753318632347537671918412017373042523028658205568044033983578824330697866095399432145971439505608353424079194615150439346500939883016736287470873510582071485651083866203691872058030780220822653924518135374183523063085687713997614202842179985785625577353313559002428202803503418979230329247799553402993895200194339166656138944474470147428462393583687994746914455857402686382739453677176636155882343937807420334761766198460661326254360123331023942484280706558836303881701912230273597620120783590376561202941372534525775699611567936436864580866902880904839081937164822232998462651233700423199200277345030401075812771724000860251211661624244588034677898710448581142058264443526416365258290792902741008682781072602024867517705152640504400024563649222519267437941739416827636414500107822855981179309815093959058161107517226885047310106979237800164138562021271072020154512607326216326914306104637113595234936785059188042989715166832381351538325589584280302204788205149571055312915670019809889438882729035073547331256222327172219637007935315180231381447666354940973585962769626306548831766535805598417516102396634733201819362129008508970085200115001206254524398393203447739313851024630087617462867835547863207880576254308709399232254597656097596108496765471702269877733069566995515485705814397870576895273183082661364361006337199971903523270764623565424757280004169056625673974144864363818220815697270722121346963740012864802337402545892211528320151873710850027780411967021427926441154239804861317120000, - 4398243602924640695674866266917984714488850981801200305467176225301308713149640178567746228064953821983737766713733529414798665299061256170177037227690969643700362261359720975750269425959143610212388062992246941379652491767916293174125050506515447913926714223269716272849005490520311488925124003497765869877133068298444688840020619977438992787131637499116586715176349633467860837852200637319511816836842533190877226441441031379541468777222255343459962530752549502837958250094542105640394456362804027469140360226422171493149095549684551858481426020329970665042550826186695058558339475166388941865962718402896737257507268369140355044888399236837914076682541392181671871605753895373947220284586982936594721857413888524651652712499705610807008378534627724165012700624832060135701823740733189866356254622821337852530694824249399078501649961198619182193005754417493162376606769158734939038017277596110758575975049476980411955850033280133206103521881405648698961943922960245699355689588834867435309262181398057020595063292697746548088978745375231215559336656828153886671955084133658148723562522052758188842404894048751120117098553383132684255492582082461093855641511879247482020970609890716454021244389387936151722957960316670736864798464154288468081677531303752236684243559223974487502294089752907958634047364140545755952775326273820435303630463193030449304558997786841925057726619717294151760251502975418263954419329097875713510728468701142692917465721934571110233200751567105150257939676612648479292307323167533104487152120146140373884952514800510968763961867736474970434068010998544665272464872262749241482285619901346666284627319141067577317733251324128206578283911262967731393569782679277902483024579874972156495173762202044727749928432379619281565160265356213864656496146415427063243578709809425208880905797480087928328551792222226481493825256747033120930330402147894982738633449741706391493000752013157850162336625285216598793771299962060794758406802513154429518491619407987936396904715413627499411636394631548251356759269709952249261358284916597376893777508547440349701844339015948751943844703015564139992396346891728179144802203027197205084593227372569535714820702814365696708466594667102485993033770194533221900388685580184999945929682208046893971992160459056059408253870447529212900546314500533664837385471150133956557344899256869312351709311828949482036321005472266418768055273201522733446155074075282107951061408425224798596801344385703410733954518758393650563457441429726084522944127060850956735016755465526417176274656979460343036714297998974433483209532951203307908551042809172813475846225684587583591952887222074133323739670547485210752276331036393656769830387411507664398447312652896254581534348225417213861974454839771918202151407203150358332798337875854278836955241236264177585989130875180258078372012997864681258785187509751930334002393138361570751956412684386569984199353586074233920979716697530422006491270653427520599822984297361907977579862398912730616503403072684311615359130312240712385895836138009383865669996136980522751040599585520874761681418283983529464135826677012067384185686341005234412314462846479280162319213321195879853138143064680297162076907285578148036653422146818059881121036155564045643299276830633262204413489252021513388297643708171565217932267165884339049709957069228305809912540587393896649336778375099082525084797605588023692146217581311138678500110837586149999225630609905869662123159606757657434772159973462834464259260310653047585121225944211662593149265345836619934999493423441645522096576990952441818649995284581817657517992106953620121427606512908521905682210239652839044805393072188540155452088967022934058340482537917107202877446900095427191485604958042501107872786536871478749032425997458227125913347657617380967528812948595444731361562350364338429465965474593933804090298226422041425643626249038552829800701272954842182977672957028914684890646913130244669905481028139933967644204332484119597168964466559267442061842061007654896146379205025835133337166785266443367973197188040330550949730597142888011030514110825992930944477637203688336326092033594635838414832919545372611211423637448852871140628497481106478291964370896338996217745598069677628101427625929628815716578116682189388710966651320591402498627892974498793636799541328773753101006281081672902668016472554953755259584759345478613703502174418553398376773406526071253048043095719263246609444704831136661259290490610992084347934462579471207768590560482667146201331227624020291605001335424182812899456339952674643334938307577042052865897987229870690015457524917812656706422993848051019014210486887548303909473966915910240627990987306461708984432932056645621911915269452587331819396532603658890998961424256316255756931443536088338691668604771637013884603926589874234464073655456228720936779584331958804686713683170563339858376465882273827188400227931850040971289798794055005114916837074876902157812583859321710011720812674268612044109755364957203867518359677050179377687356523794363369790851547956205174265199711901929721422996371713473580206844122747848238415725147926057522109991483553357960196564972602690034990069824546785222793879123250517996255852808476457519485742208157619764339711166356950087780277853338102608350264608878684765393794535262420734039366109342161946130282555659403896697895413300608963960164046443984004403038570481893247889988173639184367669009507302234238669653401422889851920299491481413515729871282918772509751710278874752325923756443709051691113720793545578361004692688673909245586338699257987343948356321962820475599046847241049699544335077734415681008946616362209089372151571139400452610992767437472257275384286453548310596929826773103211912550790897320597495264447246681852382398415819294841748347844451852216521890950702497468521653993526213156106914347239799359317343376495255958832139031385614705397849211013273881480672507906039518421578044707009937543493192127753388307193531488975936096912646541848414976512530435876865440493920704333648697337495802363503767257168383152211737561137036253003418578696461428437214735764569874913441692982276003858014443855565812747724190684912534000202424307064800047362576457594813706245600399959222782538149109418319274156822726881554858142950226859113064699815021739809097384851323475469499175794080120747791539037843856232480480057236173854188560412322390197161483984416266056604945355719280734195258118386317934333206032179017258851486447095954261666306990907248746252175335290168969037758451654381486059098862813817103219745128428459518341127359389770043844828214844307751406239770801521900787904586300505768921799782114504840651259278189173431445599976095907313092416243965060327164755935105072293636780898288192079563558039805622813007017066160211385447181130428387658730944079423944449171464926757462125479078765982551287464397723173109621727823729622545481108325507384359365698374321654393799765381253407852659051724987702605547925311934712521531693386228123000998618286399977894316117211630512697798125530238103088711143735179627292375786953669867886552433433492380275931957481625074168860944292946147781038037260474296746946715684789268144628003788415191574142116955366417482220304885063359485433680459404238155769178708123472682093681654458159257890524798884100639552463859249240892441874532640352664401330327559125863937726371312667139808721624316092909306261140677477378581196219522721941900569778265935116784771930579607078458202159844446937041004312692805710135574319946285704284193279726190303744888119050475040001524375462494481746401803390663865262222774151454952685540831402684081705662265300524811319837694332503234443777299139462819189221453580921105573867370955084908297519179640278327794523542344565670455648185024549994375795968364013663867012121716206124069453126541123988302505726837186481119350891768375886676592893791643524254588503343938650702327087573709504700196407047278269601291644647423048782799377956101650889850503243705054685789450602726157997454494796986500841378066499054927325508673667846497872326323568681292218603326211940345334460922167647245424529761033804337825913884431481173065081654062666864188379720333007163351043043640810373599197889310656508572570035185935151146272260080651070791579334960710532772784334207711213734742724760866709837730759431381447397751674544652018494202611359592784450862103190220416318362509817837634462741349984133343553569506737228412643691602422113445251332623944948287352667793591156568151388615525305725624162218685134050738685118201482842466518160146171650479899396607781394139745207868895736717185687889993374664331029092424308712174963581072803574826067443976530780604391858380230008162024373703952618578421536260849164645492798452011479557628722650078675437272508235201020257825060109107544595750812190226858076334071271614371033296246658556451771839489090003045567596792290258267032172663557172554985065584576453896237681948633562351551219623697649023364943402406425641120085614446069126941215749464121160898758285083456814074055880956171048688178286531496794883902855630983938490002557820261950769277493947050591234411933790584579678992763040966351429358187993129904712665934508960932039352370149804920809061319913681076377373881165059335887911052864318780998440246798814457910918397100325501808364196609489698235360256305412699001042558776525633425287139300766880689724091162133045749731195232959835454822979576286600095972529291734302965858572588592128305047712081618318748322136423663433245388854021574031013335975408979419711510014853120000, - 693618308328801830879988525558890779413921718102894676640883163284761687819907147356899051730654277585760566659061028351444404781746872910711012167201459550080715756918604659679253171169536711847300591969288828131657288869499068430278966548383869163638328270577934205115655259286820571175962229259818071088707756751729361583117574409980313065286189677238895246799012193436139396854860218068261888306703355137151943844556574688897023711033168322721795585388904398059514894738121066733428496787975502196784230794948641643294651408800208620868911443906656623554545891221859095300259734923290656945339744789340599163198317605349832056736939832699407976378955384480474037156587575669781268322122176428783000597335575101142184467551911061310827867645176026597603684556523286663341001844974783535412327496263519765525398282110643506647800867284164973096401765245806598501409021511937772745868537554967603870760495607417358859586160039094623623396000458139677043356320548261841547096455698923205770455680806273593855084453442888466246215038422112007666671012846497843851390974047190327575428081406565892528364956016624897354923019525090871046234779447472293600416990848963996383323293096840763214344898089669856372134023334400315418927153607762013319785083736365897570187757224748283532107931647343948527879320931153665379570819125256328696366210277398433966737427247696899799767652543671023545187657477609765303467521544832027123395804430328909017059121779488428154543876884028851130377712949943034468426393606890637595127191939081582462559442250465563982956599964451325660329689029511199084325927072614220069093868804898809425754130282914558280445559646096438451409158213590361394625135748536212135970955459836454580820671738111281031205984749577096421156624479254372121278246600502703645234294137821348872147430654474689425639799997330550301643593041880680835485442430414984627014762216892321329608678239330851577179808312905098397499370149963716242910536288221825224340515847608527286613967414026063619746129281999164288719000354512437872441142628955278700939488348955617413287528616885907377556981891082826738041587839233743292647718570114811340504743029703444473183716477852060254603930731971556384333752471841827014041268268059633069223058853087699031342509328777049638298653619671873016226140428524333854292051923331741800874458537030838707762875748330791167004859041694655299605463462412014913999634865703917811533837306581042418663664803617447614565385641037951530361459697441400767102963695963179571902633570782591947083271939534087081824177935062095950589110592855108618447509291254720319119462334628286233676756181457355077855659659984215784444025301436114525230160451655697673189490932664934137009178954318415002462698368004673331558729701854113177553368861372396286791735324742125046570663388696885038321225554159598508324127159916577034736421496469624441292180553910308946924044572237823317018687917308851082540372208271283906870227578060319803798018619476834658413119087376642002773615313757261016187465800408846289327212492935907635059451191384098619277191287031200471367066813902065238419550656185784587659311023971125994721402533625722487940869834581991434073536495509078171625870669966369345379187432096877582609412240606183572287417970828637951439412696231310417594718328094085071442795797706563711275915910717365965951459997653854249362593089212745981411268268901277338831508381449886335467096655856578092122430824920486381223880600350469122520849989243525241754287853472014455849084807312870448905522909258030112837552884418273697273827989222656263383853148363654713378678610216361085675549805784812267168544171174832540115113995399892030532157377993622979674461692666174225134086260687199758560534473062337113392689765284966350409771807179440053960378313851585651125241008637346713041072184352090666887294591378635781873128809541163719988932118726752763140755659708373095522026110192604871841928834854731456168523665415146853020380221441082366622449171449763767219185600695838970223127540879284918359966214573269102249078970142248827157894230692207942611230880324296049280192773928639640876296547107428197334134707022955752332480954894940474426053325596753121809084254511347118163926653890924739120205995286534871897518275945594426545432836127154266247495735624612576693864125265428626487737163564909615978241328913172869977615769085368684930006752019568050325359751610953869338389179434312967097313686224871291660230092258165124407446527739742896806183548797011516483699065754257384991613538461526546479842120893672055548529439547910759229295687303601586334201142323781986683243027825172876725623997689739579551977398690528498771344675113213637435773030948499516865063210135043576183752001615556878824647054551395401781341964873627523026625959069831848397832511698408563973372432877642985207479711443323818294493907452892318307134216065232800971212170280207184298720282382056289515744838058945493834222180408943620364930161342822351649660339813895291387073603373278527280655612938850551485034924267170451680728767703282443049437995604941465028911546988895723871658516726747429674883826997463930286619188054295279793957626709323739617034125983144805436769740954363623167002587429142002077880686600890837564460434461136716602352350892181459622168389447562655263169150157834037306606088230293406356799528474851110880830304802455170134789650961508729398758110684089779629693262513988644008254607247730508028453634582325360050169809893653144446695835973790518516371126102648304271137526252506743814852812964446234089111420175316871629614486094736651559857506297185210212102838641371569806104343213865579297780854809459327318174868664357391739281647827233991983825143857760465616499625200433201783018789905245975263839674905235720739650754188623389260653489060741212747281061458259209711045377126038888197570137199494135384757830108300581278452602368400592656644565934256556837933156787965331055551851041012573365776781414158967567582846818409738335039656018774726161741181351168410930079632148627877312005533996013720524087808369295313809064676603333616020214021949788253377961206653787107570928349649719535873491162733874479450603418031230983473150141556871305201429182769761235179755977946908718409093841322429678562720418273933634481528825644732166319516082529865613199349415079725646550774753686916956356585698903096499167034632829610880779529546501602234391754263227515074355800390226787672929841169273685363466659604583403504571140650903125035268841842619766983023183022995300129353102897126105762173301911603981789107862824132030616558070222081592361572962366867543498155028104610242225047428579953897033973437326751439766633235591523128335073626661639900129050833932386919691400266587570686218448585933483746896302111739133694887882217020202986551437537167859625787229620562352072554580972952971457513334975722417215219328504111988919214782161984312267387569204793489392468358137901914999131023337187989029168835571926532109724547924859546654948348154207044681198008420642530684190974175322358535233478960657126955712688422721420501005257291113093696929451145132546814023317405148772409757134938257683451122076713409874462411036083067544687992446766573523234525882476883279049288284251109815901028291098503972137131476394196397651099783636742963098464489682344326345334389731987444953792204760328415312370258721302637938447383345215516281893640054604615799952253780989462375974355999785189532980322715337491237879899351257853107762855436700484500334239855983492950926668293171102364577297438237092840465773955346341087206173791884138566071187846295467223512744824631218170434858786373627055486908887325300943970433709149273230835574303434579847379398494414777203895029311239741986288245956982939361639312942877945667322097999782747977473785498247907813733677131521256941608350510013684925661529404778856422273376432477872757146468252700283837914781647080612598535884086676595081376159718211745698254512193686962142755384770760709646542108894174265817544321766424324058582611195875453875883129482970517011041076995273374631174114393385850958324978604280481685478833513568714614613434320459015421193325353511807620983605568425648752138135940645569137335289654800105821607353047621218338265875819555786816114787708864245575350159737876496114459651732279308948176854093103916103085345121664841499766389168649572662188479473095293819064702552795083848285487517814961556301111802014935427514707385154692406954644170370794447637719849578619392216258814576468511649718984457726121055380568524464419681290836834639928146091964073887572780585478649915671061306514834085754395557892514163339837553407356029710617115898009457517827759360747895990433321393675737009207718296147677870198662901556487275246683144604148404642465439646310805076671618772828750273177653426154017494028294457425717199234303681894523522721202842578025194164807981790594054956548395147849431860453304367783615218072031799797871606040996671073689238985425904197632738057569365739727269362419363971472710027845794603785091984020887235210429424868281473315555167906380594133650379976352840629030632669076507171580361767091340454249852441467648485749059414175677485827772968639520118201468803870036426333914658116254274778080096846868074402231324546693268304840108686182567260268616325590553357799691512839347812375526598021798500574750036400311310087315467155510250567350623252545310115419923737729341882036464162326328666658985787971402388296965856270026095123927945433081115668338086646906880000, - 103109788922000974943167274420587541545628121354731989619501110499270320067322977083005835421184277809288533758559744307264979296359452401548504253103929344243534340110664807732996059998168941958371682496550922387340255682635146982747465687409480656600817744602898506792662820341184333827171899186433508865188551189822898704377101901960459682697583407915110213008057981781143487139333301565737236615589391913730195846749014248400941505369226806713948044959596665009252142873477839712158069056038194647257626010286419191503879769868124742411810053807375215153192929316819859516439698966815672769686299067522863363293678652395439016614959495224835891945311983723713749785228404209517079363156693222927070441134513652003017027763988458483458941542929443341064844426771828889113479051175798266230200159853179563038336473198520194832908701216621145514439480940805892569641899223864585838238067268650626451495045745241123945257380524896000705674697292802739113667624298629391689517278465198589331739916503477645810984415395202289378479429914588783693417451200838473421759131914738277334508067104765860373541376431752019378109574091965641654771386880499964910615611118330125722708260706001213299664093673714051025030089935822835814169686556578458492607524699929884256659138069800437034077360964562624389940311341154672692528584374140225557233803672091660233471018318754247319169742206282676133321770574537143969071246882354986360198892867724140736867011970750213251487328503548322290275586255407822080499871372721686600279804759570378073758036410849041719489789481738191519698388978711228282306576817988015029177019719403527070191936384567813499306164355885106484580949769241984431632304365989765029624778457887691589958464167039110575745375416765596145948596345984230451658937628298522985270698109691882394292661322082709690941808734844147936635545361556700649869402576893066199087519685466004015667304357268993834175511564111402502403081461662824065829948072456834565614679029749308011548690731617115893887907061988266716013501315001975828807405196005332687089843111156736837791024388815292656627900602083225166284873020401083667598153647082048012991279379677986713181016512319450084520854491235156011569322538761198096647429601358736718317569635903536965896911929171293759259984736908671148672377441481699463331258602738542666837339721106166805278994601720211238712810675028640671606465210953682117862631945442668667215073381973908430849907343061463584812535229742363962482503416509677831056742071820360241787479112156422908976946284805123973591749989414921310725600207811679790285429860370423584351847408272637759704922015392147556950447196036937106472303432233205973239443843255516920495308885112000835809377403928411940886914568099106951216306576605045918547632343759741159602087253526810886418695636748252225510306704497732728566027128636869573935422531624293298397382211976360816278705267467123687660548569101127448440678617839996385629051948486287727711099536095191585985935173514976203509018931009694490683226170708185883414014063065721174305940323575185880302432187935116760490682649045697184632837605564752780002415239014815158118016007706441452718440870187095559135485954396539862564481615197607312646648534631679363622954192069995424018621737776699744598366352991592889850638764800492637241601617202934291955452233585558805012465878388455285273631347766329066349982641005820834003019646079747656475386149982252003362587010193858989166475764600613195653105802015721358250447879652274393380243844532475750291314104238215711262650645640442203901996049952409614734941207808152400469500697768716401863961324256266252100251698307638194892091676419220056163058109215076477444409979315665057239183244416868707579245779070436521552194111413221477112449212786992879813226537823322491326342338719039991430410319926573832677313374894090338209208520106890785812241635941761845186967887879645782447311665102182086448542308831432308970484394853793428438649725402418281039607181100190746021937190499456014365389519712745273526260672405942093614051346641878784535945083502821755641319427384196480605900894118670310528144856346628662978917363418355576634857812642720492070979882923516868968424187046436149371941835001527328277279759757425377092594806541007157974904305969045624273915013237541106454531247404190398801769767376974038534182395658077623064533162362354574288438068742926717187360895775892725821794954812791014747520729288842967001365382516192322313089593020473923709456771015824392958001013306506376177182596441587885854683932697013921741969769584713632163288567937096042126003770223250587965456139116422419417861244552689516424068711754747577030259990572255530550554854100089691325947202947484896930498789032932975765779085963692616367062863141489927941556103920753045673827486381379244399516306347325777798827869591940704675385203720444895725454811137432991773741995434305993045714866081566724660866360594993263947216422436343277278071994107613106328696206203453918856896893931351775142695905137796259223896876758278755440102722531745888830961394568850682453630747630217071300810513036300212258508481461840514632657989474801744303821534287707401439088034400553992568495356515616512404182021920838012167520913923689020362925076294083407829765790031498124163678970976484503885798326016043935313229090458255976309522277188750093468881823161537819260153513543101388090629446019586720043080747242486942248403642296559289926125790171473430607784414883416320535396345354159207886302860258812645916348286265235724331820143841714137115231901665602515397839440023162227821742424484497644186525076987480610466557517490249056547700993667936841637027370538078750546123326788877148560518330308178241271107924714333026363667958623418248149092061890286719513590912276562923327242710727549624046086641158208781246787886542489826635058857679793057529402166046783460217525817392016740372843085167084257743115621374944646424617704782348277716119361754021897038469801628645455833199225376004515270115002966324019001562012441699891176048625500731747785991269631654619075111745849325485033924116116576146653441801057504834609935041359190700452033776141254756938515881006042071759436189009982609757755717161263684378259159926017462812052064542242701106126917719013089903626134497152366624377644288518606682330736517030252180067305322515392697800915021774001388383260508347473023151363446194482426524914900285516617797807461688709417415545193351884666687299941602485175474290473067198902917208667931690718938683910760903319009978048128777142810309187864309643689644496934991583101057484692855483474265189132196390797963950190929096724394452865842775143708327854347073069206565562774046041186901515405468098226565086400760369920107518782739825150091560682114941052828417659371092207108995297957413016544012060123273397513769867496419640035162349381782613595346163019539678559978533587078415754636957197522561829293405277099347259374357726784615483523364750722475915076709772265258210433376795870725605997374938475196850586426642745303351457901324001530432206919982764327470549833897219121936471316050147125282533186867005907700139834524068334782471747898621655002489396828393077015865749115048539655255412395877519600083647599109625994440271168104240226168930559679057801240848530988186787611879466548749062021678025152152356186270492904917163897162763844026917039530874363280637461889535743842469246041282644755764815172316960886508891306408231792271663223030038658523184048705393396287128598283517076438139167102308909727474597400765199146287989145581762046281272494781372087607997840303516437702850617465582279082549416599386121350558185317819672340503924636106566416356808457166963275612935443393580306305191094290640931343366722786297028152567974929327229399318852385668660745502043749402565449938668446143566528647762711464780767983498381274858887785587350750789023009099399176872902682393495368108122947005558188097292800862847896950225099138431931506009860204968423154305175906624013000032915810880094471607654986808252672467925431351576832155892742045540272222418836094506941785725074960701158187348009541131107035868243150568036181281353822322119980498756306774264141837101924084785886361157453462694396019664437433826956666728450929178600291468166273591367749247441586280474639819346450542289816647797441741099005740655904372245115236017297056653258777951855889869727051568996859902540326243076116296996655432468799419828945712808559842818328537819535442379170917073901972168510102993304820140850748248411588505630005014670735309706010857313166996150259596905425551486897813918189822588911178214416252253318702169058408294413132415949544055660431282262639071350016324498362454199857025881370528892358906213775147408142606509282077932838450626768094762233525850052572894343365410833120566501928688271715343717060401638277220132655008103472825185718442342462418303114012550703936412943010032401157511026767357684323737941365771139461687663042506446994490906889933820209438674924167531144810446428550792875214707102249989418817676496735210305731080062867565878966504170125573365123485340019263914211425882863922406462633554007484344640990787717955968294788786129787446315976118596150106962579625281745469398310108859126547046813608976276146274106464205549684884521081554620336562385010049473948452641246563696068155680453230108799105995141771784646913949286054465400211325121886951076679227068996058752222001162186966243307092886218997648529021944075149314621440000, - 14450159282523509022723325810721038479831902112664243933373932347345244389061904486278551392214330813018363192826499308951281584182634746275047742832514200854327851217301449989530118154064023224928107622556933192623692642501008043228358681038299790030431839046773388919199385612245139065953201111106343614283295956780851577158971350372788298083631213393616880520087677390404507188861581813818980561829297003831982257173060844579651599964254365051737038496639926079864391761159107495828219221192979303142659552597293071788361477929688130587495522271355068932920814790361186861567740043437108830432971547676233513995494804947543024200377161523244499504728952033284873539359684487179352202909009829031218137413071160945859037218212400857369487160412698279500936905973020038013782342044289919272315610601528758904335444612648207084202368629920928999843923095631549872010294349367999863942629868611644511933220138691594597189055070350574985000734595334303258091545785843138311733966351747964483536480905837227163894241040824366396374234692159122839002939861551716476199134357834081121629994171028195808036152341976128506186288318931856187523548261928000843564937353237404074074868283226845517265677647889307725783830574548947776404826317179862820151929301285208733590936076904060283212800923621795996208022969267054840315831801086742043278498319356006799439482618513188718300656303442100739612516774319466970117089461981122661853964772751485932270313650813743650482121776935096366303546734579908145781974783417642138623418185088657070053052773474224276726645746453452375689016255779497332359190351863965100495479929092545415391315205263062479873828497924132890858837320308557478330730736876712920814633736150070555562277374394140701541962811507877030791028328367219109624251639159546803406820644760649545820732737920015674860484484131518744383811743492160255536128880514791879077343632925079684386879431822985258323847644589740202346991332957268654033582504230508116126326305360892907673061624118498221913017516919910633139173908542192670894369112833639870727963461016318402780414591847417959072618989613299258753862031446928087042161003555038358235398793114752539313630977683185700581422891172189220880464748020250217985517170061614718047331575890024903094814930165825575206469937929733492784390776797036170405809234919045821303698541829158325556180906657449146643817070953272940180982117188081721521684520304547712360111931943098546576390113010959506036173482909596230511318381067571935191705714806660719202333442140692296816061756281376544000601279636005668122934411003233163150867130844021993511974798571659072867362630045627445691702682936299868618677575784041230476154102259099141046093375155747546363257624384573079680488991046969776211828509797170984841695265504488844399598948958280499863054244224317414802552357158025413184790826517831852050241409904407864451232494411777880433300059541457000965642649602441127800645119371607317941093775762414605182117494899962202761010939130417366303075809682731033405430337782760945707074558240250565020318483182348074207635321751297879939040227839323508247022255336683528330647490118449081534165007887313152193764416082694071831748357534516487407685598244443785702923335839650089530337489567109002674361773458015633851903188026856111607641856556217209201910406923602797011390777006458693397362046809233712090239366771036217760239525038366334357474895159854031506436706964652078600772081894176659287070743654599327127316404592141437292432600816894718989225688459328349837297370207693383912440445810798584773576497133145479951842376748121796487820661177638853672318711351035392989655148521167028600048600767309612001173950802675708875817591204822307363239680501783966709716286944784370553894642825868519490577131172225143035886014015102629986728877312601840564892248635473089379051837235854457066394574388966648479772639788170511314285079500879506401933187015361496135845848091406195923206039094090817291415338894648730460272984124406318192349044742493784341041234393376216831617246200935944052290668283040170214044210244612841083878170146129367515075527830719412588209150613739338833171893628619946655759487535556898927199999048688593106008486308654450646438542456376332509787743804493271522223846380587498903983626155211385345554999989956643955176119161980417502264452622455180262525634348467178642976050632452910296167456855327373994833924008078546453646111792739447737967944508980218627398244963725558392522012395207885884684276118203979103120285388465849695478518624650863337411817951371789479598723999717623016652454604150882115233450049424035214821861725475567540770720779701056901979629120558504426428708471743777843147560490934111091735561308658253612902582855116943116898920124874739088637968263472225681395186058134770807085426596010912639293891412154192484600895541346925417289144807082960796704276625762387412626852807791133612755065174110696903519005302278502352046979906283519979807012439762562730774142306182213950564384723256923508578766511577964695826752138579489385120830953525965805882601252566298197202590411824936993228315885661020488629908452779059372917228661755165073105200936143043074075134472751063449274779207773435077394022580492602034554391757682743285773620767381571626481224083635800366983284174235583477648106535300780790833631922046958643602442540492315853478057917799748319214824742778676195221784700186257036423596227965801091315498416802446121309432935224255477066693975344883077231779606126750406469283430035112372272020576651884058646038289142991023343753224717817469072473612476989896165149342747336902972473622650920919928408001577441156398448174859984501449088003484858717005498319078321662877847364453049974346495960598403872370385390921310642930230744655231130490227103051747980881807243931487971443169224198287157474666505889166050466972541375840852599527176828226445326123636944649341623177853872526835073421751204508918681291919773282425320057865967488530807816038535361962772656452969370715292530342304722753299091288806108992426270656897737726604229608011249952724310868026895930163638484946021163671831654507348920077366787324481774717190672008803423798635920747730675453545348211411953778882203456400961636469486718847788440919661925538691686781847093846374302029429567719077194222338573990917650763969249318022455521727141642607843273788581917222383194538044224755586161439520263048936233987509347870534512033080830158842115009954827224125476048361614378963000864418898833427660204342694616129298123292286049819519295502091305615972399122998602075800073458441038688457410253162398951887575207247920177601345372558635880440945710186096419737477295864589790738517164381901252583499129605327947314381274395718046138266344020739936879811542062812120424090553072084961697925468453656086913203361911443467397334422843333054298025108206777397200499986689710798861925595141516868635656880242791625437998771002948158625691598322563648546369243729944298558701436182338924662816327497244256065949136634615706158050784339052989052483581105949726705886697560369266846323744120790101103759084833842586107913799782936981504058259183630705666922033375586508455653797809791286232183226371215140347673862679334043336512741281514587767040122041750013134731255123214741104749100690488248099644888851309669100295934426158125845053123560062540974945062869360310163215267078180698435858191269141959146164002315985651966266673547208260809432253168207155740320059014225925296812518807284457901242966652931457338866533940070629627039788238218151145962837610603184136016845483601008104613218187499391370233931159501701868880679400391363279322437854457386598809281135630147905374505178329244398820606772915753294784095438916688219543627504183151658664102974816214880550568379253937027782249609130462907619527686810938046119036713939910993315242607351575008071917008359787582138527827021409338279773684019539424081217792960665110203914891730774349219636090901281615646940788623688196965474865696709292367442925789468147126297373902730327619025989111634391662536217547340716605493304955191355207610662736847486393895630249246243458133700646189152888765810498742615515728250413618766994377449033599085351689943389580964189760296516303842112682380966665487693421837809564706430062387738511368343024477186664058063799142246392626368350453648543054520265212854836061427779521049987843237919660435828765095873532493662401629729761784094620010651219379389877974911934824899236218963072126347619841122008519244981874116487057614836397464461092344971960913696111952499478842517462279500187913504374241420567140827830117473436552729145579125322311297378455183864697564287446812458546208385072037497396665721601497216388836762500819299161013406597908502683394760241249357207772126449140482974325894189926275173095971496736282908473604243178088383182174176545542006217249932902874207129320131344984864306033332080165261358871715931717031510133990695516967290451416136115796366242185557019526275773909127683311900621250678149019172465976487065334471874777045644743669842963180036755108878267939089972653975350131520225128440022059808714998424792398774194036429563995321285892685436680818898051259960956134027060493328939691212277160804330972328568398805506416761882614385074085751237581014746330205619854750529239229042767167978674089968899194293712633206456756525024610960296234263528026176100566185254037355700878541776403752890167622629663516342923752967464697200640000, - 1909222284359983394311830998230230501992972855325897591783884791148879172314660061445449951094919518958143525644660534017505515889536875989731157521251564110932228750901121054489509368944951186826349668568529759083409999218027738933667659530923458497180169103718257062086849167534732909926866895629311362131665651911350331402601563593608738249161925859169429966087108707850620937049388833008889648177255343066542164254953617297644657053770367741883655487047145400416072770046035929577551708967509481460765494639701919115606227238092219576431512734329852153265382508764733078483898164403780879882199553407534027324133140917289094294402163344529326302922685117240647933492220477465720610285518717375200110837774894961943846206805812599808475013582456981661359660749315980948561567838731558073197355746125604013304675625168940986620076707578620802139412207821817399853711029904957978264147998935581879822107997340802642142889672919449695150158344709655199100703673216758105141374592214436856891004398789678958039581514002756697653832545254186094744594533025964025291165603372609442378854102035248914077058030515761846793139062915872734020243035237510687557748072671805427916588904243487285372364651734973056695637565181770250544352476090146165447154391968105946413850759592566603469039386934227612604800002844388614008293641098788161462636788891138338698392007726293846067465989623034188035974355199051401921505693333665498427445674382836864528657250415060720382806512690729761930181733149993048570600652627408982698659414273035681263908902995863102332132617429676322395176289511126631407077461763465166340292984166340290476761853783155543095278327638928530924944634893190702706077577709752316325451524074250821107200460850319370914561400729951302316783360527540568970334872311373670427284741578935351116303213797373719397376323257386720354880562707309403566113195241384392242854672783216893141155074415683187910177514286627371725009429327741340536095916663381407192267226918703769619001940716668465141090591341100392721190514585491107114908000291197289474992377894962730014129969761328392466112418756051019952130646775314081321151104860964490202354272273499997220437030913224053039705788196517003144176424324341565909305510512556797710948622186773352560225662508581777473537598955356176585520114257723214030708185782857260972400826902856604326596344417679039894505489479243547891936684912124771405832348036982734642799685276364787240533476313932254185176335119968218559742734733258977210971122880699315216660989585567054960280509406616015747240391216898030145461376567068194363639893608512046349608651838152704802398473169180256813768620458483272694496584224653886792053841981909297320463686903848687949969555230886955591174234942078233217385369727305540358935559513693262816682149832683646170302616964736790675180482498272532666964763843785944166042933022879015318379747925560136993830203323800103277671743404711208044410216026483043403416375552006200405368715172484803655630333217210881368420821134929720991023579330329226193576605963940325612668338516181411614759658149843361852633795807291613927194841917579386070800526836998914721067749226921338538692177586686235487272481697521395097267797017726575102914183596453878135472282725825856980816670221808210705281097431830062597857096397924685007885648199554244561645319733113697187499465465690506551776960013008535881424648939432750237713493018972495483793102756626539471869031188124764404169363996915797923795500037490598594619120283822544662665144612183504208756290922812721590451138079298204432594868920728851463880382096877124915091463752902695701797377211779166340234672502795059597044984370888052505570522352456349034402060321549604917982257917350552815384952178653943903082436214563154398541880568501217625455408847302491984043952037758098064129833923120843521051096707602502696411631939731185417445701954429120792262710680887359626620324463514018117886205570762015708585723035844419590544665127076526920058198183163205613516677665886855208703683368682491960010864182079974636884286954836113662585352582449629336298356426461858534410078293151252134083904988592323451575292475545870750532658717510132887504216154344403303905590939051438457840370692522439405195275349044265180345357317222723074474135942435364692686962880401191028092273502698036829528371930836620505172367619789653583878926026924798052954487523247045136013345226121533597299521213767478817529043237917810844518226264170682429245962256976289677721600507106877477346525972328097870403803965776662188935949815258530395839217880149801811006489555801788464978333319755809022810518424569098270725963142469147371460406440413965114703731923624429114559050014853989884939730868773148707520558459735724499113157426173654981892596488708490014550893448757490200353174348597626113944868998718848074191297042465779200750545812132168350645837045890441180290156364743580684095261990803198147340116800500550034539726615210366100775024259299979223079770234403425856576577035323821969277498445876012436164434196550887264676643531887554004926321856396181376780089651158460273381577429791613865117949775590516836514683049302122711056909088991975923787768669618184666358016061209025930783464251653176020408558140749423152771692444531519283928472539977145142935268037478089944583300790086422757966864328645550187630123612010680790957019936346520896302251140972188788492498462341243975355074228322366423091712588809668916139260460793773169016777730000995538511513603352522425216108706752312566577771916150979107921681038701186363344242673432329762718832565416490625470363509955069326994604074436535407307777158949479231633587541855938570504522214747599750941449339678558174407803463833689183867646763133568452471855720334896454971131850568182862470429019837874340195032097313157910706585330136063249001862691426997266545918317718987880288615531927506644553688891749842911393143730324540024537679866375517358050931176019591856551197989716904881364196904414446796080038806894115434714548339118014830927321188457007986808650227863931378556552971330094688051846928361519007176882040254769191421525262905136474025420896905200314094180817784223424812870562125980530972631402035464846291201576291534221873434648504676508237379121354229091358630164193483017857169880684445167376876219636170054228735680231221655546359470070088329813074203379796322767576416542507256377284545719421724699931368789285776264409478669116127044073902559581574054026009700303519864423559004374666108413845780886852136080456811045605000150797496537654618534282850301577583812802438241782692910308393521020799307334792525230197364301597199191964696554212729413506175240103433508853231620659562720612600928561766234363463326609925734695695701246768048922815545548204657175507884759028449906277592045326832993685769190950915267933893323554511698955899410221373200347170983863571486088964582128038771365355580552761039637740318011921694636969994697307352415360505773965917564521893143922171286933064036431592038924446072081371627604744045561078898774530818109465772467880520249041667292456631248824587336354990163371020943939999411110142231888594177659445119153358439960460269901020279276592936372757001060575087287441786577419495191131872822327855333129199518299810488900677233344458637008500142665611339148551124802108545639968313521181306726256047139035256262437847186775302729009347402928282518549594879438984907539192626942314568909742029101582362116317453617032176746631501180588170553475179415362228666841109089803456726429774355424809539986357229547501084049437139067455102450469472476109294926021313434959865064390667759937173671284041657615865278876267764858348557897646994605835892675422492921586070209559072857117210470292945458047055028008271237525020396453902713472491969255414112221958380607569655110987641675042705407064989212811847884765263569833562216059971305730313494132722786628811166663748140466816269604716518460260257670701431050693762140513164318733689556413328450787357767088506543688495077990005228772278004316047273507009467392597216011183256173227719875640799273605335100087086059920863787120079938047227631661853268237061968865481053437717491709131770503891557123235255493701915449904493950699670335548351009073515071257119386420896951349985033411388813027749915213611544229824781318222788657455580122380292526078629032113572885682775118854973692306045330614213765224215481036964701498860566057652058196158742247086865191882502299575672530090634000661077797859381506543555213746197274811772692229231521500756397330579918574670541129715158897210663296577010950322244597241749276851239779754550100275797401282235797703137484460463245162294536133660803569635562883773738875029634458138365638034244746441188959831540681502550505039265717561613785731930735435160036049696011787593275128816491235600258756976771829377220898998393161752597924104756806050634484397970457823928442199896673554410891271227595662253701874068855478878053769840802731926302552068144606348752802536462666025655837193017082862608178144273416240942939788852083887418493867709474811451812928657480155386775312544656021316459470487293109995280289876443888418956354824541713694720418327520992892179458482348337391007884718216833843447520264754910295391688910774882190474227512368818733697908300214161230493006437213181171372604148842093320316870577755101359172694543660455078865774022371930812616280286344062450081675175089302520463360000, - 237808659004481668180971058297404934427511829432729069221878210262901231868764214267141709019424556059102289032504608192365093286192488662972046797961708862771045051316815044591459615600349422272656496020919294755976728073961765133169099874135336279680940011156887894185047609303263866356865004239782040793959867203558690461314223948944588782022225336042785320506435056736039371289489169757710933852434450493076955593875283731030160140737091559448693296069556497233126240459911090349372070722835502661225716726888431097341995600829569313289086769362033729958597435029683931296255108141481940595764070028191363041855689421409357148912256873548510132521508826446773164401999847042867145323712900078957195087799629975625620986420641540632259659426426570595309838714250082025715623010353846971844117415393399090344965409075603409406231031952359268536020057703418368137164459261023673408318008140073817339743694623113545041429951635860654717855423372693718375168179001085485211735868567550993415070108200277105685319708709473509894009097300188508984633486711753930943412224985335962744715830306819562276120716620654863266748435240253185353203875595988774428389279403904966017387409706897312210263257132223831961178043866146057103136833596018734283648413820675265076573820092870495261450826710852755626546159302104577982015350393707778677552085125622081951615196256982409012663960980274402229565491031353847944479928484503764931096931185400130001413250643864835806203862084477587732023752030808072357575424227732506685900524158189047340222926524183197674379069657123419339714430733895056777440984625732849674395560870865161891979143768527076402202677677798207229349659994676820246573444473968665237340885014536950273760045772719535855482891780831782364991676715902809115042478009713979502254365159773054500545474175943194187175725866656371949884752433120704228946316568765224474907347384522735190076876902011779527233562022780101161785103914800147763952652222770504553175139693432809607604249262263100970984052968070779219342637066756604331853900667899083805806340799230582954078942057674118148359952322932870317849564359382615278189796463150390717760375777270379257814367749147016888545848635294276363864036879012451224110798415440136456709202078664075465804621389909205652666594542659256737919366330398432361553770864011781849070273944616039624395628612542947336918337166465870700294524333961914786148540099190121255920946132709541501090044504610156490281608456982635942113930172840444471379860441012921747496079723959994295742002750450187275752121865973021774573098663025454811415330992179090085214902907574480181605273085524140564054235710166276776369521535880012715237801476028591032364275670019108239137574934531033428518125618176558413999518770431713453576723614130380756461756432015664830802080391847775656473353629573587033361767567584351395774643820842868973059165019163651724987206647569637754369869266727520152761552494454041739555690631512310165700763229179108950112374060123111176954368534703585817195026278554566882914423499582623042175292066812330188317009179150147464683816331261249904120642231656844409371657494027797743649020901448724995503368599986855752370334510370266269355157761003706023448400089641113543316375038469435390422951062498550756800496535077481339797670109425189373616290327519865082138330879166914637646811971369783138027173165338455545175670842943494602803864542653437892147779039558060683182362704319764048825136537762139886590985960610843576171627335274052924683840405028178578517599748587072267943380206551206704074477033814436742041820697435119293672048792408568217616605204216915233622421642248060526333115494523662091490689413494284168812216568032182636163985873589941606014408536218906187696051219889336993725066108287008984235694728413660295898491198434170414270541927112952456272270096043693570156764403966635224390548273810381338675466573837754852800162790326195575708813385905609404192395364731151990644085012869067539660819752501565051618190315490037495480123111676779183244101962907432116171047224987447133758608668709630556608202745000059814445118942880225068276082610601779241253453344291529526068924492702982810872792784299104652526744078532399699237915990199777105464867125334486785413940544306491444879649425181158215497595609971983308117924441793026452521034581223260532135373299731559282395017528942817468715139599658487380171814659117040858786353557450133475111097527745197965288443812587314008009633823115241653559892074679558731924233649699706200036681091320062794540063241733816338096884472204997557574875561407814710303505207644036023217613790653146639171231938304710300193296325385973374032751299868011673440167031808596118509576364067761603426549483558295262269103235895420563475118770910557061427550967218419301733166491802089533767313717907620684157144802298270791945988816402698873415305590957120396210121200012577472136985120660417500580897520545863915063304984861667941269833693893003886204914358960189209053311230963708900322928043678842406635523145892899867069151832878837929802725913267622432609188566504950655566057583952540705147027957277521042957185583590776095322581031077654717401858257297091559731459338923514523898748551151964143266631074975507300896932198333407377685099941778793468997137344925392588149368141026819364267172440370023540924202873793729249015670919111342192230823147461402884568116979528200466265073788106784356395425472873043506186658058942103586485870244539200312131205651261242125570204616747101912456236904306556888469399365207903220454306518545639294162392231445071689509608421934193831289108898408928283369267643115130888329810779351126334731878002744779705980839385731794005414189806723314972600697856293053276890836921614662990702558444526121713358618530805135189726038473457686146722285371230482458486139549348658529359708462645749688107026620624382478584085888808307426491387338202611301644405285159156676301166741529851796521710314553195808139508705645518160292122720334434842247427171537527252115484199768373620444835871358720114194564839675410619511064794530553783192602747432141715890182584295172452484757964648368823912300009875382505743932138761464780626458827402393220259189124223262251475192439626127545191847004036715452391838270467622169233456869111602835426842354391454770017924638064314822661737975980957513443237158794090188444909583427914405937654140215808210155929611726681260134779294702480210139266199191061837988905054754133967643249259626729728069814811347049925265852765331507194681546409325659947493324137759669957529002439188699611007339499140125557679381202867990585777288616311872126425494191695076652148632667438306025081302446334322559695374033719492137181610866455713445880718829220260328970178186775250829486004341180855174092025864940611961033219768199525868024984055461214786698270370412301373430363946555521693055941623571214596925122657948495955768146497341903697346888167020723050870327834762821217808198287648854271967210200098470773778361863322803663363190705643036849349754372404956701853991926748235126120729833923045523287374913682990293751225420994435494206618421516848602529092959414727988613069392270260072562160293925289516597304246704109963723757188126318467542920916437525135461935730894638521791681326744248698608011613118033676658230786983978129160077933929492823150752730729436349006142767801117323434366380719319863913937883155264548479041662475357514280612567813887278358526193602314158766505870053092806894250263348307667736860371012877675543964375363168708086687218473497321216179175351871958907047474744951057527678685662124053008460095171359074274905897663565112214635464186938885499350067947386744216959046266698338977050068981900122962908081222372137110720238696264786729504646195773613357701786361106178681997294324486281666131392473926286932842070343851318493920836514639533244635548886814514083175076131288553774770982488348933263982681668646022300550221052044422476814278197491619129578055037154955464155808621134021693202825525742866708729310738176215168619529069755561741556973133679502666228548376521845154097666593930573333487617321734630078355228789272540630993850544463071835973459571636253197963771041358166298346192379838721914128106670477868003167688041336412530936591680549344245910301704216535645824848678824074394788499083652746539029015874986863561423870786734007788829553301236020376142727050620733318576011337407537955845974117286356835089402863223930414331459693203203775523999891665883356658386021527802617427499784222303824462138409112876001681789471647103433545053741764870777988886441788232813057350472892218828992334094982555304825172451066238708683032356082373175025773682776654575360506512904339266128737900449054893506021882529626066524682245735491313382099023528219316653321425006951947441009487123797610028090518776199734113135392196029032326789638179954416681874222165393193502065178842186953377590198173017801147485338907052610979107236743768436532323988656144432521627063325590988686440337010734641988039592935733115141835525108754612074135684869271829357970052516828962280694238804338576861777817394077951877615298438604924404419163922744601412793518126756803186652063468683533635881551505622956558234604834527100066689625892233867604117998317356817941678963804162289904652928815041821243636785504735010454615705486461096512198217649737300914000704403879140719747813154488320000, - 27920014172234974205579215440713338951805043818205533219990077611291644644110368688090682165189564705438109987677819070309676799201751102229231751693059869175463085767602714419662202410079680747151475078127674643479909925811793561951685121375805658101768434443995684885739367441638077161847104433166408482036498506883722152381315911852058857749567746590179946486929125829228065232066988729082866615339834600423078004918415510742939591760018826967660612406348863847538301612021270435639724218922751178082368828642590185125043838053123349623751594419515348934767178607221257091459038740460404815841070245018084787663116207928882194564612071062671775954692275049479773169643365270754067483378975731666854108393529101619447973383371604763844957078497483287129802045820476736015289333142567226484650880599487260349956850438303860611741672322259634468433650674504311441227087338092729547444300674120385590224908327608506126285748560580635953416052770586236484275953984820197623335667922427696883902294983922547603241657533348591023295531077631493933538968696187166760256098580863628998975427166371470882133362028120475177617844112575128723771064663541458536437914092672345811343264843652340264913854391496394676625089852365649294752454157038927055846396473573970433356722176659921726110976288710525310651298217439239150545725787034634369031766307258939398326401965656427796987853069876460765528082068162299945270582693510327849694391687250061980528795041240370550084096351135415314159607222666928651025526567499676113455876287704315223097183168641555282944712819896172373545828045001234555504726263925992337789535021268551902478894832895943200340671312319162725297514058759415379790574039340788493622874086415816654410401117391410254571388271331278137361133736464853304134147249926721254602089343751085028749991150301129746039819067091000099018543640261438005128696702458739005737937178032866224290008596843705959956807084101243813265691703788219964967122130634183170391564461692906989541489784081928728048184949380587618945541540036918997750017864736237310310470360649124201705018762288752796360260924020476479667123829586347977827974718814198037470029177640329696019734440995167222999495638214071991508826238620139956917028789627636631525446596412231814475951431895104986466135094429965784212578584687104423595088429339199370392374272860959461541596591123001059326812857720113128154144698179934396407518823438604394571078237975252071662440022154586193774123312370706208936012897339135138242360146026858840708700730445605158998242247233005045094228810845676872403119672813901054430188394719964007407972164481890773782046164570393741775175708234226174491676353420589674541802892323659202630303660494196742595927799513661246742196957880574988714115258527854804617335296834811711813485570718226931266930531035884002035201705766002668122797540879864387758659784542408543126811944223379438916973618792506728683112906396568774741309481324008945387210125425112875091241631099270940245406798649998730181914315842954289018165028813149337921219700064894681393698003990898620477262248780640355384568805663101704881224298934276145987313174522361309136745167116071655710002824487575221707634406786589863882992724521743104734361659472102942423362662588172599362730017589825897088986624957734394126549781263936329753164097327949781408893212029492795476077085037097589529047518443161064233875157808351326240405993163310623688832128527478750391376076573673885209633892661582406319940091508965691136414530786126999219879502729445791736851496251777925228079931418268495937230699151037483797761063562332431287395893753640994423863513757394987599586775320799845566802172133969488133725195218404465543588833216798604189193716037838351292335484245208707210423182899298976445241628125878178251201019406141714307399841601139077313596088150215698817362840586875891943141276649861633273788220103189593221954626587086929574265328559934352656359916282791136034576264392421747988749185832569811903803601894873432594353839449654239027788108237810882586524727904043107434034580359018370288481436818951716333758566789294300473234947850979848902311335459667781204120339973568366863728971559025201848125163174062636179723155183146639596987252112555086957016159054403080219596648104210001502200029302014220665434708789124144642241001279220824289434762017007592677842102694097878370876077105460610402833935522227323160139416833657071475211021407178442868147174624063137890359631492109027093847886596694039956517086651908063505921344642803266862557782210244576129237931500250755622391869448017153706987990277382021707672360240208034443859379430123716395442790501803455275545310518078058167377341322791720300562165962003472743169144554096259751786323269366789362310902709043549188102081903026252108176217283127840329844743744696362754849140395115778003370715270071363289528087190692234695295715723859785550880448526760867432347118547587722691799152685784573331452101431916390054041520633715011304196585173422144501498587607203588470756902214522115327996187586756053653634949272402617936702506886491554985650327435476039471298984507932858636281508544311859836805542612319346950175371744531707857845251759797382527087285522248842002004445843794985683890902818941772612735086213664862584158160293054433774290220799374982100240090822878886686320815625889363607254296108568711147168802311279145370455944330177577145684270071214462469582151967186123266117561462298385319627822239421928477253731577247665402240338930992398221397081268580766539926819414493078557900806438365141869072478656962625801035012985590318026659343430364946549959356776764362382870203552780812602236058275768209551630401393997089126794792583873868711233435677667549151336413469642214609922204518065371221719016399606907131736713808739840217449527051135026387838629776171731782633975427992778521230661960085065868223645577183077616039739142156209428711669035885967602341769082776744435566881382723966189032431441341058277454405503040096099685570944058092265837254694843859160487844528719559349288342778339946897875685688254124041060667576816265607086065408062057791775188705925061393638539037802474763627709676327068723473413938130298648747106513300304547978760865647905176839621143097488745516413557791685345442041113332960361408744996966306995263032222110316634425365817428075635837467331278481200137312781524482070472390591158433496277119114247068797356905266949670379840868760317732588569536592274000837920488652323086511121081555237205210338968206698196526385628361396512223283669751877384200184599930753769388974157603330321712733484812972110093424694442071412473771002984506354294369183269151330368788115519570823695683098970224495996126986013542558981737591524328877315499461849535453146977383883720798001976961427742583071864790939452390719643515462187211840638394222969426537065056685764493049136900855442299751896504745468017452623067441822091192953626269826029804453295715603976182064528558114615218717953339338779061361882582235681814725695926405856171576279594345959198169303001224059542690327309836783525300777177486290919749683934645727425071142079387131402072770569997982291428372295021119167166948406095439635847231268509412816669586590844760486405062512721079354820240143166039558807910004581925793539978322931187841322387412557129865764264447836278923379522594889267891071024004930042902474171310560720484562232345534051682182889978060521063853931966566167675683701513572995789907714156450367413789994350255318893362320769906580761831073574510746573958652661354235880004052950982197630288900140638505533593524296587837590174427334214603896531683817153342049232294835411019656412957688314472555763506274093839219184938478432159943047095442429929302637928175284186103832263268300014943103783589843669593294500507050918499582628673482391474823036896230434763965488312107884106589185851320417487256159778074056381085998468095569325776500852015361175682462800230004515817877752678526457510993536266925006127505341232225458601839833836159672793537195824262200637770248564860013696968361159280229922739507794430915730688110000639031950406805901911704586874327875332568054155698372868784116801440447812499221319732089640772788052418739876642934282852660595600422029167603196227444635701924733304401108548523278404529573272275004072794665220262251101447711940354706102739679277801915647815708663556833906270353335701847504820222228708867553136296406979420788100556540226292684318920455882464148258801224288065170709137124784892524749543834671664963213495042813336195843199226523468215358290472429930508263779498928934209024335820016852211968477833704018975577569224601254562629054302367361264690682988303310179012893446011320702088071782155702421601377147143725158121030317800267939229471800583272786909442748094350293131517575531828848059194727273469396321716278878696964845487663235214910943379554623337350328489801424752979730018867497096331352733967991186252661338844499639209690085391083991778673209541492737255318839738621893069732185335498024763459391676457898382976952120986233923140847751267595783087620738660402428441958847490183486957445373849498488872087499337406598745101828639439933707402288775544643111836897068451457410299835374367363755946284739901358353803017938650201994184413181401862541256912363051258040771952174750089600071817107470599560091369805932798613190229953796372514734080000, - 3088848044640745906029248826244347689255858054391704643762702582560293175961099829616102584415030635348979991893876547577257146854008793395723765584412186502005950018148746532967168120697303619293513230167227078445553651799609266309127625304033477809016531245210438674079575185155829670416465189060302581114964834364371338137217546150194513094418697357532023576049787274832501275021204475801019243668272662492288866270164386542723074265831169829402281300490763231084256818896420876584906144194054026691192041989765708914055004894466061089845943224900698120988415536880894854312126218954188194902390069104830871266889563359666471218654052081908867846996026490909735738846267801067428016162012476999690645817402791717451770198859707087957176518261372993088278843349052760955175375596987061287767293675379802514022525048207150043690325343879052738207298485468287437648893624386095083066239270678466065282199310466094816345405582150167586651679944560726948214626117549765264095457806248828256635837127818131575161388309568005026600001937615660775195257463387550146749092306554109813476643313697005406638652154968353272090234846536629479915382685371369453201309058232128122311189497745077312664098421731967216778274571970754710714592685361483567769880257242228102142587248291861171468838035633606560614418797881929374652331176713506472529350112320496464439543814586355796595733630220527493079297086722330709070228522268724304367605304524300173971598515955216795638828683050060385049920191321727564650988249976624077550761025301746900596695133599836210795498459019662052797580683347761217100777905538826351202601861348203918144375209743942186045338623793215154274191514443178622893998239334616796962601155723410114425797243601161945741779852114940203008805550056271844391534661209890752746382037258560534872559839744829958358625963492076264613930237307811231358815778885206256840370845595676621384604566564386622177686603101285048576213900795388108103984584578553721115447420680712394800596566020113858712435685609297023501957785965614512926394456644416928701591913457742257411257744016570922781930045204400612964354886190639148426595229397312221988787460563266543482477303333743263301222641830344322647420429168338160067913049837429942211609382700532123385865546480224086734775909317431125929951712484606095449123833385882233499757407619513355138007300648171657660096037356139365747573492251733686861502921526867566029130173983362272341493435494078874617647458527338746189278708000213696012686363090076188237981344144291775903382725228437578577562638917503909450060651842213721893261310308725791749745891484164101017358315235081963973268577602969188814907162028280456848987758765509284329906417830238102617797548134441883251105139974471735432675571344823063553945886987190217168665548370103568329284238039532764754650450379390376538557644247306023105888285152159771708948935666985906316077349605826536247574757693363418939058013522522340786493632323283713430457292263860066441184877651297186863428281090827817966395051821761722887971166706805406999375426749978555641570484021945456359826480195524473816284346603489141085788481935031293317360900038188684501219900857416986839290663220831250632218009825350544691728212597452317412423731198036174683672197067962562505276272909381615791958090827622753801925219829786647443777448952224476171807752883398068492131323547490083127620851413762350297447126415438044047012211661153927655866982213783788165962289369192371568520145196841868360787328753321242566548561710972145561606521282468200245995164711545813532811878238714624231234752065622080389997550670450408971180012035945169373344275374404128406631816387855141727254318977839457074514969869455133385032970537499181187829591086711367190186077209268527810573492481188566057519034757210801503626341133843214169750103783045182122024297722356006393619497111892012746371788962431291677902374306648966963133676180473439283879218333327727011981005944065775489019735967233153604921051014953116622432877058357204625755765472672541907827672507803592254761812325707384665718371682906663007153662730570235305939852555033773109949595377680719323944575381987979719965858005681720784756641715539038237629911610064321675599340801138046557328939678692032738643631669546837009393404289399272303621152829990333546334860635327825781996957360884450807754320266880169469468184547583366168324795256208247566534901641487494665454059504853085670199512620721684440594574056360661687453935398608990634409882448071367803581432581668302904780964132012808507543109689986966907333360425495033548707923840936044810001072536657164898334990908459499264889896555430104655874347811189572142057734515382103158852332004109246192844464064568026835590199448320359138645820366182840843028588731765294214203332743502194720829500569566026183037874829516591858221898855747362088048309292023299955178726208304203061115419171054074133094219424922939503793993011975243964015983350174831551907144710337163204537121460480038850304702608055740449068344041834989812384108441401291218077931594100322963317352256464431030705014816505536532610844925002675701352578712985256685663519400992941461526365751593149548233803805813184699039084961555215502427949152267789430534042032777185015004092229835140660100984043159451290326708137396240708842417698655775634036263558877620603539540742641881603374922244498948547727034362888063068555574147391502554357632572964480171908150565702537660216733473118166467842342754270806303064272638452726837974531620518993294570569606411527268731278638204953897536771651221025392364525022030011396463203859108027197280856794614094125046914197319236680764227968143069817040756487449320585705279052674930392621974360631816613704478598404462881369769882791556491938026009178188417848619707694067603573930989804181086963189055291857819327857923963006449492165283796951512230621121434644623921714868488127871656569108774562420847686793175658509594393096903884323892678739826488759748653193735191861213525884808714742154805204784447785266362181560857857315205101040770934168080711210874868203451404080357350172483650257190804454950107972347479772042549183667801641761482006471513165568366471020300695372966940040245221666040218085607360911862511063703571385499580694533461923471742357395878120956995595480623265124238720644139963217633950895216069833545226052682691334060639831906501288091558581560618955001482698586346236562179228601331865633454483853669898271533322904910376720786629700769290138673298191826599081260191336542064013550884516424978502067546222171987398673869382243060173162355769434757227062960002152407455292779678776628044065039173257973203426122692981191526876259607665411359785392359199486329206010993457291073199730616522244870622880356441005312472615597253041341136327040476306999268482410284759923272685544189512577127064439644164184403065293427837239294711162318558093445391910651255775058572171773016691761225366320159955971903915112977836604213732788602925543411684749680561229853112651068559958210499397615904580912640596702783033084716828984485618455021250368566880362405218119804597841968280520947907716557765955774271264118302535758907949478819732648318215202916043576152432967689160505862160946265718121009487110362555884682054469151087938532424912967560171419925657690190448686075452589219738140993246429900782005626514952909153596854206945828110669815459192797159709671178183940235830987255985318754772552728508244783500028704434877401634665728612330898985436141812651950283901769266830295103037307876070889853962050263340928694804208591720105756152074696845469203842062627836255397113992053007991362660796113430139207642705129856126868560348925681252926576727948119979267295737304678865528237235610481246043665195580762707707717605606351725969347726001500185273700873590901589777161997443358729024961305641025515955515506652241225110083863466813787635205227463264298301633693060601834824159625344802476114146993523030896110864879581901013101920822396561061699424731543090134335158719931175112241192235152382180302757804914568715921934975575271451474950539285070683312977553523545685365377815211892479658636146755085071732099034934706980861859955301091242627702374693037132123724361306693389057217059834569946109468548494308900058591111869493979298344332666472503197215182047472305699229236656291608786111186769850581357945426237416896224243350200131821374103218090401280891550220428132106551215280694235635339122335805798275513285010736597531036453088368414915970734298955532289160231159912775533059028153476187395949481321254850626094989940264419936119563761025786095040387299657476317584042585646743817986788102048602932185227805600356515026147897946484870788454863895616661994561559713612519204758594191586494306862842113201420641207290413148639245666841048510253800218073784642039262546380486122929736648822048883347776670631263981502451410399694453854427335068305973387177540029576678363146073419027948800712001877587102405592031997812766827706230079743823056161934136962967200134955548108686732749105392842166398166011554606213803832824715904362417354350905113833756153654533227269083031258321264955546854099616069906484776813648920385186801468755611421751381658817908200502059341733366581957887154465347162874060446853197546047530816771634926601817894750448508995943051399974614021103513892700400543334400000, - 321872936943435038051527473691174894736503801948257744875378245216973663501683859267384956545732292425641339493046856989691737838056785605194714789954408934463624114336175676346026227584172141447714070826669309986804516403513029118144048283847911628251049403354202387074403843234358640272492750603132452130036087297659547914528688513313103080499017907464690911059768781838412995800935905784146227516269625961120669793632025880420908726748549064660601586888217098029069043595509452081843975898187895734689189133288187522967817140076139271627702919587741966744307601240856935480935428557710493632167954759997442766778452078787037450181648880572132769896400725395569321448620965933573284097400545010930292012221602591552577645060602020418887533865368827700634121237157669444657470183970418904020291487642334730008112296361443339577685284206779251587678438777610346644097949817557128850899489693171062377357722044734690564679082216334052913620249956121409906639672107617689130757428048383151900482231404379760263520723676734021677878571959535743731788635086245225298391867374013560728467340344996613599571308792869670166702388860179283182611902261609808053766051123440101777444023440502423702167224228273164249245146204275202795173627289457529646697218139624194884057762437501206128306680276418222643309491451657792494305518594101115444016474230931192118412800712623610331664487986940258475996000603301180109789066175721381532385601750629473608291538637744337703542589386847126803490642105439643282551566372320738927294162426137018633831649091409502257130640584072961460706078541239975451828564129745764956435042480221954174115508329126106552516939993170591915416320881292859933593800771796891597477081831196205103317873451950793751905587402016314139008989384006044708915289076693289199760567012398684933282355564020411594215556903300791779426117551547769215482845552147636701091861590898831587609300402844425495052073779752007789131352838378854073479790710812441356120258186164899937179362189351755664020875329815503519760802065045449770298308267244046713201384278699416617423928745293166365761612542035650779835364869380560995557800902158461891885575984507310886483735977225359800436949943917940124619498934371249850287987729068585056809194879476344918843307795091539127629207248243094630836691996511221981494613150000863216999118230954145358384186709947611853529553466312652645395772203165051485303532683232647857984929646735865931732183717615301886922447311359670592011298587959557013263386000018884128386350810027238899853671246132312883769234048626670462224751924106130415282575785395496907146521399323359096956233451795307004340205572254442221204052893173165131864214692490580810647392325216192720286941434552269332666445798829563779743962540208017801668841518945771782216499094666885709451878569136303362278496111186254082569734410516727241142322093238824489856557887410733111023933911203453156293606160297107095173175928428495574645679704505606420262236417219460368874436524165016890588909789230216891041944043851395173795725006911738605552168040698174717181493327453400084602202343317178002574971621377371595698360376417745674666828896658182359353357404019807985808038105624209773237554104598726404630520723267894928911437498124178568765700498297770303256214075397715074258027397995053593139763277664597000740519075716095827246377680006955749780850887036490421181144524892164453177456263641501304077138571490660035137025524865209308618002903379665113554480365983705232908513736332375646145455155208162480577819696513272596014036284109985170817105988617372416128068400731571100920060622675144506230340981095204108489342006826869711559588817873889414736221643088618977589396136056341257535216799967917923128271408668683936956736972562419333882809320791842579923426534183174431569906370837166745341473771853327077380929233551679554241410583094982061714404704416256207997118426689026701754694165941274842346228946592113097664795423166554024219680385765955144748649783327136370224067833228238758305475566274042284414415904710849896969308577025877928416163307083498202517675258747321318836929531860173156865079100793349947241344562441303522207285250519767147903454420488255663172740522436039600674187217585845873064958005561224470681689043012043304597675283240975309878354830688426404451362195754420622667458281084801962229145641918647107318925167156600464095543339145400897948151496227261760962209928335373204905534504061730372477774191132689717624159966157878462416616246490080456029356738082944912516346880244075829544011816349417964950715661437641172848848494315030927070554914542137964731707987767854182060888557394353029779112082219469785038893845799050320124134225082861437875390786643790940573450247375536450196262224422576906733511087380489023776594709893982756438825636022655130208641349956431205507725414744961015097344897201310529702800683690272153835989917450150291028303482367797674385040926750887428495592165182067702758761960059691302074158385292309296625225358258975358985584946808971746820593785723573238664755544844194792968635325134646808833148629085574802166556109443732552537980801409882816165608930946263015329897374414071423565190483426050480691620919596798912455116477799848886715783507949580466879707242090981825031303270454875746698087677235229630429454950452634883517894622816296978331975865387198993549460943999126938922519116106493984370759381926303053914220044832454845890859574404334004318534657190899717395934425084229911540628859193387105602181321731118946663628926350239231069003619749023204531615166493178373579570341541767590066457767396108413002708333591127529023591380415269500055912971101655941721085757240482265850456020797156065228759400504477617313875334489100889544479303070408246376283018671521508579802514694327937207242297118336375859622060040135094773520618767027717631757371469259044958514825994243932145007781426808543707402991962559314987551274670793967724392745311202660868830821834907228513606629091811789267858396373399591888342161958813721819469277906401823797295255396651605365273127138388633157060939476938563428289104427365578401850396411994000168629329984385377272303567856602817486873452136447482566643482410590216446720468183830956869058721867626126669410676178201463859094591552423431430929980383503395326731043148586852703093517388463741579134411294493043890067487691252259841976107982647637755744910817663235178477763011627451507681897903216191686445983203797286635470339955447440980603824031089107510838126094173152033271644881118095183627365156940701867595771978780978569443692996867979604847208444914740401558957751297010467957828606371771911327157046350233203479797822287642969790094471206728189877027619516508934162851369951392906014052202821113156888623515099760605658340990287025375194083380443831042795000682547483995943710610231771521011231708355095464348956633998415403980778004496613584858070434564163557230959642536611675574350987574211591317502490779118139123498946516443588864751934600167164918955733253166816027294087948818741395612759643711454227429182070675002961809628850025161139977554985745550314598493330693040536130378520290287003896008143797299666455844465748818051795328008913805672368246053386088272336206823750200572211226986790880404920314805659163009448897631482527380261068522656579980661327018009600047905926741677382227095415664635547657644794546520113318120663828876943999702119162199243179888510457913752309070616629328022395400028620128352469271918801801429608970003028522939278151657132769071657597209219149890547214040315812816453491344908981176160055906687791657355885680326768149629401421597534507687794518047452594345323777881719858757621341011364105128792276010171131788600813073644737221629916457763234241307218615992859102202614632036683262158812588539514887612698148375747490668639710538423469449449473001816307384903575511720290427710068425651339762865306235841525938576872214407834863003224376465581196081644762687061663839155582432350643874162619145562819596469223020986011412517592213826611989590485511701057282495498272320647341302345755466037716079205480111474780944415340225159938567477962699570894655198580572748419115650079077935200850901522765420168601189749630048144094435915353706174610765448244000954347664049890642884109542730324872971938845886938622619460542555219110290738625111345708016756272757194610152295870045100697654004539225471744463982363569260360733084629081536972362036117972286155484174633422065758470761187168407636613144348389003173577041435392245560601217455391624849815598818525151313778781878633877746471783489346307661773085377458808517353455121123097733658316004468600795037942267652662424839929660266175663121411403319406405611357877106892773651691898810114655234415655431269163120794003561555590457548681836352341414196472828017396812937335322501971145720005328970195948669214665475956597033324387111322014429980853861799182990669768719262529717469902824848028057832164629273764503602332810792917648336025292721202887846215068091354329246130879655215309645968815546621647552509939723200562572751837334184139290784663468302586575994423149944376991196000907920683924231923121187344179962657605053739375102931913074364877436316696049271253132780834643593080413784988578344067816795294154979017849247083009885334176223655885940612996792320000, - 31573292256155141416491685209678534977025629079593954730220196360668421023451199484244799342280734101258180572594348802586609528538839069783785997980521201135805824652309463981953139651501903498608000521095698754338020241559894161270711008760611509370983003555487455848384531891700573253718808005024805468448550631434007523847936093988398796740561560841944300495391142779548404261223484343158645910858525310680088897783347901414067107576800284974247111206379539374398445607471744667915087147494363468850416234595765802908376146122929463784427005916597764067657075833112310278735172609953642891172393563148249074428860152981627462096151403076536170763532653479250587646401745216317168590875904383243678649295714677829560744123975908637149439783741160876397993975419496196012936438655150635782386801713332310302648024731145027865909703267945981098247148586452015609521880812363502924077913487520576254676420103056892548306219181340175414181440143526974976228040886317622246385870625107747985945482554476138259920884714785926420305721256714789933330671206941869528146472820553029087766698811910292879809599168707977167532627655018051415896713661082486251574242465275189495110710112777069895430532268314921502487990510394501260261696209778730288175708114721609057178570287970617668558165325841233052590918448047022773240260036817276731305897344401839369788845078935435635008465141094666702597833031438564909156160077233380945871252917450727087487118567595949407785058500757006567775398453999450663145293266685165910432786674970707193565877124849068490221437053097774050795843708517899839127345994078518675839167931432321166610155930638180758551140026379247958286606531818008802836394436671490500244691662491997495753484909280258742723277769383669610359705480932832391716287179526280713243991568301389100893550330023221176842665618206145030874046126224125394856875563452313069437000538191535872566716346052274759308635878492256767589586329194220003619752917195885947154702908660030428672644208523709592167737205461314454783131797784558065478646696960646227327806118499288865952966197508742483987506713461816309770823210661093392847614889595774163552502438624024165603349304278864470971795509752992463125673048451457225694667069016638318006872945255850917405524177344278967082632858316644764135903382998966223820499922767053791207223027044624383806937605871386189477847361525789120968762304222608853712213200691219764098721235104750270894927417634215144238928780010261235465584626171998228367732224237423157076681178535775766336231982912605454229169148392376100225433716199891137651521975506485551485620467402650445648896868594921225955772178898765500299878638928219288695000741213068103265786979164907171697915607984461238400109820114168415483392201581152482675721930319444378216871697698245127657557949937247917517347014510153714621725389792142740675441176419859122012681585701418510410027442927545531051678559291892866001423247500422699607808351536132874647762640844233313800917612981301615275534181341738555617197839148545744160078290337156262650894214426031091384749544400784494119216010301821217143647035678372970914671309659361905977254496711913429775420437071370329907293278187525058074492296585723669214197755681581494845210703001640637023828376771435969627849151949025336425637046136704364071836322580227007389612448861709451834568856327912933883716704089502984650783403692790248426911996602806772443925747804655990661121227852290192157252165012652546511955611359045941594976802727099864429173359992633595314626994198648154265588113558924426693489499594447324430880957862855364565119080183208165083204282897973898357993907305122553596430307939020992372544878135365677185588868132142474281673131816550722875818664545227072781519990510894752337969293711381865813188747640167180177912615231598882721440053048754616080481870861313815258851848935131745466937908856137625685872157057916512003092822731030985100029801973492011475303637271221564646780943863455536629775379353664981273270936713860029812338024850942774895337991210069044599077319677580551327964631630384670590620491739655422963135819128934559442274962791926377366535351435546298153257030656352637694192742409942728260542269925189197429304867154366884409733873791799888956175675550313012193191571029187417970014559713917833885389312510133188875529478730966846296629696164413822098426594437349209171775508887322478186829253333143557908668786619368578346800036353437257340723752410653738192961671662305598989667316497997569202832541457620039497841712835147329046431572789409581066558641365869688954484187359585029342267765761399937415110703022419793619229091183370650741279388242064100427181817558705638271841606557893830215447227480832430936961433593743188936611655636121776931204580256802451017826491771649259564795603940030367578937955417180577766627201580771003652152786699071484505326951672115466342007766305337072355291035953333197576636922230384058925452943781266807884314944921549156193048653473674404084361355519256250400067190327225204338241387248257469794183035136603047925848947744678964523519888402886965595098610335640264927524154907962464455957667242786541008660814829245614744627254667914928153610357767906715300232648477793968649632221301176171122190567797688699101313011045172270772265867697269975133208883039287712450269553049444389111482382210098535632585532768378112525449475909521054574171069959053555459210493851253825692287681909044809407243196619090622106440846535443991256524951997424965698168729168366881694650707145951757637322764863342259977829020809038257496485799566679506456317532105514551963697625324647928568029783836127632412922811726886780352472297137968768866462485665567274105479241583282829176261831007367500881084675566899960131054608713023686318918174366248065470699559428776731939081633789515977110252387622424854658270657047815827559672042247482248100486067642551946247647809512008318002025255671283367196717425630155470735855173699727672302355909216557950376988263968899405046745148946796178389481714002588544232996222904952934465935881240284017540245526611112254532695288494650823075152541612838728007153069425491311589466856318742468246543875716143872940535535759852766183316912455937576696574411421258858698764049674646791352033316665066825603142606082484843689452045978882595763634333759577248575392771817929873650614324095865028681786971223145276958344787263890648038071277732827177915496425512196026928277990046292552670469773090474143921603468398424103282848109029208650698330039161188873652494141325718984235175029306318765030577437669955302757746323955345030106154877445794586261410316954821411289733125373401178907852419354044179030630127945861652090664526547739854912528053699745499192342785945372905860488799274911426323437158142999576106274480861508256683836637665633511534370134677083319932287828533641123431596728146484429864160984504629814783040033591304385517387084734932052349815177933419631272731142479230352299406589836821165840978502746065470103289110867870748206105694743115683147809671114597265743953410258864449740670834704190287678681094155779879302485670547319151995880143853547444057517767532083128376580099093032671602949616244495685624988379040260781614986260796751763342219376397757929632742710774251070021064167559797839923208109065912429716704357758522863099332117975641819454670436511779113769956683465533386150540857716744304855737676153511385525877424038045948033829675336406062172613353871475704441197399946519050060210614812604413120812687098199659658082383497962461846925622627050838310357105088707597820713528664062588357802278663790903780984886272475023537347553321123562138938138686951111279354824805500709917775397830603984607072125112035299164456817069884989592629569685169119280235664879570057013951197332590795981024008375907163311947960035074345085982953173004447992365383952295148830568022925128771127300824315797218997147263973884977631386467286387363660019661680315201103876925795890211937127536762389122477683037413241163176987935557279839961210351880919550353987012876651234624998135353191431693975462391516256754667109506050603692544352000320169847124649718858071272739903819688722079919402938420112804831632933391605599199876890229953454171814175537604390052506979448879994685557236547241398693081287996105194917911880396038895378476098163095156404310891059610661628811597971897879972274261206616893372972523255105498541188864231023165131258616702988909685248374423058034733522006514332928723303969745059612074331826836170068012659441414124344063060006626257647439210652755209015230102100695544574294455625785516851122528479408383610100334615584876761783108627042950974099455829521832341507063668226470060426093088424755258943204183098368871764719800318923266194877509201213518813175658631872191233301770955995717978663745381904119466292846118864632689172816834330010485460711755270863862780372334173470603923492391335347882100765464081202848884875159655759006469895380607026109108257613105692528245583782446449576058890637017232802972556730388193916105145005585301972246532523718755684921173257255482208399413743055030412698112045986816307913570308571625630140566119197592606190590321842853986994592362870081659239189461714357229981343341451982860237662392234882565468975991258428108617390489600000, - 2913091810401733446298475501059767314034853392941596470892205262069976892719208277063608069122023482888338458027890384567867619291502293530438691587064906720648183543157131934534122439299233229552348001492219218584326676544256852604555233064213934273271994056077296846863629223460222526491258243656439757982070720145004942145971339325315104800203247425237997375396615733360712455422564984588268541327893504674979400821129609838564097650815565843210745145913030050713511629569201190336288490681212704198313701111609153660561196050701692013252389678779386662252144209983168843019106834211428970389161843149501359584708686394493503827403136922214181542836073243764259659052202679698901681111732184094573379518815897247195445763177835353686377613818698556586874086163092408885509293044822544701441889015707749401286102331545569672948426098191262878169849111481530228994443116463974538861319459475828629790807581929618404835990582389426654095186457513042662081575421216567162697301484432110129914743261335590292231912581290982345673957687632699708340694321773025981082835602852137632403739536814524536262845329406942134451172864640052557019844349517993388021811754940186814030754780282420188960211983472022296615186194868899288165633090425773465599134456466197909133464388832424386925633320799454871309291645275394056602002335044860370626647721516203200492248028090144584556544432455889071183780264271143753330560042475475584742239816388402696742665484729138607556850130841150396366432866895981013078411587219857598461985903152785221708501956088457692837282655971118520495679028599471055022003478862515637063264078132062902340109632347184425145853766094965962767789304543670826993833708467470578127815731051262793197064822132538748548121218614144232949237968781643205276420085112789188136278089493783071638603651300950040167589898148023676275404049355354456061481651709918853039454346985750212950114617460866846866547209838030170696672770734469403845078809413761343290119213844656910697322796957141076995802981364825904180073571056255979381027711126794854025444670047106007560491444205859824768294424783146925957063270594942577145904982567541203868739415527856117037613187021070980247331764850689435459169056246823392131040795644541790368502526913247012106849120302831691973209247923716484658512464942682420142647272892491746405557963112301184697306485592393193164196657472117125783592596253284205893498638309968866338617472078456177730238586125754378848284523538017490210012495885416077033142262589300598111764045526991838482449779832793101655839172837237287732255862698573148560941162056931805012063458028687585354723455606189272252895377642254065694045113409934088628838275615263257743918194383138411207298352543061113934394052217295945889806795845295213698625351111235415822968932152072768546669658683517577519473466144742824939149148422372335127535365580702399075877417471252289433697363058545296270688642130741914406834855733612682644671876521245398685501097020831744864644469443988363244486250490064591042139324028817789925249787726069937892805380362641041432959232285118736684857711389952006737284582928969548801068362790228909960705039459526592997605769278994130000678104523920120460510739555596986104228705775114784983356068464698595984861189820207148472893441440285640821509582938969417143564949714866035430186747522066141308235881776067447247261444249369058531877200464783194288403125598108630841539006578398839671129893324398916115742383882556718204803878815431019190880223733488015107247079843340460405547583492232038810802419789495030247800523686736159060688610325634702827423837798745386405443539626293119192711902763368425430214964211908128689887559183942261927737954611078171917905589139722086783914092911804785166937239941671564833166300826648247556153024185982959290839926870255381455439098285276322344342065526473808745223591763531284655761943865833980682263775737922732227133102163382258178782375539884854871829475552654348699659835493315078333813208835230990282960424091955567370284205670062892099997444496124535097792685205926328941625858822597459000235650570568266351095411451085700011303227079390624154371557211027950742600016055513384940054862394001097661703773127268038326068798389680637028086261204719952851170762307847893608613412250877101549759029181627801037290888963195051091295258473792499856422188230071225510592011630809647537966789313928780431427826716780113303936493046237252614448515146674945659264758047496905582324012506246135726615109664505507746044605160422370482521214230096435485066385946362621877882259129080050741744073872495917405590153486930731772634783580698938701164354046018731389136998691503047844723676744852821314910791986012304165593988703357548475258691810875407741848789907071084233738550665887993540401172137943923982974640373488304429466328553793109403939708389938428727576806937430889747863986931078850828102136936296388323982391690710700204038052179516926555109426800835152037643402001893167131476549927474418823147163132445928864634470668395328607582826072199550450220776876247383360117640009422678870514582567168355642394563733467843194699470387090390079329757790487221722349233892689058661999715060514899308976794388258039932466017103025530358675075642393583164832538549385493664653401813357707968873817053099837889178836325382812480170249855660534003180663740621990595032130544242940113466019049479869279873038429571556555429450659698605941151528717797810441193970552642912429914393014693513738937764354628944960854178867058697268793067825730397747884196711797826371771413933903729807402364979839772459059249443703064002030073767142041739193145510641541763965282412222999566063503047335561319731930142501855280462341312433477719791043556590068397584929600970006200116640715684401612302304251375082349544325195644405401965335992748749659451090622296928315096073754419815083234310646193328346690030021374503175275679514402885618580066283714601086042743386396509948036719515590935738112682945137254717378844381199044048721872241560878745673640021729455539896908216556694927395965022874218543907489287698114227786319843500769330555019748486334162995666203778436117675649580781633941683228091431341776121923731622573230327449398185384200873063759649944652622157303406751440549622326764059301140083960904142364940209553998140846475383417246825356626639400223064796167208999028522384962960740655428029720269749412616161470971822177586308972922395360057286183749535235523058295992164339094901486378376093651614817792143387668412982536337893409902599048094699487279796640116217826385609143470874141020957797463518710036366840657251204399986754855746506226546313905126307747225093128965864454230437304995937550766816863313958371523781559620551082097403887107846460672105947932755816100267991456993337552010366841944139483589953639726071322765468763268079547567598883373020243220491937228598152335364527425426230125083391932746811168017826166458368878407981877454785354554315469345080154876069998487431886881074275892094004719340935727519623037829687536513579157399419795829604060536333929023945368208357448225066540885471149778036240483403926140785994789548730723578842240385173716895672076219562399880457327974103117449360060953360535448445150211473594270791965312108106285839013882687908285766150570801850735790188559269383596855811221934541718066739475913881904024654199868272870353326431364291300319251503097697862111314692968539756952024538268896246200116896109120411367320069591395119491406050137147048850840522177571243942277747387755925526918369356040448392244560817693309666813248891006816735010039161535372447960638292702160154033651166186399161790130142914710139036549391956509464348638220065901719138448028698309991590715407309925573871233712116014635171006405519399228590670411803180376493693828796841426416468763434890121677556660094637776996072388722851625225200997493494782534779090115176579342717166017266611140919386735199459319309831255195163444433213755775908550604993564100490409280152758542111897853690683355408276002025412853384774875638665921220748149610031637198411687988563614511962745893401730924812833241953557295833555587387846544200962853554978050597969459027315145715104432087774252843140318718508442214269268028722570146055470006376193449315620289620694367783403440723251285758316635873525891824100618985600496972545687508230078142154827840751385121428518357024178564642811175272342935984598103427785590069315357172105482987526867309244291033845487591350123187388592439947081532832827996193520006983197027705817123269425883598950992930773954704714969993213474151906664626070183847072509546735182537501557848445459620413007263222421248907875585099996015066798263433663372552916863162196760105468874888455878363744895311532501895432621581309371831717766187190097261280430742158397183949103058597466015238194692682181063046143647858957815160684319237542406067197109040047416399916683928896768741412284717553380136316907230555521963108277993784497248983171526101325998510080530959390810011743811675483290104464208797739444809406907241714138557028774644156049676740900125577894068340627129563731076587707620771004113594018308611017029125700502410838196381739634595725778713699852590916936533406578739467570582817729683222863405506163286789324800000, - 252539044502821484714891336318608483941751797745743066179777050807299943470982027271653715625699577255913257347523687583340799847951288956000308883127906275072718024339940022735782559324856683188053147108213599601770640632848663702510910817224825546270200166997969940440507755059201356984133383858987619217872347423690642720521837472493071230888037951529748716520582474183458023606586915585876558879199690744196708064661264383496763107884919416781501942501576186063054985077308632595389679056791861435822354821000832989332038389327536406215927255882032925875448638013933001596180407776553981222006780561915142691431796135355578367130679287829755882373989871915515068754467538216505751510225397075322960310842681022195647897404925999715697652474649849929380368458893753559231285886157520184596237694938747552166525127022116387474003545630563602805042951882591248421870995449508145366351455231931913023711110572998790680657494042385813378188748478007747508131106778333318019737674152926945475375389629656726144122645728380394538111877007069276316773911529228979384095237075177676995878369663840667104703992413242716319566705870220515751882946044349054894740463686445030483259802502264772182116322525675932047102351128313048716590867739922340849742066851760510835377561545674335560267830084414747338614457558970812183241638545465766827140113717292100234070017671226037950177269014479686660191839379968349229605875794724481565099982914107353432030330956250721362861041983997367945812110979123949686849857640678774934204001745886467815375937485528536726031170698506914062493559032755804766821571381634791998134027399087003329061360963111677140840573524437275751000684872058546638446965240160059608879198679490659035197538376351109562847810512586094358600179423029302776044697434417133307725649688851565353088421308047235263166793089185573549748759861768417634737908169528763548667525546347465784078680379686984945445058040950376848364083985092679047055525860001742909399681426210380316811490981620605532074869990538085872003786806363489028382451855195225026676637525958924672560282468174824564160749321644519199209294018851627881232096258243071139524186437576856066206153181001710300067122588012236135861357818620677548879736189088414178482427050776338917808495007863505123112123440097202008843880291519511487361079639780007657195889263767383919881503204058635081023243094839591479854297032682826257656914651968949125798158192974556988106318207022757239272811840917615865081208182135036228432334797200343619210105531669492231973116494177186933085044727797367808502160174418147798962976934523866720398392098679097217871564191553801338670503224734154174189762052085592116095859491092301282701714018654428166443484493368676369396591946547078074748073133233724617175151087474630067659547711482810914783944156435406905465948847744081831877393949335096087369628493133734817133571871331013786525534085725355738335809308447130420999626681438140901219434601521728182281838665137472382379043218530577021505139649594286594170174775743682494893833359432607930472284104249424650936280782532222704913731244204245729578410254069335662147973678024418846335050792571561132469368535977936857685026446718714092766063318405965022537420339824004711348891403071910780166767457466314561922657093205924640302576514489426776426009977609697465198957112303227603546969697436845882363168498423242610814960276330666274445188857965847930771487870732747175332156107331257572172295435666667054744721714423947665454677912735984239176348655354556063861077344144105786350504443352517081683618267638825654349734788167846352783172136709574936048919459900487214159989428752076674153186195433272179394330022263890529932285708349865944050551276600168243164065100898995907232662246418689017233841251902884456458077953204775236944400960257240097061427306490604846665414610797479493773583929350038937356320593943186208664863513067190266972626659417317021751690107121036473856012720153222641198474615463262416515685056394012789071054844192477113266989725777230557708295715209993152358740046016994879551543093579891391811115652864933692909568938598319669671553552025888051303783145394644714877896967993162662829579001876311112671207891332754664070804386360731314658054777890008351700124774360478247634152533057667556942904194228742072183752088802574231322975668771669812778882175193467378198390248614326522853610296464189858360992605247284805533008400519045689756826347146439170888097729141445436728710783326513414441251187772929102908282840452983949945304197660275893615552179245871012080630256922797433463210106394045886320107685244512855669570460585578831650120975285182637793141210496691469789679426824355079568335254507110156250951346897552980383914525521652014269628472517336115661014097899330093320738721710900160443764103924936610158601657683337491339884775213763769959429418477248415819891332186749516429440231898713542173501370428161098897028572093624609240347602336815627504282034082628331088180197500894695800101009801856227586329607289963121417630895269556440385859393071678605070680307720565657148484293173885471443417415192179114093933935555107426518560307326168291572295821413878653005708469040888204947511389947290028558055682898031429736044796409847110206457512857713256510502258054232727827593566099537171801101221786283897781776660486714017308271781613736593191626918639687119741609621977165476827511497853143002165192407029429833839194977199379066455720898324079044234064110032556978301323743177010623765747762118735484650332029813357960731204715946866037084121580641752724259487858527736105188025827884042176988955088620927696473192579670191938929889101193873704395548304665432689028809263068373003985269434848434567347710869150052076342089143986497207280563057983849590643872109179494973352598048009780303307587370442115499782415620809452859058930714056631313914001738728021944181264478972416072298660537810217685302060471783829808614856395932368573090708497926175037336640560521625929511395392819817087481172519408724351740909778426511406674720137953460444685503236654979350352956350065773347933009839601910170422493830600756207102880611086301775245569067135998664332364788619444707418049630071112698520953281530962084436609825934333296766188737340895457088612563678014943464257422340609738338212996497141563801632438314302620837706937467629834412391286697932735632325381055957720947556448643856381961398650341687358013973260153540360580736582755739865146459730912261236888868749647773613766246493428446306912192488160235435777535899381226021241270411900303603187305348260836394206247884144093127383580381204647309199398162085352745093468621138215558816701161580791205123884675675502519443628326882981978897741366902354727647065040745079326939150457055374183006127823769440026761726961260860083171275366989773601096652103639831892125121986729704202498420943050091070345676079395157883556976231268178560554293491677669315870524478146847870136847649667298796610404525831302845937525866901570053374437715519512388735134264448164338915800558747860058975595754590204542945106094664939160530124333043294962313829732871753682021717553440119863819292401613566061783191602944654957617276042319434636657417050350967249664621769080371418789810538953937068398563333254422761641851248114163542381630874094868255259828764302611769848004855735047731288945365706194041130261270583038522271344738614030598828345754055784221577915218220982141402857921814225528612248609473863056663675625967852051856861230306184671341532751918601312209902841414242252352581172833650814270992029999377728156799987342840706068124865508668626679412231294018814062603514916003217918689896284811787075673896505998890135895656003018024641402922170549202698520219358021586363252406024921296068789684332371567422041356396402100919794446239693976043737631913864782310809991760508742132420110419176060541074647415410544173167386236254714263223714869059899918350607000725537332615434751661872264618011308353824634185020522533635808427349788319734692327329284395466534996498938611895962731730580563438399448020806351210917334779609710271467547656966909507891634876401307083777533712082635820763906844281348139657734882095938785241568084771478666137660178637173504517915332944592707980355927747581093123615300150321290196383621360432293439648827783425690624371415368713005184712579287984764309923706478413824601420914443851995740562240832758088022010958447905538800545703195583253927138958472475823108376536586922532479517942770202116616020340104439448198288281242843437296131900730553579368483523661706790268814176722091792905569895189867270486173920509982496100375277512252106301432205463324336503985587624748519495841836389116568350553349649868954866642055627033566516032391513785967284516263655065165095067188603696643880826223587206281236578029413109802256759052466378535505816276926533381673583660975483275659040524105054821080409554815626766319474767933211838173015078456067183042972382142931241992277197766713141339768422959044677230028624478139280772398169394211264582225861783607885367294997870355971850860091634052789533582049082465476410338623392418223005819864781935801607153125683571239183271386450008463980326481595018305396428232636110100713230187888640000, - 20542071620082469102935798134679364785092093613188150505742844573726289255436727464555632961640568498632307087985208757927718972579029311357351646047904297739232975596916595525710475725393097466914272495427103325750213371514699231185143047606642084857033186056364973520525485682764771762066014010021029497485977171008385145218333334612438370702943807342716578340306121134727622590500648450771482442707264554183565249291726433894139138811590588293503733174586826536474789055511129581674575306790085882674907770009025257641253848655055336273995187606640621889742098986629970534950189790241506961582001264041746978696428169013222375692795456389513300578220640457652352306681006724285431674769600729775057240780117024668247179606269189130483815243687810631523581833920518485586408529079203514129446600609803444019396599680271450301083860276662183352967753916871820174008976419609718988706607830118291907663080090402033470410722786560351900574137322979668648772531494840424662268038960423567235068919473141576276723883320585468283809842209629201476221034355023794547169746025489154153801145668886526130886109649879498781524279253121621752075233039241070508857815163582973927778581678569689069549249961547398546180041542593374369386222162044328447498744285752892798865695453558249295655202159566310314739321106068254265654748408588008758954426256309556784704659017217550256392104307610922127802821753634224427581863953825614258762059796952135063498062094867235207611438290242267334550717591428141520543599185772967391975554152442657394282911313404651024476079343028199429293490650787338013626017213755755696186254086171407930065297899665041220716613734963869565112938322030519386609305619218121663037414307427763956285933802982474290979909741792844820109759065758342923253349714474578323280998622702296710859634918198918165183713072437501300263978972162836794068490741300792541646501508470840053596002343971490872964633114371582442477321184092289140732804137493035153225091177367490784646040027015270976509318794922067550099957421969272709425558997612982160526239376780157843609443404656378338020735400200658203004085547232853645778233754523376642684285187095366747330499733234021799676962011362852820029399434945547241863213673168688377880598379440928674308821939520730161659714934691798262092569638291719259311760472637605955847273706121649190736021938168116935440918075755666200297941996080871531874676674624119492318033722735709277297192048053446783347497812795488229243954958749551814430692924862723293287585678012569686223239284789411714450816500059069200708579201953286500233145774430134568472906844284626128469120740203304880729701419776794362978839539792818130569974131703699273279383181062677790642823290880957172213708163059340294075570330988558693400546327836573421891243293887570921429400687844494857748173567687794129703943429484483317086536166996350213640309508500750417531535535594024301765836762885381379433792589909389683269116147195819666281622466342484480704025354956125018431111136174287054873908220146136633248636709444531909659624322522142477109560123275002684191621418354792617035422465505497523177087484243432973626655281667159197889362413251804730895750506528314488882009746494286083292154990064861059346194190389601197713511628611934848892059163579401280331029094265699270462252381759167410670853651031939649630455716853590058461025131526125201383397662834207159831375491308323191758433161320810717544103630490348280382459356449568983801958528507991929124538355888396495909630968120629973533983337096405441835448513093060978622390476059959034305734740257190052178066733099904269781281681025044626525905518742439333117874458066439101880580236325183226280984555800415000825974233850841282749677421119954794829616257908646169519985898645366300414603172788415104266725557961707864463157209738127665624900064239619884741722712178249179240755499023085237458771235703122438581179801239736186393250899375275373794436584630822170329483673998008094399586535554706570520089720260859508277539862333444047293853835129797456503632281181052977003066648452660161436942250296625004283051281958466513587380172253373165043028439858537036380374179049795535921246894348030618723540568870116919099276196723266355245345830565025004302175296535062556865839009520462467988369558914463699701417847606535883171160095152491810003091943999391609052580564860494968792968198420835895931697524973494362587861038652769887040109943679795826600286254652257861757211813885582512909589400026448328915377378631166198296639546586308997793027129593650300237887011684717495620288557592670006113139382746534153430898399525895668052210898452030343311011888326351792796247339149851227971698995838034030159720794657525535374703737248344563832012661315399907018527546506256735716828881612204378205569926581514964911705131802001827862778626601950360486452787908278416127147426557459105091143162814092261826276468474712061200915356446397451273066652800814605654343531109329567758830341903484849137550180656448261798246193821509363273220909897824677833871942670870349390042667864163290040172200206217768001008301876930167374803318410627806063895812012115026306845425847734709801765104073616015470422924329020270336353869773924478305520304556002875977535205075890879948325485275063581731296184959753294336273747476525740414407416216873845593433581484120509008358093892723880182143900587947611154362798374202688442915661791763204309749207072717176149237823116123907106324425529476108120745458959249994030299172692303979150778067610323712478721699225950100866765163416654950718125566972055964770941878804193517887463105095695043285926515258094315291075654394213562396897336275628623768235940703089646752581167459784867341343713955592048155569819900276691792392235424905734380313880631665452610848940688117876806767280141461944631916521929617833193692710463511644865984900125174975086619475648442306948029393170584121305943925920908097711256242699778758445525416585441842461376690800498437122099914754841511583592995033378890491823758815929187381463166452408837340610916985095920790108721211645395778701831022911181894058824090817379974861594947930718662022599603155655386172740252183986584969950672542646067440939362192529987212157788794804548799690673218939800801816127088294024284339879485828398699838689339371260124546909050175474210034347796853101497148235695070344952049089641088675034326298154642385315603018916011453314574486846570435052663612264207612052093493127323238445127093320526369101203682890666304038483315696056500444388461041244532211871395577660843969286376012099802198440193542915891491299986929872401307028963887179735403405941375379535043538583127058215036885640522074911766050878213633899388407149462680574343384249141793345075545446951664299783207059695058345172583812242555905997099036385439839212717643489082526659209469785127799460171622952251031068318759247633206310105899090245126877830629625599489267200557305233541447855950166977084193804591248637242009223786367642930846151756850337781950177051834793955499257747297415246782144337821759034990787462339881599546885489794575348389321961116637951048178763051086909379570611979059249545440835707342691287374533895726165673901111975562546437802865305476932214510174855694675626338790927819022474641472161217432716316755058477105926738763746244438404373758567421081601402964821122672023101157794378225070350827126161482350244262750615701678484096679715846242264720403758957361809487407081506544520095427606639877669402420172753328168041432823561641151879108129313880563979157429126076584369296693725671976942613639709360830833482017850891688654199368362294695356435002012170510748936413933171532096273098172537066763741013633162818392633464256163907260287677228566415082886267364181979622265044337836082350178310668008804857720293269209346483965078494027573891281474872982925596263507559773438207543497628025089410319409782347622628292416327103154707037800371828289025540476310796793552843379473661712109419488817786737809902994685034348463273211247344134467468504447471465503545887071713162375925501323410972781234181793472073541496974044795236882998031120179895063819950098956238270004649621054262171929537338710155754108218154303438488252913766712099962437295258274968297485442048309841475222877103786622289591531179500508695420594645048424018694776105705743548689827789041702294301312259085173373047237783716441977808211456946252001532223051952410414239568334825921071251486436108042378254271900384610130414039470467231870620021272176969298156125965662227534510344821398076258662132954064682892075581985549169955593652093043238930960754604928920032981195688940405633889365612548483823814036252139835997311236173947692994022466602089802682702798747168553454696066701644182702475071348188420497663680143708147708017932354806646967547811134485534614768461141822384212640836430067408425055598486583620761103920293146793696649405595278428137276711663831138890317644315391944328566604531430599571451809080039540554111895650194518585920729845821472354812350871515642928291646638606597089346626885649945361788212866771020965871495298611883674554504229524481684883174983878937029332516345219619343804447623454518735764214251520000, - 1565020758975267996747553098788494800969429778383115582965773413423575070228468495201047107669955036769075991192973983147818657398124088018798234334208104363087098130521110084971150778264555286656178277267517072324851574780878195741696895879674341497493842166576670570515213685310996630865608608916585673739877831951159501875947436563455513775530186166441498876878670065179798128242844279814385414353171413193793343868381189147731246816914628186703784748294937004483943010022531703237159290588548500870736137388205651505420240558348841131732286798513043602719458613472552298694305334465100853233593715380382880216695731833322501174310037923391919745400820402335555239157708732549799535653691049314255368003293719143581127980188891680675598312766106956505826932877828159713718521449055937011059184206751721920276884578417959774034609940934934394708191580318767035359853078014437079889645973012052498757793765703336372031811232060369835748345346456121388725316430349598974088423668698719816831377038189031060477299417569775560166427327919942186553544014573571856735212336440281416084548843115584503070267237510105554463806691982318345646618513001714343271696970990326910358922397529101816015375625146718692938554288228324829776004457134603067878218023535174643716462261995269253975691633332357622079111382984896610953741958519545246323359225971293987284742175353651210012548253298227597821337095011543667824959428323127908227998920486759091662013219619817693216255639433558830383344484286954351458334551000987034959478263691250036020753064852630210699757585782515519519940645539081509184877284095331135056292544994655164518860056051269528713520719326575231095836325213475483234446758619790298935034530616946558932164276026887202710530280988998902421793931537801706357792510204427581087164718244016912297158933643375003301244618638755226684965728605904506341436905889163152616776243473427332547505854284280678256649236259618734117573880549552641760351257548954132589191315090938995465875260226361669419961989856045819091893020219070007084983911689557652496079376223934435079177506708325183611491493029718779227138405247455000115695793884270382838724810518879083209390622996399239127630503750993301941099098107273628579523519231848813420240299354907948075144531668238907053275090742046423858783467045532591213985272482145852389172598102968594498248241577092483806022930815482857466841235744001908504218980133711549022288335833835374628550781251339611901003476062681346015218597913803976602037330207698111896213671849800406211980834083239137374795561700819656564453523180991661126507615036921274356435375890488057391061448374570008156619614929841384243718818468466246309230536954060957375831610367819642112934477703522676988257236890620334302930239701871144510656598398519324195067725012749302724354781659043624161599796399679937903052205927861584160457239268652395690528135531680121020991000101565034320612009559670034922936916586995159661000325768497417604024397504017990543767739937040278733483451961795581740162830202958813226995320028811161505252956824176816859458077623375114868087571103993852137120502638674442370206509436995194993608962506844353654014473083762843901803937698120187162069589319877378151915483488158888467493717944300692321479416824696689443087695011846337221922000000717134907453733597113759478064118372806724361985420484697927866789560621837468511669633186315723606365601342696399813183571000918216335343644665030013293252798126623544545959627870878965289876363196707086177166333111697369154819385320305748510927228461081452235211951396212717374061566991210901337097643459472275326589110147728094626796906408420369392627333682094325668509197129684236441199591514611752562307749698283321529585662335826014942493357329578675520577267901133111781213824371378386662755903838107141642952930276172208820402088397944796535559495937974821073665834040244750762714524726584825752880167319202856882656577486185497584773636957475618241888820126869586727127947816051911896981563125716123838516142164858383854076301972466018947305749585736265969682511283402847484521003323190203398332144641020880487346657396388237931148935672084810457629321142614406215939524934785618208191812370583343455619701311750055578616327735933495398869127018110805039136921879921669759489191969324000620565044592133800575515577699542639497357937503606903276792209493712382417076216599568275841134159587594796040695181173784566433043730545834296467108504676021950210807918027341038360479913252220774463964553711186307274838194517129571438130370428185076714794212627815618220816249945238053920725020574260431091449080637899016442502468315402757601797557874616347651445810088018143639945304656941170792750207485386911501150234135496271543828917259730703086876625999392432075074364049714724263633052090832186246088514608836637666102987360536058120461927514132311349804923452215784300624010596079845972526261750222751744322799962060042718254913233765766083452222892461089033186001521460296998198286173770798588832670602082192641612243016711928104225968893911582189379468397398253461595831658088424433940296439663611862550844770277571798221406982291065440210807159740767064577873112470279778645220405481593032681452981369439634937669994675519810085532816121892900027466289686411410606143340232579675081699235991308412836396955734700908914683338594215873858856159919013158248550467636456247888027731435785251999995036585143099247055558497462843960286151364517051081168720281533704615710960799872547384922118822878182161548335825696896478984550630062732530008178394912199756797955822870214660446117424898153266830558264246577855252358520918369342340424127415920404342426398725351238573771382563861707890458868336821967657570003000296283516651034162890097957368343984004196663800434587784501779533507374469764740301398894574796312774553739751777246911268819399658764003638166647606660327364828569716791620596600416158253283696965263492545348173345282799899606048537819993582529852464265745190345375337685157342189195844866479863532589246702774385058771985579350397645316572948586328737796056155388718959916281511372972381286712919930508763257902712312145806207093930235573309364050837584531365803122499167085512339201548166496173061212203735132928129759024174205489686922325251005612822358928559077051258403807630053974956255319744885362386388833315265774044074100367314780130056588664698168681394198294454577408960633501710376771216764471397691076705860719400346440330395486169200104947762807273841376365261053107604490663454803019295147062776970775058089232911558522048589929378703333494731549088178497699137583740737462318181134622920426439452932714689072232742147634261878561694944784354729969098966529872478625405056644046641911922252206536709545728970234133744227211733809943199712963666643314781873173912597478601714944481118286569498094917064829338294061207440696000632035024963562282070527736657277807713242136683365382112391669399226161049124127854326040495261059771578913712593486558017657022514120576258059978737597201043565795860387007047472968336621962756801017949404852100954575173890743939023149205598661913148554571414360605371912579921147961840234915032330121197706303385928363134275413323845181285129471308552528726488426772575696761916293211498733607288305222138962186982606780540143230181355461038796041264123168053331255358939778051917406856945923880986915335171703471501503124892947835386421753511197159558690749798543262962266986658320742108554475810775179788106353777075854099822305805491059285974815634212855689890272421200330510856747145699297711919265197773250739317060375189518648008605503792657491620252729043822022310735110959706352958834508318492372572665436684420120223499675156502914275396101030244780316752929153723601650519586306584743360059348690066353007992334400749087031735843075508373848858393308770855698284956589896797626740811100035024622400034549131545142120910569575529407534934817940265331848369639636179436016553055816318836947368720708817499737576873809998189122671097843077701726388271283120952130209790111084353046172298166763407614367722211101337423686982716421598456365504930758613574347064534929648256215257930667664387171283342744681087006429811512097740387548854526029521438897111276595868591116825534937039781865403877804249942742737252081974386178461337220971017935697612929329743240239964134617818062856809080838900580242798267121188064606231394056768066581136385119189291488163275793113427828968583546021052236370942755437966417688249058836596369992510706539778555371064213260655337876390994243188203700492954815905464035153058569686384531380374954428050043191623558229870684036977065101978520754702736167263672425423464230360304830444491447740309897758627303302403368041780153956748908596758497043269523687112321020541831606440088145299383039758491306369149887965476102637548233370517383617155499354851470189008670568095831001572993111988321198694863401061827157092871685960844847139691548923387343315010748996921625152341413749667578733129135685288240573868475911297412460587032826126307061075305728601444221648846893749403655556042268006402226581308806051341808788353755643651234332403294477315420979200000, - 111411280687837780384228762386481042306096759181952125888779047838578994015694765505595295506179051105312634000695288701588567383749272004079536960382396960255988767341462836182527924471224271719600004184358955405045272565197328787906843133925827127393932188635478602082389666159703878048265971186760405499771589261325696838406561567926624992740315003204696676713038278480281944271738004439568249137774942759973706878169171400901822221658681796515352359366307945750754093172928491400537963061772145661464195807481369291308859617662118085509547251779368846295633663006382484035309335288984729635508755225683031569908042635356873632778785083697740794912739956767757964031437866945753869322909504409737119762095333536181509359416193628419360763283804181752091865887924071451822442823625208263007038016487338532441723493799711133286282943267367120876176866145426085994416247778545364610940029370631891323226629057810825318420992242430891749053619130111784470210002423128972048377936004490543194714052648819531399280340297276929958898146451938328434793986880586815097332859502558777310354104561895063555998253255239743367769601026519431092094694042742977853008870850392680166027051842065654950553151133579302236355982735830770972163315426024350690022019115107644314805938137621350879762443639702167711463263413532446427014391386672830693692036169066247832252370683268139784346212152871399109245672014562442608670395553242578948231808591733964183345070443516000459159562112367136521574216601118618637763126695761865426577247510597151347633262507224336262926444711129708591830534207972013490283819835895036256545984665726366544389322782671796262426709737839028499526647993743142888279612152249060290842350458082158571522811964484640374092161068636132371944520020960752571821823193678227916855766665508015516487363689380875145101476761467455566432628711460280796348498402186278882179788348469780661984919721109688179974760386642172609277527081773937630284412693187870979739962448972755486863458790982436813191735713726600702050516411119626396554116829825854290660212378127128207621305890159470206684597784909036748764447847698029943841614295439396185636024751443305434041100670006130483596198735714005223199990503536511594642640825251317321838975106694339205918629130918438679489804766650176385669591491242791064390667276971973069348172717511275110489500198266342896655791642185905919628466494480404160656920637134340801934840383101469019433703106942730107701537081024090976246931843528833689741594149245379245727981295008513299861076002433540351177337586434843742290917967290955904312134131328887217235429751926115353684528041241831800775672094940570444803820483681863484725500412694492497006919781432186991462790808723878716356972281926738100143961464321489499137672404550028301445160354710366256116664017999888663156830403174684788213640565623369430611543237727652188911773125283909491580421478409458471000138717743145445786838702720209937139813570495989923234036680407952455284530728069720711280971234164747424405226102234162252451115211957988577629387908999869386904433434369349376670363114212753180267587438291256800734351670511052842258992845815911533296582902744719383672992605396945109628509441335245118116849705376810003874365561191871333341835315701489527423624560574635397442406757877428699859175269272299885025188601692102961433905104752417477490136375334275232967212154342783917862977723318461856832474473819998972092482757157430388210060663624357487376294409479179484690118273339789140651506525752557821520087753974595736426232491763156045060232385775754314622541246363023198162241622836601482357208488201058058608034027908224170177577903378717807457551096005450294223619113699331991662170148848199522610873243827032438918132111399605533446093243307197092738679585548265737583006784715384939425239543324403660067887186407012817104240037443868862156737888220475924238975658678817830034347205142249617320781103409735866399765186306645586676966239461483188589720684583540867977659108948537765796239064308639092234709966055098395733114339522775984716235150763830577139727416302987591516361453226379275520331534297653053320675675035194400918356460265780135140265368604073674900388366070220692383816914107136167839438904059416514798294638402937916588983247008260678806909686741005258449634350956388723901592939974959113995726631083203614180499251795652785685739672762502970066762896207353544418250520265223928447959840532317688033316365922048252510552642180209397817492773812681521140069705114713505608091299984074804082914461434588026950448009513342423044921319733193295124628891917252888396027773941998921794827601246131889265256233571767658126663688892972365767791037936955449912179786928463212131166432986269766276304923780798113025923047102007329287650169258528107497123687604019666712619165480783985062268774445283875940511727959312021721383647795782176701123096081474440069324588783994653908343441739869327003886311184859924817708056031451533585560774672167100575510985534648530450491806305435418969911918757792966120655415304671634447414517618143797587780138064849228346229651795528990940515443729766429530920760854602919605815077742783387361596319080812129188211822740448967143850006596574269506082369473178424026481201914005846118342872568888102869839090136451390869559788787480671102317520927739514037293556638604366926009568832349940002749525318538204054328271442882623074121267535014364310981231436272949490957134404074105673223865323402330608000950148908942748025194105415806532711320709454008230142300930029256473023191072777727560360098073360637926293914065536410638512821372449879254479868538896086270201904337450978298308719532880206385567759553508740147377062346264132166947975205213420930113696001529660194524298288381523650088206237499393728065874010205633247762578724183958978846573048903983363967292924084522115193207638521889056848934046607891269235765869105737509024728276191246968706596662808509642385014522801542132079570468347042710152617711520339960821265292343510381882344673335802723670697295115478131802052855799834256563637374012317898389757762700037543360017171344907955321317950646682078532384477096926768148985258164952541611717381102431207621717105596579313385987462522260342039696646416903309426102657291371480721592681866759124360983230239658456741458594460276073651574562876028403260935741544450965831553613082983186272718295651940742040371014640418696474177558438448897081780223353843896469742122455924718606807258379580868040860746206480464542612004272689867878000658729975081274605174115663584020385174434962430047840012759088654931803385235631531191182461402536320939647016587343510422160918723166337284154105007731794953447742984259773984577713809724475105160653772958268854867500654245980652877546516577282144704660675160088269347737938748953453101220411945610194265107449984440527366794671668955945207055260397316538568852561536738084635166642025732973838126073495000521311234273454272027480914951872187352035177473415525266582503456526668147453148177026310956564183618896404981267628202602874629111737475873804020358313616815269702582760470609021504953452967283837139632333782977679600615104508831491858947883872205364850108064191986960600975669470388835762567139731850475324832491135128022286049932954252948928064836676096628586868452696191124040312350393936221500332659259138207601093413942466560137175437940940965381117735995574432981020630595656232907759052566277247338108477233752458878735507274485399218138227066743747307346362973563394112306936435575053955385747370679630417937088521389707396364945084661536738939130221618086902474130211336030943010160417678532984869790040987504148497172713965322223172028211820732776831878365800459211310155376008825787641608091796190435273697522254216561012944644639208849699731136829553375223089262592925947055262238795201042978147508979443656559987303883706561357465122446930813596284622421601740969418666804671890832912680672628051958034107852568289583346547209936043747520949882170683067030870817746825100457990640221203491212095325202341171103680884962947540419651162851251476133378614731180774329504969480638096352904426241663970718653625076080096068333612841486252190430252587636532224761245322729578713890560558189174848636033930751504887845201697456448247775216752296613852541897085028142003763859164278530360215498801900483273055986320108390156924852130877408151402768109874915519598592589269770286234538241398599600332797868644346962023862381532490649543242867629543206143766879651719452447044737830085050921562039798685969335801222239300184331703776908681704069560734904224066650330813047753625986377151178680685073267116182148574040210642101516414763001855928225800469848521466235968509379733957374330099407787464601156514301972773930964985257771614364599556995132520213663431674576129555188663452351569698967928056622942603118517743195252280883129598762053863601239421497938236491390908168532537339160093530450220294443949453056928948959852027504662239949264760086165090445835680138164185650224144572481009496892236122811703941779576518117974856576153136648156770045470404581383337307767435286999298211840000, - 7387556935130347032852059858353236030287490215544325124949532301663682031573556906858406044893097251363184106690165212619605667339513949298171529650168664346227206486101718146475841396222707936921940897420601670273367413029131578330915763174320168985136619536431314601264054011178806131993392717368564567036264043156395700359282587030185193597892684078419996373619258154057975323049978334409053297303407701039167348374253200611773130443818575806132442571746862654533181661117312348965347994373131138655394501668460084821533892279752673700640247373609642971383069206065054429543768955415166142506618488690075683306100407179560970414805055658595458224176941027065948602613652199897778297683349368990751440040445826046353260530947261665291576401195158408617988511768779835373911145672791300863893268623565431223366176297896697488705346344734005018175289484568985350005343201826435390498125658139049296598970728006907344869739185892781877763950755306417537362147918476831480953831343868558115990451702704743979223413782331736844082054212029139878804912755249792720714934995939640623304502917136672232245965011219983644509683218334445376185712768307661223954349403696105652057336414651115503183795774889071330716846021359158845847159443753935097201570061228658094939154646206713080910091853271183096310265936571341015900291855844767164447537495921228885733945599677809801092308344737901001431421632268170875181525235097837868954469638535180542165556957108632620851022494920131977638032482851429104723060173978970336676794684251744269124011678582830449577920104869855412640724820382364831251193401338299877835099222278547867605178097937291353159147641654625737115316398021800420695179941152567390880764161643372434138505126316626804013152996590327425285056158361997425388167037913620214348699435582979685532176786050705002483966220792778967518012084676614410987290368077191207204929023005903712279860518467960568326512692267840284765850200556839837545420014431968248384257954631334717577362587378782337901252064816815931770689005318402973044208362891004053324881911565548839032547759143182693902331688773871447473158453532193990273154159119269260799582823712837941277030670758193927336775828782009180008462338715790268410798742520276667897550840667198100283184563241785491648932429584228563514898913534079936854779076312372764266386241726846354630212090824725805269898473216928427736387423200153239403917825260945952348146582238284966574790831498298174703265253418326119948037524736871057391173007646084275468644978129439650049131971810053070186127097896742328781264898435440905111997353378734555790113562817298654455499946148259084160439507906473496599964242239772382669683919660626997010071706680331130891661546737417235393408961232183457492046460708717738491634367228832392494805895392596422724707132027550903647500998021776178803250716390923752415568769871922855108652159307443294557994827228332866867564220115466617182330564674101417739683569105853147501213233942758865690616951858447600162586354393851884107550324670115332892808963275028921248943448197364332003036508054842417256047461909283005065306864328710413809535695954043597232995169008642786362031786393779372092687603549358483220935968316520229447688941233700015279349379832149563253130703309187970262982301809874909713895945698105438213349523403900285561015947877619810002280019017521973721635508763652368684119516234751902116407708613687891743473767963740684158886156640746485294289233703708272557215711353315073741660965405270607437274576332381507702934239141338687330592134712701500503470171298136016600902633014967869568112925239240004313661554530469163514160142461622627714327999537219385155710723572795631830943799693500615636394449317689612205393184142893551994653985607139164853554367932310236246630200253732708127564648609275962951323219042680770733579288899071047739120154448299711498255389499772870339885708486192501135883645435005041487799615662104177590441914606864613410886738539560409857125809007825130695386964797413872515039261719032950580505376835372785402004496532913915093389703301183737492028288738293738785876399387845991245984189814234952253076760333744609077469029216412464091033169969674108274143352777092698059036303396149230178287730604663769498106519011305397104149827111998509519578470351452780676671718601520184727139443931225450753002818342705342432654433922119518850710451724046533055123473164832875248434857461645502424719714410644247748212241069398767048241955746474396780989450780067135465299702913136322314209995958291309566623172822587396610615841325190167375804938615906301182792535392195860612616519693807822400900699501416665305233366623124898049442389550695983424038800974969316595397143680124717727746785407159380101053175710775197648773271035996665412283435104650277116956454541986728780644069263220360445696983602868098841716734721711494649914902678246129901415557568548141952159797804128854240295358024747853571927198306685957259206646364851273387093807117964410561558280273893618687336713823338411289646189832325614500064149397210375245650546747158077561659434138141273673680490283600836963157903211843010941664807509596838331768310871102666109213986830716874291120224933252222765957181033419247399450995886384681092715711880063063201898161288037634852119771595267148017189220228332739254824862875181564526305637091578638142278779624804767374390515413023911334379629096060593290984132840325175572563381044326256389545310226937855275638237063466099233034869067516204422151282418499267067252607213594268543559921654380526106561253655922931226605720980335839944275409584735330339099154063463196960580554167399066110210963961976465684212033014579793289967044299790162213875631611916870447919691541667839188613637331191747298792849633182099947644192383878496910588194098440902521591841221324966997214156218731785972789410277984742500782957453232557038655627899628407389192189902165034099760603375545155469263082362573481449091472996111472744486804546677962978280410515002492992447728238238876721184173303150031746295404995518078455397017069025708464080898470969745430254934569865378227201563466122942852312151866715332355012475423304154542638275095118062727854000493210261650490190172129705843034969299034012175710393314148532230494923560578151165430801737887317410052143274341111287471261891472942034338668537026347977602415640127177674895750507860823974604658297416953762021581694461811494303301517181412535833808110116747889259691105615741135953289487744291096250194444772793649309687263756829097685155261373978906100422583988276170198181055343168031847298462769837845240366026844638686630653924549632985810813960880198282279191072965146736199740769211837516273898322777317640302097519156602819314342033177583475733795534075057556540816101347250607138374641863821550102716737251499101648407580722803339502815417385186762528324340245127707189656470213018680796529452273197998951094803077323656366207903180484596272262123581152895791780290420740278164541990076835337634319814152393509015049609115368921266349499094007022987190445820822632702486247222828720199375322181092449891511122722956709194290183515667794380741498008615549064389769252393197976545476740704075471380165947889517655796225220094566450643444926563657609760218113002830110596790129066403093505867758668774017279146499355692082559059867426490842597350786331016157159052572591818454895267688696696585712782422939821706510841453143026023667377100305531054054707160708406702995443856075640589593711129058441829050413505473308407092094014468088565073287495860549229357180140565826601190054047581360870742827302350536621811177981008516794727290598839962840636177483301457891020198744131502106165323240263716808271802886798581246717437750796235787548328832437618585775731352613060715288346691370463488272219298742444147297564782535982455301435902719830898826049634673962143627435070034323432388100310191807712211054225905691505724826531953093970794889477837238713306330192084236152654214760456579429678937034793957866828687986979967084291080378696905005850727433609017198560319331600554006521544542267886054974123958806697654640272002618336410478915311724799917929734939101657257942170627417906137817648813260925139948663230515116293700524765024057419268456219825247600235874687672093754378438042893999693021053715803786584130724216155514233582496308884269522430074983115761365017475150551266240965216617617185704030204704380521422269500006901303612595449343752768193406403963076356313166574404760706701798347438742077295603792516596215505753917481303933249279315858868620660963745237730434312127764112395947475663365472768172908984233683216380822658376362953018240918581461893714093038412074110323740470384617873309922006303884278261617048756719426738240769190060539796719477385284545108225446617743961799597080136021864870062134418299969041055664219656363616219753359376455378587522771095790670184932355196421654696075904909644266159977016751660150230949984537192146548801456917220823771481068162534685280758981059724345761080700625427595469666765144785664564716044092330941511595677371297870072480610281617937913610240000, - 454320124695165683544983494025843241674598131734144941893764100030069923798254522249935236266273545816516233281500958667752704773708854022363208564840612406356397456477414111932488473703917266346120131732404151864216979160948328827888475576923061014940017545489527754971959505760609457257872238939814585092960959606454867146679941605799305068158725045665614773630524538042416888568246774375172032162913052703084306318768382820862523977132173570619175784904538486533630527854827710040103693025149992820167747498555333217564749260948877178931777858689288838585840409412208232645449700941193605448808866518565962456264023900268949267184692468396435547870014700324408477799908259010810222649986082636521024785668982767695518032716368408239784784156148841350268330550885741295694506441609660067078455882137535158230496143784556751408614327947801098896371112088999252875495209884994406025947066731980660244066869646115943328589555594465961430810364491543210356748847203502935637196495376534403792600764832379219583665942047054633467116470015797937577860039687620658621661446811002732256019781988127915760439222743244564066183604997061362404558487149745126480641382787944418910256803590753817827720916218912716976313712878258681921606654046553240671446586819202830780909863942641470996306481551460608920483730516896506094197218228415695151716735391489330655533279507732517547915111483433959427777067577374530272380504282428242680875237006381099026412773901409233638422517924175448878593094608917633028624342144876970879563640484681869948927948926577139341487984251670922707875219809477693775279976946649889260864700309637564280244743254003947005508435151134283363509169600433784563816110965051319490701911644085321935259380886012628241350369551035456912060840508727523186256389835303540838003272113549402289415424164823666781820715099213433364151792387690431150623609033501076012153277012794914623473733890851295341453325336020114991321300477132325249437265352911153548258290661124119659515877125165201803566092053702805776558174221035328716419411154658838931386459135231730236681994202860180049294040736182798813977105779691359613813498505329736719024094669510261686404374818953360347961703616293048314803417180027197004297874507257164093639507564421026183140546887834473184881833515349551930258723411711447019934588922043182333634249245776555039103645288644761253262105677721344531899844904071468631973362473513660965479212160588018483969392378118373394743784062694463034219669485623998379571659855430568357602848058244139294455155242656362115043878316748172503993285331411878387785853283940061928901034397778235973214914676344954245405961554976160693435101642750362041527175478227336213065357234862492059182078614955009736368269727442640182517141758219141985097202761923523184650718236428290388983373321140903209812481296577701926743349992759377584760590691154861754266467293815382771808782830397481687022715698982715383837106887975290155069271696999701977867393901794149869313321888727622881646290634971093722916143611759077852915332783342664311716408820907540215468390080017618471435856093840894304344207496978847825202150564043509709605586716606280589752152964229478379747283667656048457180506105108003661460995878162547197567881503191770805938879321923952262645180187621594820254987403313855710674776826203967765159730759012305215507694146873862183154897998845481344721349077575753095030265396142878166632958143027956525860440753137975454951116263384878757556644627512618112614341113929335940529647423852017788436188965948281192008974516078584120096352200073229793587345278863574132534720210828752672116605390199452703386436987043643506655585980735813013683703817681038750064697633959438150462673033114314733884037956237958560905253661895938951225024900111200980693766370417514968895488634311017394414206374830157828046316243047982182969041905978113532608978191397774329898864480801099223066848538464597776461726402227869165234446316495863111343801683257757937200419458400575926164071674582681680775529767009121325416301497282736845868629734143901914161625552143153107682366721633630357171165922330569623268223120672862048518996391735358354091779913796352011893391208475254378303370612764547895443823396939183754212900071421147358623792770980193759367268124245298040084915826039192677255033858846429696214849675749584435583856619465195106717140819516004825576587515151926369855072151590804445818680861851248852458181277022655669330280715857264660460036925471154816265361379604484970480082919316127151062635868179829230573835470019663385138705765108916755020209883203705030564333327088079367905582762974554884723106105774058121087744914883594328926624493372945235524637259464854388382994644513055434216438922648803425412513912775638593667630663550712399326433100169491064628109175349981470640382067699095182503875759087776696775159065315313186021359751270427728517219037318911847718875933684817251172449720013399735089060289469026166594931857723879761999021934794933514701758391412730043963183191315526438285302002551758306413574974187739371591455682170297054784444599132979782048638826592951164486362662422566068142659594113716567350953042242853744554593411305227359225391692891043811891797775330143387041544327008705531170571807349665401236584860831487928612355075690113599634570603603209903947385452246669167670146743212855613348363683077645968040974748023040832383767300588021388182871994233059320788892984635505243657872994179328713502009612488839402438750338046748113265377516370114811039240103019702824992247660819445662083269106132990893118215793197776542060541522044985479589578884789365489598009113715150849132089989249233530767329287430428773613730640419577545262682918266491499097516594912526630147784973104475759220877593057809915321573244389720038842317598148805076488533799123158145688348449376820159690283267645659288193502396908346526940283681923854137534283222776833009361925908179211044003651305870164206412233354821225506468351300937995107259923102192999302658809580189430816549806729491622450256584473678606869159144183791976070588486477858947244777440030432630299197909417341758699911886820504860359843148334424119867765503082896939335032010250959015190767582562946750590686312928123560065687556179337240501521210552259989564212355375907187350142565841017848435728570196580258767291721482917334046815775537512958368820164539276089925218014422560439050985750557767765942108750173477565814316180869619583635475599401230415904086440182498400450754523455416940120712105494421406398275095674257655463123828793525155009635206963709384808798891857551934154281472587586503776469478321316006349433922052848505285779973013207699803249810703529555596349366591949675009181280061229028412920432300264740659251875737193256985036379341721892277990679934434192598315860236945730515011354421834915517271803632959428039424247550187337830851088479343144840059350636350868683314113320713578291895464011728158061881342531682741848906797528044476913904604360121117797546558136144525743483117798673897228420128469272505238779254596150503156880961711018979324362742424574909157765897517679669416772839486513946980849243594473145061123919372174207864757788873437645246500592286513949690398348998548476192631413456235201775936701610384121223875194653728439279929171328841938674234863087990215812982598665007211536857993813420227580250513746931810587376500626675396220339836374624713149488633525699768682362483524672113565185476530205141909417475725083362567713584060958484991845523742837325986778769031166818283724571117245681546613733806863329668672788936845234357832360708513269311766551280341320866476838888374233860967915383705463476145642115336662051366093955416845492642379619418605356897495552423445830640480114002956831921433297516826072356285101785809658962319923184096696904260327824499026189939855315256549412750300685374599447458728439341358938467531294091058797417069488465701360000637807186763761228764673115541998572123410567355265608271845196837283800339625038988177137862115071836395371685057916871271742249807093057178347029448020861505752506267542311809749312473688439849145217210194485376341765161617374540715891907712463707012478191951705719189242513510869330041146570001140600499397010055139533632532758228353117140875008595641093160479972318758744695194175612573850119119723587776430673918495254354295971270763591947227305440396213522969056890221268257752075498538129822971637940036999040730245484117458101267840000013475296891329087537490979779057416566914840264632615203536199446720805445407206341567962770213238869165955009800027694497463590895251280999009806119152911061660992101220918669930405716241582388545623935582116048903574245465379802625117744104580032723125397062930108143639963522923504778708365510481587754542788026501099917194850778051987927674426412066317027184311993376508697024597465422498558802606400027717363117347954135528096857974974698012867015807339567962412455817388785645643775662113410948155839793317463982342184834484065915637615839778218300018102980548916145741528873704509023316893766458844107169784135680000, - 25755050339495989232547952528562532248660341997997240311623223201570379938154357158227445970605635447066919931305484720987067901486521195090534652029210015003837747158471216665012242243401759567409563852282760647077531187090545601652573937322338684753748982102891421517673790533881152921575160198676759463746758860123661905780803734686109329232046217580183400333308209317855993448031994433871736922167849315793405474005990290210421909206749276726723803573481488154973202285596473368842934808856657695546113525341370793659839069193201100808924082575008558859549237954163366305161100169446386708849528104180077031820341495095943495312008165604178076278498410064301956271797733373119915096480927421515307495237555789377616865421476678851453799655277594390147048140860535660366299575828099436253958722526785373921469992156585850239053749956290727431306181639048280478037340815861357648204018721579665154518908380351125476532096769918001524682706725426394602854940311612514931255098943685204567741986911659054740024467904632856902144699462232219377407901586711543619747186648613240803292240958686738367756644541301188379236203480993967340732786977289578265139689281110766633640758008780719079193488239484878801275105921188524798973623181244094268291687704817387692726809902358021227184205013506528519088276144248739179353774574637596792989887431615192260162110194939186297505796183905989589647195788381627010835538372829064838025469292087484869386998466754231772756205386901143329505826524633921390902654850411582578704753381754386207624454933144058262867847368895204952143132494895703375823093285817690470448536633177013173785376462036870628774424757925843944350996427407784979424441320354851816494641408920508653570126670048030598296110663789743741234090267739894876583277393098477042365095465111006608088509458655984900516191190220339686862010585649448138547062758574395482241920532218664569341952486219733176745581830692198414350868325351370350392571619024392990699689763307478246694848984095269548960280558742712395026382338201080850696085182294786831447103119634163965668641093536963357181666662128456445569902660467170604671070108459177962148971406865086481448056251911586960407233317368267341525055590803077816158588752138835694115995080119549631913052455606585438869674847725912904803503794028387330085922504683246408745082535545692918038953641982108540959110955246715681784373179155524903863101284201537227165379388417951374275411129019521951149815726188774779886033053444268956009590193143595070035109581084251016052208993923847034247154280142817927277161604100733681894340362936931326338455082369189148962072288810326947007683101347603513820292607307028585891929188525978479919227306816386516806090726121241845687684741102761510630952429928623525419688075494093200622486900303634983989514799634060292639114806914567914069076706507523915819255552332710187741111678815087987227546568613973855641373883272871613412044677751288961452080267293894152668206743613375654380630688113573307090837414439589504328273060553847577519781125323049725963602523530628628687099635370081226714922893166280166818545053592589009346167101201917452162175450553249514043130081493874523100358455536085107663764168073098474401253277692650477335773283060726435360068740441489094985097050397342269685562326642341145188336621438935509526779545865596920548630675982573727586635702003487102931410335967656405157033763061677224295924650377357331162289938823550336257772207283169054966578333458120702233381750665395442382613551543733606711848435174475704410090388258740141740547063449322584541831593588703395690765324070770468387151083867003339192981971310165006793787561386128147628440363621013301230376512211696577132615603798808367646263555034403135525362519529784570975374246967153776716602104433833062910674953841949525165452665546875077348922810345025106737999821477071540355166883961668909991449530437111765673570397957811206647277942329388731177985251413558010703793484430805868197289069831855770561562497998297728779935099473255612845765818190495410497811095724083101485074905321683328226437691553612309845291929688910848946673646253758736743293399488340401077629609248190969414602035885329440231256500460821739956094877031505026386091148246441856654510678238498957925211379235896595976383849982819708332050929686562205593187986737628984791677578396946567462506443647788837279953146901263920354862382220467536315639409619133647551546112722522739342637442384791350931905958315870186074889235544258114107550244706513893693086190794857826319047479294005008030811936950039849558765904608503929824298239863839860028267497575763268629565021904335202517779961404351475862415081910669090008001050121065170333243177844501430929474804334383290374574667573316195416195339333677870403474032364838007572674775186136562221876568696769411215531989478563001195561673057516422956472112278609604074868224215813301720717154475363989894640996265846074251947889417702074941696949018480936678171295445602870023615487149121374816852760426190501372767183507940293609286924635701813649479431078887570242072992433097759532118331834007487741461760064756635388276234732160186125843169033208548807979387564516699441620363215569640457338214180906966169258503113196485114837455790005052103586136717936658063517083903170933593170533106996155524459960355376107129365530878999460987286809288588622581501384263369912139170185045767444412748955750224170920974480629359586959136056050773366188335690990200891313284113709480174645136587989671424995789538678515987798768852414187944009524973236603220935371048518684838590465699723107420625813442100302185253036729992367327842626947555607538624817646896173568389332015308874640764309501086753371798345184179370705321236354615810120614322598248650916072115298406718525512853433877309771135132808322361987552352189924051416937335698778730636217106081359489830351269219254486116987987271708256221760531644635301980018110662069786936302736709857200276751235711417227467267707961652761033636068630032518115740054624590911525215152684670890540489248915394488722345495606512875316610032650364272517114123435508443370727057587086864900452240374341027566068877564258290266662210962076026404708076917633518708157913649505395328832049857081452751732774285064765346806213932078534377003956847203837079937366949335905219881069597210658472347247871455024837563377099909257844261621447936177280706880078107345063573960421704867078151825798151630639956506843491670470674833931736540436046374918713636719029180763742543074827575817647923288466775789666908917996707965826119802080181914067658938282959987480880167139497697966840950889024517894089546740308450614442061455681405301052264544814978785915583137594772631942848650534182060853897248455588755917804612526771613366530197195805452752272385496460692191809172084351586785287198273250767706882919994368357514586219047966385917784885552134652749626731831948469343201579360089626489441725789720787673466567686670526059995372934556886429348638097843840576668416607549736871731317180467168695466062751249577989188713372388006938615453285055377200533656188773274233072272583063212613194507702158676719220383385288235742943302622950458937284740237540892728240422906982322603792860072669950465692680228990519234988714445574835275248490109331878316135453814210451317103415216467455026824078114412087706865220032740343362041275862696697975469030515165093816980955525757642768257802485973380280796386085678974276861110647719784716843044512064692425654563078493373154482354482443995965664644599532864842907556549683905512442503598369344517518992167070573169496856050813266524727409377179022267160616880260229642778823405542650087580520627365249103207219732520474158187245006253955557856220176644352714243315560051548015106406793937679746882521933149410813016293295390341300975687277524088443944947783177603633572915035405136893341260469248986171832124331243624487152995848593497686846899749211428392004964005468391673540975634217819517180013277292346964577843168846322871915730605391464759241434536675320321908849118836681929078101274176931076802696673220394152523653014123882802677587676808296965680252382886554613678351741246040460595117969408367374902118231091083536501740218813284518337148126964937757106994723487011291414637843830597472846023987475843738989308461189387994112330505738690834260537883254621989269786715669363523350021346406220783186122755868546015681567698461523057876414102227245472826323088555001477679791723784865250262035885847659324717600579151389308653642194441822617930537239324722423733453167193725739105086700317041620481500469558499434160123645413031227636099749888855488721601014799959542929330529057287150379570907264588692689916385325837616045389714953219953818315192329758423628948634167587388355706540576080967456146117229359441590601228370743367285369741585375089116529438266172700986470879805788878467839079176362719011080449626526146185076612027108832040215137975028783930758502030766151800758808267473590232783185547584891517339471379859730377579257999830535263580323840000, - 1333711978355563949368085669835482129385380104858143816132442909380284329111554704333410700009737161717837170376005285970226667189364317595576739998450833132240131651553035468418012903933003946576841845363987222679053565857264445479495232412956093875259273883946054557322563079071973568249958888854468920691036578866946272715276328916957801309772593055542691831867241774838053089743988396112926747121352335545732468823994954871817851098392527659652890988439783963477377551268325926788861153019308387152617436803629593284103710576268683141284926363905020735128546597753947433340443468865952376167460620170252651507338899689173164063982354926255424932833054081169003118343695150305724390491091335674501976412659740284529296766716382291041521658115882611663573228517522295288369855448181476477141355661450663472346442129831213586839462630220017436928512354610157859318429179210763602395084388987569575237712409342949543914616557351105498170311756419516907055900257969815864860272684506655064117004936094938892505689931162582122558725460176310859556996370622963019894612428993864649103221669786261570382610799402353797470751715065406583393482087276911927968298661505100951380885837145128505240733639161263267587916022344440967748187587049649434537382219227089645831077212975516241959079377151738051879650628016963922272544403341020292214519310323476537903572087986741031225225285009243701953108907645962946432495650831264740922528533906837393092068717754449573075258371166732629587577734852122454850701160874972422728089485888062079295102146762675184912107525968583942106924435401771757987050101877883127174986506368337583809123263113550121528723047910296817665848883648549912395661076228998238423805377414633893810632512943116764299843575356614763724907065182058278163814468513936783213502774397826872962823303793990731406981948111482744593614351602075340231914665288138399796799647781194805692946231703141125783677779405382250973234226016915070416554788136381206735211158604226882386796607647725761255090583778652298258936526522451917001812853307770096585217145766729980921242598293052116961626313898652763937835308121098219577051443126721168501593135000232548241637407891530117368733962917643598680535285603621120347279377241952343218699849435813223596880787680426574715681978734042349998847032333287259751553832764281207983502515125801918949498581401154736009811132584062966458590364939315682023301273621977069677077776204145242598615414559609126387499111039105335861262031769940871451340234969261311140635078909718959538372185489199247724591767956652281551788109846033576750834898255058472383143930077174888408913024081534506082756680389645836582593265911841054891446605135614162966575621044217886457171079427712554460362805143668682474244320011652758603150877901421751523220804131107502725039177758558980451131976537933990224649321133873637364823779394895347146985229596979851944784335455846200723208731431154810023812215955088957697203249702563071353497074959427527825549745704173334561495945052214313225705282504264688760033048539239758664490003286647825737312977154072540988978114021810239524552863800268076402870393939070039076815532516108524324676271906670108514337806577166448842595956741958706527191912381210027456239498183019908805363456858077074940659973196379395012942384080593024072232539295846698968586133708387511350483308095467117646544109654103454844580738564827722236170719193743593840329532250880584770969283804471562210073502926469029500124238426847908099276344711740936275573434398954699106770962716391179013762253625328104061036655602051469322607937330731113815826189060081643429397269729191606102992066435544526964638487677668948518302967921082197988311071213525899698011165914806138304155405590111879404502675334966403285361547650891179123223935848832576192901699329667782970649381978664468862100993719790579629617029706998854332390829313366750662293605514968270448267989386350052113995577377064246539503122924461194814543163196046663277829458676290020676859141959227975624683873251627078845807182856963931301746678322718394725465508962580425014649611337794519762658035496802311484757033109366912143760350855438538098166435982584027853457312075730748705470148214923902116635478640530809059075706620727317736298749966179946424054246457805246619635085549143786307776160546739131611365648956256922477339023685415626297645820099221850631465162032084647020028789791586495462262391771014213555080090259582506273704446697090557760678960664678820097503966133158324166630375445739232860468682482542230379927142533110740765393004671330059294730442733623640269858844478021727926277901981265103906796928905785351114850932742663933197160798328137992681711138758690037395767174189295661166225470377194000410444417820142387794584155580968745208865725089379365896206489513422878269156819213886637614299304733674254966139273598625699978236991861321603845374377120477777693597874559796288783963118261465560329496115917567016782483105750171619035396925607312326232251586267387531444813205284825194830359675409869488363737712647715398326364262893379637759057487354452326250426650379889365378403983963061275989002090400397236979454564715273205259873478358733071943161030391011636375049566866628860895332536181532489951238575687021350515123565411933240872090802098326605241261206341010951309414150006538362549691773620749626769191523487272410072128485605211775322552275321647804805094698208692849073795206234783139887953881106422649208660011454338787099786365057166846271037753939696649735958063608709501441469370277405884932824269700243005439106822644065537513394593819513005806913489852965027101074327633452382503186881314409327478240680212822266053725605792270598026224996219213407375343805715583743852412950383845038513885551154302976257778325515368372922363540536849434968724932867588180097004854764295244282455769575519481459926698678411145418960936480621686357402426173220309824279766325715390031744073157047082357312397908253255049612136775720923737409892184771538994720033014110356102135341709079065669939243002579781918806886423858367912343933439190805914540091546359189054072546723594141649566743307354118459614019024535464314049155367108934739917357866984364360207495091174364577102055895855582555115013639162775682877656015327770004132047731228277051532771313909149585814300942913393341237454941166237740307564413727787781135724348003733133316090420304512655604724133455585829333501909996796061389619539136566103290017948740428768745353159496748244119085092815178671256856973791811742835153084595800598887262762942203230543427436384066204351204135415767304694834300561046686278699588929222498992136829123203871599256721647936558277672700625925120998415795790203261547378906010500104615661973687421748360332342430248559079188957389615553969147017469517225463160189826740434883602082514697161743700503683144320799011119650917853129987612077748463652266768817051060022431563726327440627813623737163027433388580579896436306715203144601507987727869266046576456239469704204961480927450205251193930927535689953375758460474259466805642484193524615428195757937504291418117570892171945081923813613562733650299677828852379559970441845548006474392892650666770567245863900774998021754619203869548576166849682172811503227738864930862315630294045498968805437734402610633450777325328032227526478614306815712651688385006064900869220274975202800431651093219946406637006779179580699987077236244721103919820995806716978532394824301837953894330214599968843197738850277477068068877250600598036866112211072377509482399485151568981766452974688286762677565942425496938888248853060586447467390845177247941060807590920945343754817999361581336485578000653347401037258633692780787205116571534480940778417603568642609023662746541333370954048249794437128266861908762704779804086837686967869582035005376816192324080603666093503116345095490375639178725253738024240663528940619903026419509685832256284915690446310101645482264734733164672168600261347797149234832647467046895471346130558179193967020334576813928311142831247784642376811644480337142659589324340843439718689264881157152229264317796724129612302993326364375663132651893042564674592629885481845733162187318090136490681626371108189158172253489239089425764403196563621856970722112925990546611778416586016945871075209988975733451806381384846549693953423299525560153275336706269010752466673956603843682699066428404441069774409085322844183557994253017227325747641289733016050258070805469472282474029023218074736564226812421080925284905246153811339559787126810203324237310967873709345685016002939763708762421472606254529764873457598064022144005314087867982853999101074650625124680191761040992245482320418305087680145863831987024510838608622332149342818948038715748185780621509516139300179919787626225227320235876406900127303175343331693134709874749513018263390473974161926142919111001953912319570778486730781098257286393014888043192509886366784754031205972345595514581917849343344809634636381128456023127089106328566025909547870817076189544112685450976193025146880000, - 62182213328110337907932423330246573751337022314669711825399804312429103168283394894667617943260500791073221991836153790457482901604187901457850628113687901998342874972856859318107546673973673169991931184266725628151816654310755990220781004844378795186812602658772913994049939472579594959842170564394442606054584958599414075273225321945049506856172176280949803355211269637013960023274139536752683268084929469093009084208342895349308434853763839887439949607685322551942013137097171434458728393542882881061809260005315085863187818211451601498858805762061958391181762555466141824591001333983801161717618739941863830271151832755287987107558758578504841438053486010856417884171713543316293454956883732976860813355708187904213556890038715674673822662823968570895630409403698116969676951043872578252092711743049860903462176676492274077298118335975906014853977932849658124731511644514772189401180797918686110814043846095389353624659865462746943224781852843366276924430678558716378040038974912578734666000066587871107331876138182625854148123422184599573678585073920263512635425885128425671768016838718703545974316905831710988284610203113057866259912843801235422233107063388806416013138589067940627176992415507812394849129005309644782028225610716124481750054085672862335238483740738967007799205488976262624184041478263017156284841547189489462531620692778796100261613101293430885353579370022448240669461621156299732177318647509465238496282256123218105046731130968495967345685982061784277715620228984685042123595052830187526234563427222577015610980820940770057172758984041517256800869175528504191773022223211152868943949672906226781005958669489499443684174026470409693328905871112832386705270816133379781659890175635287082441141524487196897017225764627161187483834221753901681633165396108421984464968822116515580865742404095243907509680424987127796242123364979229933116220722449391973392328170740893247306075084244467255288336701927851650488110399465714457153478185032648974778326686334086498860631401195281922964705676154436932433915103124066187267027168385671159822189112284529177594782941116431390332642741551914528533264420406462486823268982909215050384450990575032744103901621215313891193729415188659667552389766115677392326181967889040863928161118226744386039630830803894935157029965019212955023019484235858905578086029132100477599381550459997134208353014302721605223669645787087978128569299884448732365148503118380099773207894799112001643049978960142892888833878697988824735478902194604953141083131365705575531918513488516605718104828021274606134261869139792317655791486211263105062422926919710714363710929070469928499453149792515102186806476986665701231660529190708417833430408662592959501491547619001158181803386055553571695294266338766199316000836440304011365093344225606404903591347811119679320177875871588448049293695638457195736203106520063687828981749197519282670902032987084738794777953524625546166144947885187229409399045122241759455965186931324506674300866951622431127869327306055679463875148101756059363280451728301569600336281048157502129412096181253266255523964380382646526268161056917495640681314265794263871570801988903330707065745868654086852609664758811825120674348991369337854144363261732088436710995700581126042704710831822848164724372003178404498817597256495665233880306670042629406407613653352697471765568540897363605176452222809585214892961170706493054369355178604119363140784725668537976543465866123009919159958590712230585505710197207195571946406801283810742880250537276809640774285027324150039128001921276248776930370672201829799381593235784894413846371065594241398990797712311433729538141651621184170961649178940678913197456235144229791807779941232514397640636881342204744120805857309282586500368566323716500322520930023257759155699499206794241014548343482560581561643947645902576523376188166624475791014085824672322962329096473138276620071608566452268706006226534692645250463994923747814349278223140579844120078980025740785353398926313239540742312675934248272422134551700599988667295459568019688482121017934709928620157475838124954917779271521219338178093092585694625911770520478938015054749599446540875447067615845537779901525928351630856517306897987622199780337345140232196324470236195964498511326232100134797446771022465936363076071680236805014419995954997759780618096598849717089641718473595113827846977095639210943753795861236434222560592657771499200046084735116546707014965890446443218532118936147412509581283237998666009792290337023543799229787395481189953309684431577538624987708894398337589428848916985449950664783714093627265060663432014973535743207028944858127875135763649875424685625566248816810188856461778487472961368860246754003059878063045163217975643317089650482729905215539138988117430574047834960496413198294880560701217485832715672421954247191358124561630429100333667345514618320384348803450429156062416310668822537608597693755398966313864939948355467070669384144032894491442341368106751944897983542949791397908727434864376728063205037730951828149812064278538580893076564785382146510257945433669321416966712991252128844851148978105072617162695066803794348813403500881722251536830237165743478250777087860154857582733968981033879368891621114497301576285855392290803503061472158785957005581176403738865305383566843625012019743337990576377766505773173572615509952759909793573006624898697761609007758326486887386091610526524272618976798892959195228639674497917495123883243063273265341044602041508378042262585441019280786786539952280482297997939263714412064444339015298085388213574527959581866903025541211205168383292461753834060941533006986171466669056723690883345570594291164990279364403599776061889326901044436937462498008743589169691200230968697414686013062309900873494859968375792625144566710426405835582929910759149175181787828464572466295326350398522385645239553632621472083479470022182507680868263214377723061877835908067169906609052359944125451573832801404109697956806787517573666270041751735719812484428158008077623496841891915356506463048888808933966916185176393250468445567798042840097424035436666000370103082752288218881992468972669746455028076563618982492699268357212380315019652341638067348867116997630116109726494716000858951764340584705075259767056994071839359447314757400273657025183924753985866215486696953151107361994446944687780037621519304019136104442050393337480393561695432092825846541496509115619031385695684696240273287113063781051724352960418342919306732599357280959236881942524137942316496132262166850885845428696395737344043479083985639434280075309853507135560390772005343463147453186452146662400740122024248196719961965647260774013553342966886929704991620527196452208030128735261397339387543749334072154036733706508158568600316510991561999246275266521136239763987258411719239708265898756325823975979137827841588073151783321468243579495082502602889571766652009987508242124962712431998666301760669625952174499562035073931629697067399607956452802723086319107553147803317576749796858786455398801397707226041969242425314800022784974279060574430860503955819067821872247699234399578881795369883889775825759638762837381121326726408718991083971701221624047411279275691101262247080757911205733763571001650287654866273907814136048828438219280767002167074712176850714652100236723894057703263761796681338884107854272389755822342513899042970905887387341463375776490534134895759761447865533651808829019906618222691810046513508616131290574242872865331397670724021359623247657837793820431221137853879858825086213842594615179913652605160383871046716169884860277012504750938907339803800602420748875182601156405096479296005502388801800178061235510245600401929756061798710069959762137015231166339590341727514260135026782921010704817515495418592535536206696553432748255545629490990833391822778518540816614484759181480011557300007021529804926113858001562624531093675355957611772889705443924120773489010823331358215589583572076608938413234452707881405659874767159000203672722303138399982576779970202420873452014729678496813079740292648575315283681756249921585426007227959786586104303298379541308742956538610682772397928478838510360988645851194348907779337662337508215043397208881836542614332073290964376402136131947259732222416590798766851421895452908429732500485440013432300107053433032053219470530987626654502962607616418343521649562933863000041028429467033605086642556722107093177451521958805291144987085389151424402728815299980425592340081201188791711007986131653033201228354380664628174566439122257566067450393228416072221696318663994569153952990644659260975108068105911304005411387429620608004556834692086453008325407004629733943793636920034443993352014546044353627846759484294320838346755177001649534754323066416612674090617038215437956625051321862145563271826927291606895764122742849107624753635327587566247858379752195906488181194094306416896646176842890582939256552235926225621942987681094426632680692510428738475550030317253501922418822321337280766528771358068355696830112778837548121579860832080825550214330046218240000, - 2543683443794795183304864824924151565358028186112909604641370035594521366334013215914665966894729340192472196951574831272523170087611917685130271137702042342105875400659316770652434402257944738589418133395250137958378001889631918087414990667498425152270605725733595975966955429141057448911110993506154097266232365456450873018130164956840893161092090358511988238556371566562170074248423333484527837928193617075252236546608093273934098927117002369448463681119177308509860494952862687199699330767247303756125683239267901122533870741426208243022136336670376506171355989417319021242294208770500194376007948284638840970145130279251698633115585802643151878399609055114346057024382788645141477924649582850072417976357864252524652963791918805929215701659918541363251673135404361344699575845981634684666708962599962879236980842487063958556136709740564038024611571566804566881702023803989139077620815241820533264659377226473009582069351165862822627457760243259586501738983266698152108975658642280723547066669557958598609113999256428007522557928954603473529400417462731955419822913560788382363892966991482812894801958731075610337748961232402283401392980592343377518960361013768773289521424834732428071192037340617808000238159929373939227239715573506231420404420431133073897473327123508071999645316059069757797983843448040170150692389503269322470043854491905056878862801307942229971243960652587754793425221931968180130307120590197628812643223702225556918363428446889456316048677948441269972255440557467098103863685281998132193680797187951132802199725921859834438675080178722732314954655965946458842212761363136135328960971790565517377315773414492083921252123322922038107031837793373876959127633403572107394307182144771665438837452980205397771914438831302869736317161065176030543737327881525506344229717036667594037992892352862294535877420088286792443096934065345170929387862695478054939491550756352347467894779075850117039287442678892076316312253032010694515858921957858591464611811967609055567279377811688880719100625004604469320309040889405179327445979680042682202786455730167165310245510072546803949192450988053728295001953099654122491819414081326868038136826469968339771591009582781189140637782989810422131896287254673597990062300477897845227456328184820472275439033650350157000521627900077968314987023277766494997885408024875647541359435205063812023431816468304244634059265234743680575677383533330463222442777857619945744093533852455353412989644705477361840706841130907879186008349221844441748368998112535311186292018873813173039361265512305978351203364735406151611825866996003998037281247019750191839793476439392435416066871064806023420211900921790815565621211821707447809989426602296130150776658284314626606111443043553971952715022199318002774723833347398134178427086792236169049682164703795547764178852887394108846575696674369062673087992875931420945389055785200148758941870190731730709121079844538452994165268857904352767464284912201496948107328187102135286202006351065620194472853468998666429132385335369287741862182537528034949415290243802134008612242120727936789067327491172128341142432467642726669738250915904870830309206177087778927621547325728561194641487922093514096642689029363147702978879286092227813057214236930191520751094146537631570611622905308349996563621186399245593439851848277330735418285778885898478565467156923623435034572331541874876508334015132002189151775377469525044953290263096800807631521032551671175772299795824155055509220563234866036328209653111678993440852157478114513210458648075150039209422794304448433425678039315961164222727813880628080668589046176081445285401983812650113168089144662429585013526069702719352078845808921694769252341080036076616472865078672364956379278545785177873008392233800515271861035992204860118445018982317630719620861280118047511714290880443558236330585459758189788525112278731215771214020048708354133786287685474439574965412894335419149235239261187217381075594995798888791644008984551819855917564003763813535764580011745229524544129809549787203989217929905872011236747925092604617872551267955698795792822724888469301913167692328382579900542593601648599374995687037494788362986955548486980301885523779807882672799702239544494323982331762340581004193946482485927343294382236500218821123786047886825476550761812739836915355873942237592203190339071899632829285307699352338140311470699872606193858465765113424804334665052404894487973951319865174237800362239095554226409901332615717668628296725200735010859051318608898066496051674487264734971514031588187793566502250014326021679298525576061902198089554697403704786186196882540372258811949739897879414823416649454377283207869421199151980965466079164216566693893243048041914999489858461965855379821734686474627589709730043917725314866524384165749561243340869680147128303487231595010601387635899486125273336483689469059242521353577497541522994179484545862029979694565069641079700179578201007703827491925754839944528836973955208496491409321270229100796539273084973506727764775349097343815781955607758730968679131486841932530163630194489237813542611575343649021009241200449823980772818428125431474818234020903279711137334208045203444258911285818585294172511485983191128053575400297024638663843494172047491663358210193880727451448334150989082880274155563740340916500894511584559003486616589034371625001023606137059217335860333215765108687726738062503042839655391521268030071420701499803413262148907203568710803570312599541621585253036125926351297504193343974972762620130017913113549469645792007323610606499009822928148912694384936245767145185312971979774584101779615957051078674389716756817106725195638146191940658739266862332194242169523930968063033549337386000771748560841113502255373585147336765892275538592893680284917412238347594476052011575440659893322590367934088886860248185429381902188180545704630923716464283683601733260171526227200020478452746000975999701739787301046042022403205429457504132048695602773513346838265338405527239881881032758418305354459960863615718805091293910385836268197784778828444673562683963927791848473137426317998484995441349949162016555160840773355154930224190120623909412802970630855827992158949706514815127869494833691575141441340352169173805941874261732386470835963330884635176254674284471641057144173251739764717547681313060196485401661321850741876314120768181018196761626684537784367648001453115479115212970596361872133600665756259347680420948594011108154234856244752841609877501408837715601957877440682877802522152959338333645043736822688963692608763282435990577357138829504854496515772637048862437189584513683454083226303931617273083474617712723680649989330975606005581850223887022825322152517500259010772836388543335499693563642757868219399690948952171445785588992331589926067093350100636108079571231387456137021866564744051086598270948863104709829202965183722026264580662715329601172103819065123163760154369136904706613429771391027168483014903278805618872871167740169556508479653144905677812974723735042283815174626776150776746857656622341065225998591872642900529917667521656885596466222731144862427303428326200983283729765092192732667140755567062952178438259969725402064282731986591859560307884534261622653513128255947401502274614516976050825556297823356532956363218022016306060745961678055254790626218982714823179708409709939379036872519454034283286768833980583992962955845767153258932753481745623075821414146958371893308498949416238357883750125860819787984865158074204190776384972520124782228434931834991517504831943212351142349429419780179518383894980944718731945190478487094236426056665515240505887678755463963697040693301328490248371674663326243994415436815163484410282166400039092706414646336508282361388939046220082902987059205939389422420700901359137983095624931883476062198755684050282652862034259171877711796662969358375703816228289026058279920030009636950312843501306339529779252034673826743982089963726289168182589575397068993848454164128001158844091580555570339533597051534886413409090231371280440604436370223859580113697484451448498800494350543255619755153341587729180510240091069193779433598996654993647796358582937035953301404159766590617616069460432889949856671660764944496314235123647084994189300371573936216906991909392454715684489508032226554773280166666022218460030090614946865669524066494445912942970997650382381132870315256907558854697186681168354513559319146021312429079361385888811567323611645433846437134366704330203729302239868934672507647450583157201570731535592218127282143358775745991716183573665432348558271167490500343246196213909096273879585263652619177776855001114538340011695650890699083123832365211531074374921414506779496044186186736410287849458917819931261839649366150836211563730390494938215174783768308342150120743435090491371862212865622856356080899027147875364648606997235920118225412553566039508933240811427810663190377637720361215210948868862168819410605157149958114890583044793964458195099122286368701334581052440086274305865414881085260333727501903943654440960000, - 86415248741010421596874850021860830548193822650302361150324604801445404281705360466569524888469103157757455798217872903017636011486455730079052437201509742020623954519293959742696608831122277037892812382693572156366434812964589740968952053992933094773946175000399704981889021050854304680581517563914666261635476342911399918230838169313075040504417517999051154253135619616635345696964081269841846627754278092154449555484171034469453108721202486729297197696155434437766217534254137519201330699761854395649052994903757349988252689717022011325050156594295992898995512699242795802154866307732304727915376406296052589171687284146557163894858118573984103403669812507659536811160313696624236473148243925519339497905224529399041649141224922716416816369520654023858032174003818249588547176695810370951105944660676449381660039224209897569427250676990205481627235919045503133620241847927077942087188091534668807228620160823946793201443128072445210253208916897293563675297990572611898111072265428024790469449906010708807378463107184044889524182640281878539447170819896920238160750818068259699059104150265313854674941989664548163780468613536447906953115273354877879186934982490414794634011377051211213077268587207976991870897555808849649728397034431942918737090287192074684397969160615097501093450526062348749716047540982999865470133852526863231060618640321538185317824641927005485150265217587086352116728376687604510515603483294181600456172618888432339146099425768705158380470637157832576323277284928646047567521081406198474115409463640446227576802694371647423060374942856799983622587085389238947075386687390290565358725485364568050137442963869535824980389724332159634426700176627992061065163846515064921588637410684477266390457332496558433051999120627107517974902352656943853253319707244671965084463686104378063445896877223550298897426021187810403218509932675854255394335301121997883305626588216509625648942814076872250411691340165493719790578398739957549774035663494254085556731186528909133544387468530521866839604755416222626589975520771925154021612650949204925509955141699012444074677285733807000810395247791161930608241648731914767070688762993997474241776713751349280081529785791522839884777253389157396957102347598629887099344484546315539930426501987862067783254207987149479904410526189637537633619798622638412781252622682665818932406995399135990579220223846219460903531306490234419608115301346148338083432033334040411838352651868681691521334776455923241601427442701071451510876513217324193965819202070046257213602391969027633717866958899845948528878627874580374118215424886584855606090166992321034519197733465237815682880928969494047220562733649523306448763660112510561648430552427437365672829237809552795093971412244986721859426695085967183262925086940181082305549114514696415549383148134698669859054350204775272429457346931907118404109889136252073537921875814155796614474170276473691038517193485831684491928159326927096146666271396720114843256662828177243418009825213995040913499687808097826489416268517585825671263284379666729999982007180215439557699511228979015011984694571222407623706460955223084363046547010707249195998397596767136003632575107033384841867944483002657439537402922598794911727353729702342534736680457108959068387357903996363250999349266609995937980675876491396940702235625713936016781153659680851704292649962838657171203346977433082192689684735185837475649986753949763118370925115742561033328919390037907657027229424324652297589010749789853048808639818934562049116512461717899464646965207910450781112796381795542860948452611181303491620438583150436995758012194556665427808275138157111856151510728338493075000821862451445227979528576101121774204851332151376938079874512161710115498552196317384497151425160286770196435563186327717698280207483610526653470865994575691133995174000123409870990455330131654713725686342178098332751419025146982543935242996357075212091377948514039723827106999995281805880149291878611458565765255037692347618510503670236364772856956127755043403111768830499869622529168498606132456083788583830102186242458189641418349970179348875774869911775098194650616420916869562719194616260583591232956801636876104964523865953603735271047960343847700399088877308188683691017771404022239055251513336386657014157642631620987573470183241481794560729969250925963020709132434826924895185343831648666817998278227131460037988833629787506228933017746507540062188876671241622393085201712538842965418261043657110992223140779466430111945184345590580180151818985125499059415182660632897868763588437374344985643967209377154135194528618063017803459001048432963104429375422951285123082917501627236029072954048110084361630340684105598782734919671503693141832484090252354337882156257276288481436402841444561480404704300946783680130920885429752502941096870169085391169847608044403779542736621951886827493316326839459303791664897256620078212390301202823791001783641469641441624649664628395829672095268293494487319163135242922283886966476400782750068442371999617319849368141756482801366965154261511250174314781828187606954010204932252552731351369688695488293205380577488144409753001323904261402918066555810803814194544275977499056084696644134454197712748842777571245561121240333391246986317080553405047547122444727491709874433197791763923272718056463090336850501743637692577701496794592320614556001218027992564301941179146982940617279051330734020590972516982208504515304745483512257500980906750360587618016836735361158407595082538865180306825788817766065856672954934312931317191140922749767313149880566648641024490744365925504999443588086080760683282770387372092481725755148209225610925677062856555715782577007103976138517803512504752413570302315514632349919928231907069720889086132093418230140785909282743950903927197337172065529496878966792173406639134037815539646157412790993348350426526283255557169280076289429673002163597034165838159498756927803528304632683597849815178217743649724569466792077874294045938003450155352930913993202457841957039967709285166528577585219498148129130301924429560567727074603413911795591009380611986498447346559878261874913129238017278055971134582400523925397032362661890341770209012741134130337758111991469003297663620177684996160440594382282228215982383459614428756827775159320283661143217015717482839291870381267578976986486554487510079164756398724446140192475219508038126584738117331510265341306763029891699120301345573335068504763679619038093743786649751794190182032073560452390973310827073363873486346008959130423942654115997769481093500450225292982477912289780616313411813403879943468012529923411929317798533000548187334843882651002203008021976865942741722900997784801400971281707757804893614658489211779792591182818619525453408183084034021650025376551923899979655823974006673205143499563082306470654339810808260105451648403425776270724445041040643701641158310656925660903560041684426981211066813354375164739386138557210063297705133017192309793582230916005686923322510816296813049133521320031262664512982763715545270524622693242277030601402208139823380113860507259015255701104413655224506467530292038396295354317517213600558925627968935998320848694795683759959192944290598080819641826669059221013623150735032994154036225408277084597809876506309190344654935646003287168189672793906041602109738720726432714512327341013462471989665875968732906183934853909279302202854064266232632031884827361123287079285333335660608318163954388025795723398242944626814077323521180484150441501864879726327371797684027788490552137201179244481451193800185462258594091291554996607703898810253964779359641733809959545046209453419526181247769575203979320249452196290980002072501266633660830911904856777506081271850888840093598167904321187753895812454273977272702164393358625067679295487860728915533915323890967510673463302849801698170765924360620839937057977765336980811777341107511341545663389146016911093461767179294843781978802272695592909051946056475166422694341844657693543663305962476976229952177999646913922533047662356904429176202269662451444763641647989236011865276914992771421522592453991062499966276694635522352782470208957502938719921049194641586641191180768127068422067406987987875901275883815742679249168130708632655665335177515175133798635940284070425853864392896337177742711776825996309318955845300459994264906168296584179183402884087578571308736671120763124084612359831832438853485604312452023463278843854054799847440890410224317917571000844482986427871354959190242216443979600149503307939091577281529680339736269298620465810935212088417355967812095120744015186561978645514620883983906454113173999245086016855976798426439917888522704110698378424603134156975461747662969121957133531346822884500485736594196271400261353120826054169695795647096382993069558741121766319924680893363324912466428024113200818287083323487445122336961773516790678805162231229411723809602042447575263550166077579652138888054928466521495660490244908231197146602778495569206738492223321519794508433111121920000, - 2066471036769251728774567494011096524852292761975242930798946920681941585071149832913187717042307553462660048499251838302056967272733840904499172201847880749086728382664799841353057029062349065705709716786863911168758130092247598725747182161089266576389105456404067712232479007943967748442685828793900223037248452564468312253989172436480026216103253752220362004267031058667289891083350667005569472433004069713770026633568348334948967791727037150190014549508513344696305634550897277809527983569433209672538228466165970433840533070975617542214886050768169899642794605011408792191495802596820555242673043281808240091225821304293203855159184388845170579557216310962325169189517846403642899618719546569723730900424046978355533489198351384414341544821056191932683241470158397532447434010661157234834890480992237786001378460492431054491013297116584232878458240067761850511034628344196102827198440589308542206489449568315109924471524156507531068526409037335664290489704468071464370329609121288383938277839536345457510466215598614258225997876349859001460848696552885437044338449067286606888014778321752583799783625149518171717216871666373418749788806183499681153452633544780966280786540026427967086373330300755556773223915302692068188418981424488191885900877236378759732639997409177921740210752155165003448035501411240652567442852125732748345655606072174314299102477655509169435458049161695531681598951467671026591739129049240093912956854554303924281549282479436796842145049765306515868242574649539840760652773714595891774370982342050131380255942572727238509987787287166211640008575602024902177704998742006275183709055137942018858897845706600490703560402893479601550081855220210034445679390088039753115049500937075866546459930056814485627043155395756966706071455927603877052873132538707893312459675341832225534971430572316634750331614147366492120346654798304508964351784022624203350919278969064941175599491670230800594057952710751870475855802521571721851664470156347321952859690933084280733603311136770628190661741030244740839758311784193536558706365788370301458995381912154704721851729128725052026351927372240498224199400474694284168834321941618237853923134442736919249557180137834531212043994936348532931389305827828666605827227231280359356654611577679067755771771518995508673476871205154660948206425970901218875313899758364107383094331601827069446522828449139430436357216126565551308182872350436406589721316427802767341669704400054108601567314541150206067796094852333835365639438578803846019542531518564707108631734767064278836211679564846954224050181222716168863235037144703473480078239870070248334933942813721025899150725449048758487279727514246775442043452894186304577607828664703809632493190785570510131822272720549745037431294134580952561412160138515322419024120712532039656173238061076679925453324734218900004701636940327000551069111909137429911970358657886907921586526224241472960947110566642675789145216683823886786044071386893305244678248814696451444928683580793039525026605134474197477636052727153963310044040884280780054259940010236704319600651760114967646284112353032455361728058651038033314031812763161600863641057190242680564929333534124666582728275499584141269082325508471766788288590908042755800163660554729244894885298230880244068540817646333978382068442425635799918155116352905473075457067617570736413008483031828432721817491413490534553006689007819819323447400378784273138012490842882184235834369262543353653266772297541033754021311358987717165719037785412621923244292927184234874199016911978476722756498402187873717646457255913587871734583720533371466703845805531954111263181447475884353944800419993677266777331593773538510168990924010880088331864191117228486631817755437780084276922267384867518055758797948273397597147898086570305404940270579987438215927252723809194963747441078534865177001439852316655308282444427630961892191677450101471897876001048971049276460211686222826177960195456924732928824367227999875420916212981184827546030421178452232812600764796276828740566012921858862998027942146387033923275523646205058348087433940940604000055653119187799495161587736845545889179121632352868803401947697410790023538384350186398886609003543607827934560607595925874706104851788628238358152663198844871035825119562367155998646014794601987845547798188665207190684270289347024632278817534447852722284717805675042650012010982703830427801375907911149123458774939251460310980647646192033819226482890931341731190402301655789044423727358023633105563451808650491047162366943785441168236774928116341974467644376611082228068823440537356521883023648747612984282473152466746522276765225537479201668782977764215022550616444897695264258492305832568001919370170303241881598982912182684377375050642621114029209365826237446503536190227653164330616212773543897864087594126334562639823832516616221192984847284931313888514555919200547111975081559332639533412236055513820600948358959406903689154162571141406006490660798215845291504476868009480084861647213763618002649961150682708092914631665231337773837716724601539183089925932529639011576252457975184410770266826287195546989860924806445013922465376348946029355906871855467811340632930229230274797496588033760555452884230739862926754131398961247506631753093805020511287572699115927278552519734626791909386656997091987661823083353536165189273191754109653680367376067306299097949177303104437954464498506669435715189018556890662140170935564705684536607715421900331477538619305007256163412539044574575235643532548707539115840796008135528393275429283366495621112263896233814119781497862447047089238362678331802860350930278957240251422214642539019825354975065520388117024273988595753673745587869615945796431805880966058869898378337701967972893626525079948856331143241272533091593280142235290196893765835183379079136941385962153139659401722008394650605978391661994266439394243809634703873470077713032402723590813161914045900597181530114292719459454664340015333097301802136298420436399874537577767899673843329473576174219725560773376407821404545912401371592068762297316632687900494717062913667059340448882158624401363945840847276860649036198910716309315439970148269791840513957378077046023033685900888429976441538853067604478777080911780372147210443823222866633428107253615987899753875052003363670717276773843512549377115166281910059076469671319682879817285923267241602426654273051996373764215810739768137513254191331391383394938748270849074711478126053380339128873197584898355305321690188987101470991811011657578618270606971017875549619541114275967155338941927700203501478729377492876783023125850800075082190021867105069086378758160548254842137382907426993901078677412365859243980854238419874227435357470496183683986298146241377264193189937907524989110015692179823141182326582489124800170858887903941180708959357992722269131331221721345282234809729446233097337259624371018963815645166048882753831185140524156145970836421714385416789387178692219183760689627433931346708334726593727107804801646552816030601017002260251674511374022121894124730293020038369678582433787681929713091230160434703236596350432145269123003920460382814175829242467167417972874503913076598643473456218185747190535689005401881005662304547282522737148453160927767167670260489234229387553241103789082274844176286320956909166504084805932462750862848079025288530024376514021914553598018591314969476406352015417376299829714297753769436592301711223845690354237925106293326917973834055352089849717208872395155584039747251840742808578394551950263810023983877863520673371532809265396794940231120343663372533063288123488136561336793009986219715868688400162979069003638101150093383811299460959074089292548459624793780430079749940357943482902782530638089929531190690113770207428602202484243749568392459756538708632731863138706042382337619468236754930139597555737744961623111323201615710091690435074910975567269501022568720684748331029012174300647977374979635945212025951625431702014066615898809737577477284485091912111496943526708593071861997445299603091593527551368374039322657820554070826424381070165328629419864344646758709568471031692588233749210483340448259440526260838107737689281614687847291941047650039323240530283100627839194550842104115540597923457870532178724393194533291871231893743948749418503433189722759076062902807070655640563496104935007530359797826120346198145664978413568242509362545413132431519398115795788605137741469095176593474682643976510977812954833110782988071273638273322867496924656907427349953552698226733360593701752216257259262561791078898605673687071486571587806216604347810144142878081684908676659183213635347931572626952491084861116812527491875072481295059116092226578293616046424985796112446523581410948793551454746623931338555615924835349784967054066183524554743103512640949954785289807376483914856708867233262635316659630398687975622398674769440648395590903547601096366659533283506150100242588859879501951105728155773590258659967731267102341535774854348800000, - 3370981592690649947210995905917401347423140131432407270627671648501319963936648497636121318896162394174197300732910799995698318451191512914599043617333001161772240259094898331210860045143206998362793398306705885257825997463428858737195807974139814775682555559353311192184241050324032489820604030218085882610058762284624162356682431803511026283838310148310742701268352696275709746578752045001233569585486110273589088278719322975793644450001810224043166349990738121958769196930105607200206380457794502325753560529123632296835613943728202749420943838201672912466025096472250642723461770216628161591457651014691663325792144402166685106235525873979271156895992745859995050770445242679933210572526461550640950438401163300568727225181630658799760913308200745718905152426700689527685782341709953961203935569698953620625336556853947154301909973252150245689729467589934436540411928075417592324831260870137808936942706330735757172068632047708196341035788909036972225360554397012946858823459436924027784729327097059064006436340974041113671159639004321445632893621291324305249012775354715244123043255587334760466504919567308852980396990562062988371113325056489204775271109574550643252426826787810108337144343146322436342388192612726166720934139949177884759566196014803630215046513760751360491731713572139246500599375293486547925841532484740086901005111906228717855703860102750164810995156325784966691281948602784810882230462421204406880537452668832638909382368090082209539017192903797836894123467474241567937187352071469406450372263936319937500349329161118563002780483514836604883889583335814607974385091281471007127056935549385714561172633031223510765769509766759446062288898414228387418120413241692669474434875264630333208335275830369582157371490258033688973825483224782668228937636297188833549924980162880469513686164748121818785692925562301434789650805138008813871767667672234673545087562420107527854547663821555945001167660451035993124774041902040828357551743352632625089484921777640279115000098878782182459877991053558676762256585508848630864174400449385539032503579775145572039979803591655594492969950982030409979184488853851935139277132046093966719507385475326545049896321500608076562531704350127154222242354050177724604098385625282671922332135191450310923009140130198968251334012691666105938468709339193832611408785223472306528566072693545742878317051248389272582154204585326958166396810781034320101429244067461158907453086813774359544658145372323682686888193076670155713023782451117749396570604837633228702156155547228335961394623608729498743566125228901176416167535800373830115097756667078634311407157545784747858218514831584576042684823355844058464723735824986375279448769961489341879382402585818666720999561030775496022374816420076289314500915784563274903911765806416958902973917940558145659845620520846834844481828267325901663921160161883185935917295247952910015838410679123565392968920918442146292353663242435057676359220142776373529189581287467044377175113327021905437336178417085551462457390739360850369579375608054399682630515083421785403127466679312893233757257712859295786991371819553832273674810283370129887387486746582296930205449177272781304284082200935782472945299023283939805249088271142756897610958247049506347152283823811223055891651570580438351578292946945900059748091061472684302166401139467031041716376479850037302370444474152253575288273161389357430326859269651049594179533438736052937416221005082326296404801722928264713492128691818596933904255127798257172989544342982687949933965588008861106083635807845290729614656538659818586352123980038576456533438962998308184620125796575015611826488121955088138881148526243687159921512105574845198560898560057644843668648355271198029395266969670480580821607812102744625485895800479484683301845859630989832458660695012947374117337611330790832636728610593102203692764933157651448379888506096705694576913931201806203219163458518371992666643810192475738716263458314636042841747339428680873304063442300249654902847599102420365535704710177072481976245742978633806963863931957243258434513088040352352144822593206475981377442402358882730108244945253452739153498425345953342930015349200670876644621303004250640429750317474940503298719545923892883768262567579089610643475749357944233323155519638107904747525273766863609057904304110387683052495767640894860020311239822685440737253784387306695870870587405887020130909052921738838073235472197936011382233608048446584201704602585599135971926856175073136036363524563707613057832962084886610119684638028807257659275302053096423226333729891750793689165884834716526084127794617018688816472773487637147035073018968116147995388279123526954658759233160943393109195554081217442505673304423367634900363753262309568128381179081946896448543039010291678929488466289642276616418937006639381099364393849665428515740080550389315168151943366289599543737973562401974716076233213835025603783165035124916613860885899065779867841855338071172905488525155067539003578555516937282413217662807702277485683816056868671196028619551998999163200344757775501622496407775033765935635225275017818043361088968040902649099810102189608808199375286406460991297315703279506635866152420894589892201850734955440360916014492271027072519470346173332027656856052490309277786056546584220402528256562702123102469380511290095149744446291148190979737076705441998907815155692187946268516332947320218339579649477514784130542314613729940814499937286815943079977363439474528048234154572093101621183089494189950829299272047152866528285424791649251731022923121918399529421548808777965778644585115012641315890707021107228770638538755558091261403918491547845736971077598081687132832083438692246022703317640877142478193697423609423656158298989810437615240636625659262502081180009633962253882407325043772651968693316463982543253298158414960226960356480969935461818978602036917001456267356096925278239602900037775194239443187308416848574380838009487853048627961630945781971241719416262988816414057724143929740787713135193282159653654607329161507074099984087498107803668008899517632932447504796003787638811029654082979419914363553490438994295434600879087458117848341046517812677663149707285550114568259277933772462444185248627979433600680667909134049077728758555570269231638287894420602026050044688504079357762273462290183527751149945653488270075089852987845983944940268204375787182095470442836419412345718963178191866827117714005509218186983304551348018888742807508327126410003073846885887450434675708358503861624918343435873878036724067496335489132076193365372907253446949741709554229239738272885177989879054562353983613530763853486994897481327939214015136253527902702113346040773242776693993424646416954328434256372675066228826720535639708818541145635193866317203366547288304456843577605591016179788421479337977967104962644938949021108783301791810481597807074164824931375615530646150570488305986914021749540391063600229994455774430148733836689041091803541002903635699478959853336130751349631488744033596960845230592582320655823418112185736721535719218132480951552024290667473342239050717049393247097252154882102807230025145627285253628618197912323976670129285484941892931170226919543611382273536263853641341299614851703825959371834627055298315618273008836186037260598187588840121367963694458513884850915193736378307822102965343890302146839333463579883983076403433408477646775085095342386258436029275588930996065860604343095863791473606244972546247749000479298381479352807954365195717559483054938189632734572421746945742872950401117165665114538474056138607198051847368159324133459939737105897687936057668186673195702684175342559603636444998171951213181318983535813698008701633106431965109617554704042662579782949444558625381751924308902007060658184114119288036215973584224035314969589941694246659135978323234966241955122691300012093689533125990892240092303963834915308141524481730420190032117737701097437030086067692795889037944287685929668617983012590410276179995200260477557267894269101000845339939440774343639606755331669418781784823863320608291892531900102217565231039276495117276734126574958751090008022474854231304405644292969256608482496727564122878270421689190564908540242115621492708397813106089094421136280284373710780538555974592532153910334246154777565365539525836852965392038812142788740300694017679268319130954942929035102168594709994329303139397797590431942155485509461101366370543058502759941706004181858391395273606145475729200167895076063620557067325283624860718431328544771130738668050095179658312871675506664887549283644604163106894766236463212916313717427216674251115355440571315133900650547890528210213941372055764717142014976432274571189248661163423859484569319960902875539070093081293206616138447699746191282355664080500864775894309349714282303338054780789167216758603901805414740955497022680207921902892776963020374080728105522267697719106339138132639760223513160479765725545979108193730560000, - -3246302047918681310165137007350622550958919816716544344588317412793197533524235673828789883909582717873191067503563095689364767281170564763634769828023544783053147501964842887940087160933677412535430503996108245116209163592357672521730853249677860342017643154263355081232097353810917225650146161963671806846654869136505637641207107611265114486290291303104344306588304250931583987925213848004835967448099833132904141575588148452163735189869184910050394903185305616882164215253744614967435276610035904517311023490081361915716042650923331011967588554209491767965557446245378850408555407942508453930505899112052691022460483702281809650230034184507922364535298024162496247173744299627439891978784464753554011033779613249232530608124254876401557002090520382043019440272095498984205557377048121724282475014346997362312733972845406155443192317504498191916099637762478449641314625849666494907305491111915290128055326835158553784858304991772615352041703154882254526413488291037694992944869665239978456863637309351527271061449067204914780122469875506456281285147213466461801979362891650919805958448775674796851642202669974512814319757066650975401549193867749209099514762720244039926695270887283916081797662997895710409013364046218886772355524800645511961900779654567607339329861819685957234760294058328449941231841711468087629974709018499360746789957377207488028578754672897163395179413622800421318944960470096725516252403215255613475456787771921973301081109448280581762393769071835199118179640298610926207120414845796183149149174911651362968344531714404734611608239574568315310852530061881779449197000689174732029076023608594814022730857507443008239367630019965373348033372209102934027222373154538380807012126037787681996601929257596697330348919534279056236351801553400589722997201554666717561550090764486860595592435336246078223537084197580451624212426010272833857818014410901621824277634841904464402494404679698050157489835476619155559690727007950734712647126131861104931308296019742531526912029295094509126528739328652381148683745624904390805727582409708162978119190640325387915870375632148350196284125011426520527214441030289250725782723762101185469159790085314864132882953213647624435519300523296091603071723388137715718275098880652852118790587015149231623531069138274575890771458008133480048970768273976808055868599863581251065330648801479727049840628520267003503497938618588939181747851282343171088172879286123314903412678215802185429139592338408779722779329212223562338084281794132532360568353371743324372431929339764912354784784962175962401672936526090992177444345473988239018875853345883670367236481473192657168917383111266935257703520309376756057255830631133604335651149734416756696467129838002738708124981402276125076525997708422990517459222197745017269210889727875043678243918866188230029249283832192899300962809671035795343203089129162835767341896186058618850468502505811424245166935893942821263605140120671655599386104901545791047329136860987556771916796587206821677016675353604686974577747402496027266246131971198709352795394702587803810435843793011979627758474219595865207121394390187646169292463183447319449191965626077807162379112137766968402300480693625736312209330166911862542739498375398956599134518578955335264392965245922589795171325301582317518945532385804564602721214434969555200257055202801697853223641545219352532543081594867551033882660265705125144823061565723356305917487820972925638282464509557652283284268335377846005395680536137367683466252811211281942485934034607156525783846740834689615010281030682554193303748796514724492815871283206443451971651830117109648917855881271497164327838788888318000106637033426381575396338154033741133487375667222333907986299472242547941628265674449604598237619550437065552589181174377649512305270148543813489721503188093932444811730282772138572911581598194796891027924644474714867853367079227619482846283786308429003841076316019836336495827937009153868616383570189254917914006147108668527833976485886630375332679000941449254001220157997226314782507570707472032951447290204936365014524313385105934549233084536980317575466861470667270333897839018945036426998425320726414751424244262646759442441026808827690829150462077978590594221953320598246289804178222236063597514630151666580393376320173045431388375892556693443456162733251456315975267537901582808335512943401981140820290612291451202138795545713630672448315424702958444419188207656885965246572169903099765527657625292274781095098490729879050981734277743272501177627213740666826831376933205015230480531867052067813138168122716024360748064530388692209436699522678867339511097541073607295556750972108365051345520774090565496042880265514348579736487965248867741826327968492644382130379314222255479448207706007140766263809524541391146185648444942617846417462062249060280992051130655635527249772824021206248720352514274572902498659333748073951811563567499130169913924749549873353108081234390455743809643809837655490235036360245262124936181243746024740712285337538455259949077160385728801715387854620292180404888845364162638111093847427984109280397479889983092162009992887465774762547416452681002476492347893259202657400631942906118537405674018341326680791050749823013266912877205839650376404363851418456589212123495559708654408986964004390076460585814723438462211384137508740548090389759440320437871886102943537978555312639104822819361968166669284924669579917144519246134367474543289558912873445922105053617063173296656490950651808036853257319403131637055994687850424466739763284340645002514034422893148359413844416043986155543824105783490671087314312896377542228766569442030547421067067946182480526008804488650348446075267468116067714840970303366429258110911816558545015418379686178664376565076071527426835974710871929687972770307738337850215745226889021896471389477648639966175837220445850746378496875331246537719829044851491812545992765769457224705322556010053139646417355422956355410091917507941987189793575094590572122161039348705193402616535632063747921842688003184690395523306753633758377712679599143940090668726380005530028884249175009817830373056868816589055655589030242352313940002486823561923515238720292224356666615698593717166531667422124452715014635285841238835461503624297939889597975869747546701972155281343810835122994300851344476573868899946919325335487721685277514358446472121641711811040548692875230686921557853106242577583540875093038398118553289341163300125414086625636748712149790728210057598457822196628307030050475569633599810364679829060943919206345347855619953252121297354052871968643916708689947944101299719916698552543766948756959292877564217222672092120636784707437767054981427120949543905419225037078344421526492079657735309846346597875737026930691126318384270375684645282687851771426366145432687202823102905856025756890768148436105467489560624524949100889907883970741702826418148073101940646880024754164677553763675480214794505517064867989567606820216240297144867788674262836466952344300555348526964035033136754206849814428385943857643731796725787854203314375305780806702693797963840168979482307518208800804198379867721572292624810135380525275194787548978575584350062436287217508284837023248758330992947880290128259498912287596435668376593352107971321017845163173219294885469196450616462761654715401789897424149723237261961302953624857526591322098343610295402046944864771881811591619360247479860632867590091408195326835397441229928593335833899545144891692609672020953882177165838310199309183334080610842576699620720188717771289149341056793420510009509242908538602444239422116108832038286058020680773647850514271076008652558120986746591043517247471775844141811431528182880075764248390098812600098879463963344779936513252020770662867726981660576452008701114055879185542390177379999525465690082265681071592839670660829250603974177761481107576286551487420366082936490115487087124336948237090445978520024457717042040327952018241963225165665949593245040096337569400324851168113746109446919965442003572212788976467663622137158884508643193694973686243428599093468746936686094385749334785866296617226328716703363232702297786453657856977396016285406840183065853366883992435337409037208207182892795810197503729718931595784287930302728527619085437416023196243664430270974021423188534028861077966148150915255935232528855407732591760760423246728760100461628561211102266021385962660835662260802712493996837562870095983545239760829528538278646582060782055483339924593213221324238825602065614171508383024003924659600487835815227148762996728386442211768555497007209179105189293427491742888977106156847645812432949612008782650433559991304842783006113389987489345041547701304622552816784445667151574133213353365840868425835763543424323253599600420932115693336137791775510070763126576270095123533785642743293599461700643597858233527463678165970291396145916904209049832047813477524200138801963924101732678412523274240000, - -233653204706999045680434117029199140938076340759626094566235374864279795840448154364621043697918244684292312531484117390594694881519234459583916055018567219829231128353112156994651782687794045769219517933561838647236655807579323714718133025093117117699025627254706056472351136641967527422382538418064889321521434859124985747028817772729967518830592512593721648863161090289255288662992556048974545928971267258285997623907412659342317641426614854605949444581267665941063437990057817117448246043725548613896739147435099517907010589033243767650628028848619889794065241276369201640163341320201376800449436007007847123070516543218220765428362312756951167006823467637238443080586705356868255965994744084608490736287200938848670015542262894491502008078742175441852726717001238776967634800389874137534188174220566580330355370222954659898871299871531485584502458602975863060477681431181897088452586458748321980035897515735155422646398660221556327744490590558045800867446385234105474351985340335934048915741266592095369378715293908287727039573726386040103049247510558288478665424837618176932591407492322904028753273229460577987206492638358646789889123179225292435475517647311814009080308169533291577750468087327684559099565682010392660516581736799589427386934795413267673587000409678291253615609051617581227437237927669967751404581481650748134677873322639308325056154950183277456293332525422579335715281967249011795841396297874319884795812935590024156922018661720579959011873151502392003101815232329526777299217191149091263635835721876636260483859919474172139681740541257561730635259506975846156400437044622050927214582459087758767597859467881152244415439848419141244485856380179511840841417650582870050087885870545841534380907141881308729647423276870382232912696457229688844682407198078057783859038612247189763107255330791445961099452262196045209734256358356975521968475254901612697475960062916219980144715476235776616981478651357354110768644155102756627955054088691108886301385419805424505074757175002354161098195446265394414962974373917761041900369846484004317977997339944457413972350478222571233323520276894695934349619484589203514613438793927469681048420325127407251294778261549922409748352246427609885272216427950289366147288635623524427100638323118011998956641259551256258995233243114581629269036197413711137412773295186396437421444005928175106257313295467908108158995658041212060948597994436830060269281473669839154515781969528374054743900732204839258957558220599721057824819110640465486022819263207322565653154539184300711952311738221155636035051888242977967466690809949732784105532165097368476596332772803972153995559075298032390834422850479230050756984713559891014352233530815706783744409692885066136419507454357167396134054332822972928789060067824324151517174352486632610083069711104340351352921813116385336891240496423044729994247599821163413463930795508936350853359823931512939145655119049352898382802235958864459762373901147367796614419594560200969935322955038720552013792162919254713395799812441743005810163023064546667794911577336300183757770406228540762242295280104979059701937727998116157015747072918733116956087600552198785400292135523744664023973872760186314405048353047359625901543723888628687552987590748359838821317237088143740664719468675872040125851030078139443601463629245027173053768922404786053615054753702834116668225708847201899272375784695782406074944181423044383839711597750070015453708960479435781411639048847000958468538015462535863381545362361794502709950094859395980808880543944268230059258365222781307253957636634376291658048185971744781382849791930351395288143339676751728996949135185341331057407352234747300421195296422981530983362926283130224920923574538353103841347657446565058479602290101982778878073181116745109277992623997266911564243651050523631470305256250878032027920215640776591083716717820528400213941729885409817971895368558703760731622638058560562685578586857113177345292995909745658832005017340540237753300016696370928645507532399921899407702436116797413800059599022024145384191881957032041990216744473305920150517067826139140759392378707210741968798297834663907466628298227225530454225509274378136324276629428768063336292444410350871412139353080722865426149586420259262622905013374448070137582059269828466906911077784832585773477299186416292462792675171187606190058170359290741399469237933041760072699244106751203765501253450277638491984457117548917545811139659124476588455525421714325803069527803607010428498639244602074771554548248230001836669831651022160624632704988740039901445079497810985190711888624051598255547629564755117483605236758179521477105888058646520326459464333388117233716524012330344163064644181532821820346899257014613002702345496824120541459999641125948735249332566260578431370934173590469527607445178565048572005883944502185730297583379135474522744102258025403348711857708874338263313617888030473328089019836953120136133933147669194479389668721632652140080010063659876653653142323317232401260627951937594304147893889636074599501668696252690465736754643532113037461245650617762209355186980517002997045617637078448068730840733858644115710603117395560582233261489563467556191081458932459430897422224393053089703499887432208253911810266240114355193960601809807031597972800447206288405340157274954220114398559605114186778533524082516066403808934388157816140252123901491637874153002640226403313876649927187749874077012194305558337114930489451164788753966527666798539449650654210041493786600434861849907724095258379993811524227976605762732465111837915618247350450530931599891829469937882483910520472622708868632005653132160510461047430320578230478517265535239830614910214112028736350946575837045726038487946912691326446703438685859952799349543863150011376372246499189660378481440585650170845860181439762192245308905112563249524570304242552623733015088396142464379670541742381024929437218282302619826404520692523031924639448927667399863632893727002679915196482305319820915641293264130078843073874895402640046235365808064214248802363163328070826006657343127070558205170461098800402701808967076746839266672510119283137308628966512337615829122137436470213335939858389585862401967631908476780490036333386924604384542865279028385717617769876001531471511755178346245670186665713065436657164141106171006653531405800723984129874544443189801235632180411417635099719049358030578056268576369617951978190867818669925326940556434506651704272461357367859782843128161303285634670335339159736643434734104182678440119471987670874308782813421489898788084331365959336433156125138168072431369221824237796579433646480302386189075844341208564518173070752348880124696415645022106972630889131571918138112658949595138231432979321600713034259371945475286572641294617586589112947754023925526224289391221400503990663061413692030731175976415001751684339508564275756457385136021529157038045113567220189207408904792155219636839689107860332172145105616683704759484739719843711986949122343800952416526871329538012487025080282794442892540017846365491191371885079021222172900148170667281476285787343499349464094793731095100640425854688800148116583754514125594275171345446894291965784731829016534725396200837163290048343274105255248569258545894428932308044082086989288515102653933186304966019320314100213148425194123190517165296928141963692445721551859047128555027918846409079829308353589277119527551679765993555332264101605602344810303033597015487962260546913116814797303143346272910825912490061686790103888164952664624158987131528635477120864280121339496615334063222827307095601295156357305757215501732502013373360222397910708094335727076291039040093828714245497473230077762969672251759602092971733698112524644109740512414294508815947895071186436470127351372163652751283345795451047024079574496078916228918786293133293483446692934910992101989374859080629190613892995013625362321055981469058862780052464132584191881463315876383526033638700617750691582016685641392789249908532204733169851753687140385549128039306968892123784944040988485899002710909672799009692697291455017826595862801777094610716002299051382302195554271323352617336905811401106076924538140697147973110424398115673338241428398471891950275303841862762683289978533748795006218379100203037715801625305215412490699073663789754249901435121315579810025331040150756855165876788514779267421832178401857849467519957373092782598234175712005415139621032895786177700351906628759101621234113459426559924119391820507576132051976149936082389438423782720351867179365275667394555249600650541930143782447216367984226700974443469925957851487103318693112329039180534497435865406877310111314064696244926415835945964099893088665534217693399265114205895817583732150469147679204400929507525608141661970978003911561647736033907666728209719361995533272517875865791097296625125701761150279291438552817115486227401017896304108839059115212800000, - -10831247932816383401100211492741099637740273686696116064500656110230437200368533086750940587252092660645152041939526222569318711042251202503397973976941706127299738525398840327098832492730122486199084741241841164824290637257826017945070999069917886482459793986354907733859760765477156771267514020201593673208727058540024804621075103474912883070034625604811405063256068846628597205705799419403878770268130278214323418630945030973159898671053928170056654364306395763633376735538090582877326386809450403187911021862237173412787210950905501425308515687939583255892502852341474393988335380090200700330686261057317189412763040691047544858723194126088123132612179844868139294429343042417141048828171354723178379632135080515398578029988108900161050280642736862433951383660340913756241134873796035491020689062515272062114551415182235010340102208981025351535939973791232521230490673702162476049157363453508905822013919174729418135158075335278419564403446152135849275131351933840895879579965037338549346358058902862927610724030106196457689150415542783200034494596828772471416697611900504194485503688814829258346386048310085176859815070568432604644559562377280178265436632818532660868413883356340207552474305427082288259803696372115627764397995428778978429672057936278068575037945534361579710199181006651386019267834514925063463070116475937762360052389375666947164061034209763063282235902893536034673152558207440934771489028571130607437883116787117885817988316751964455583089954846299761232882619936410570938572745856282714895991358987529348813855440364019078568165570889352589308814751224115893652324346569929845250131591307599926131920983189724329881585758202544318216362525422331959522150309422066774694079258347494827021266609248134352225427169120952218647204759245156816915582046488135261106673770070388944004389587686254294755311885447251402601233003254514738038772257487007002770909736780941781158071069375429791914220095801042690562361913294000629301610222082404909384913060553314160439735507737972665904546742357024530319449475049001791551552540176046051526055984362345143194259301640777500384939074574957678396433798142209301663149567942200254943949269749586699636578200019080680637894832234651025527242618307751195724706666267623205325032485845099625487475499531870347934457710203221893096931492051688874878325067847330682866963929748154315097155759183382799105940937497273719985286157163009970338503916167056870763812232660922659092402866122719924625170865317929389674651477489081796589054024871659145047952475128865124010575336438082234755339154509118188088301937105003069269128081517193423092461303798176147142361675769197536307038197202071509861751211559186807907686773377565998895905841723826579665096747470111899519061892672503658271314893411696494164600658773656066949684549341942390379422699105894845065850081077415358832931344935535384307236848599513674152380489870585772433997650704087635046541091384978071322298397480929647764092452789423975645582235890951106982352751294011228870969802788550660664651325572993179400391496792821636369192277414090954208768653303326108852174635047296996652057518965367900326010935924508774103526274324966716780193133018988102597998494835144387485842530997793150944999712162126876789164179568297494551265359907883462973275306796997512453985831606347949828009460906091558999302686363441924747616245842868557015195032856055942573641150359505249823405827129452937891431269287006310256766137248175343153558924685096361904752677637632849808925598673629922918609857696236568981895613681078147761417945027653014667881683956628634362683631191319520465049042630746993760694854539592277584230246015960578361356602890287428358969148386891484346582040481655221603524100272268235486568949622968998201649679273621749144000116284310243815298979123360602918530626917515938131978137730790275179283115275515001253009028270663159485876411813339696500147671077103621141758596683705394658715705277423875289003012681904849647265523881189060855366465873616768805852469647038664502431336614488939918427273514973592980209322335066363656950824919590536302920367600519274418341958032569056167688868346415701417692799503347917763438769373194197793652020557416203779202892463018262230833484574928136979407189184504860512359095780929178669610236871686580388702191667464299647913724677619988361259667870221320195833434837758415610566004213464826609113282494384021844104936044163079190886935669302043225622673205515743763515117013913556152571485378127888686613120652040090342399228121534937169658275756785966815305669769992046837932916285489803692674875635494643341685667182172147054508829419868276345839438548793663419980191332673422414948175516813277995173252110376793837672597999233257293038040213604314007066550075442351288493536423721336796389790053167964134797088495031784435150590938698318284679070393544362150650528495787947770903421644147555016974387842014946007444493528599809973621133197322305702006944271255469261922694072804159882281148766428623412754049689208176388515704926720398615780921094489967872620624594167626151606939647702939302638109644733756176609011336846173021107228676599599752776840904254199377119477512028900600786108837487455683799300953842194484709911530555709712113477992412990302807914377368353037722857920804987506231184940716529401386172277928703414389859413632381757350862228008366517368743692397673302235284468832892500169855569268021639738917041123571359051955756180643318644602703255210982736071347440971717525337100723284397355779336548561964060479435524947398184512605904711407565262649053835947750367100605478920179148280942840712593931437069422139908657252038004793672050430565255213325007545253985318592957537805162586756455186975955902829144646463924365777184355416144415820421196570400699461591559454807914666839531009683016667102379518544935579129177454059733840615947600389841560609800973615936676248454648795905338498274346726169104790580777159043950995700523621932685446380724007699469282502435265714816217361834588002784832208714150840331266181954015151121525055789207128232329136479450097552095347784641543177553583199466360758909904068041038241766834421828592615437326239588412035546005523934856344376064494208410049640736766284695301661326606104678736054800352707917042184705806306664938573170463542922710954093621786558943895805618037071867513701817672808249013239957086336571966554814269746600670764989913796811742200083770439709579074920927763448667172944202512723633597306623680036341070434493778238597011327847539234351202122055889245114647518445688918572891580588212350731480037392462030218752722516843109831972492374227138010450070308058146440551245345711227360272298371928201600626764734681550240593239697773423206146294208272547035180607835891036677179777549886252000578968296166253043936646085233939525417078180551110154231926609713898803905044415523203095018060065692788738212223221554199780851330767873066124052904545162316009781058267803237840466259162317365257726380101896633835437385245930976301051992182483337426908914131324852347589057411545782067621388120299883418590998624341422169159915136419627218998375147659506432567171720587859668182035277781019276468923646404635846203038810160270473457071438420923032552797256201604926563734125638229663698231736280557679089348341405562156906910230629789650244115467913391228196775757809008462710484791530476149003616965339024585773590291836898337839548043502092809690224984835862855520469865024650304501275871692289915014652252989563283453738534103127790089926166130865947232269361981123293498158156676953099169123095101590783504869518577645254690270268733605567357771806820583438951577568005372049743292506611293233102057371869195276558239580197265374867265859830923769774662379490843047799822721556026844355602508260484385149584437457532516650554975886005470208755153461652539256862186171595782072216261953388258251869535244815939565157121219499653937013243209935278787076142398062746448070308849313862887708584861648562035985183632968855396292324429180227118156826788910914422561279841070282693777812355677949072019305030915166142108297627797932216071527979374511062438919417340245131036791514945355200414267264323801876222964139566355045525070544780069943472216895902175241962707559880372740535376746212381579844145147269782511335913097492016972010563429990613725456546025093691184921302677734071400983191904275795928356417966348016261906779732931837176928935876941881592783341355109118691919070069397240176552559390944129748491575117921743584169826208014326719082452539570061425038078414829289999169804890011760928210815909444748840849193512086832196779641167549309367411753161480433879969083427284834347169644631590028699141047068579818048963654069967340157075310317394160286454355565763733756199304578639167740868076991293173665401415925760000, - -363355104494893222617353664137037659599062024113343373576819902589044639875055461411411377505066378928236056473206179606420280828184159448872239479593847299793103371194325579710881300479627943172028267912505503344891038010816463887303598429033431249461934370202661816014932055248978225798267173013214868067314400776805128142678947346623311648042778708659450615560629173544831559054516189174961608396337195749810085887849547001383459331917800600918630775386398958014054479079439925841861907563252036736975229127688476850358131065140849773503573536048171836860046652908501858832572929307979030108690865316230724607808680685663877361602534219722216823772923832880723121924449488250789243082593922992069823307060342711803317379682197950892958094590381783066693752082853046067590310957496786752241775066505316194983927270196891983271055408733422928260879730869842343116739471684115067479579194647666885370363518596485617727284190641724049641026585942677601894357539843727708482965586701107007070251576026477235527373390192245296503333376007311792122460179554006019170042400576238221551307871851408884950754850159060462187835755774052885163737471060196128602738954944230235431987881141167765240615672353740038933984320349702441253303904182333490022003244746032649158684050355962039561331186998113236909757907376315724050666177833228495742733025936808452948169516871995164563626838778054158710803735415182522364476638799646225051736472179508787454377384148214049138264477187596486215177964865520750982269424726094809070928230816461731821364787979265965267830950349085214764394605685006184914330039525288605505889977926415308151987417898957817701188655480937920170320131692222559372478116351587793007954043100317041599759981450567360269362042607756803056185925306115262332477820705030173059634433204472531821436278094440940548269957383567969793920400643701292696320918910958973366405953247969886146159965911178000232221634353823899219886166273741939807575735279894575067141643015219030682765843631492850961832316587067160590106862353078817878672462157614683568638692756251225556592806708998331922321098554459621590209116868602589410776084350997258901415033932515807608286403625067333613331610670346455495337692229287223741933599161542211951893171189977026905670773586725520171057526684209617515860627625985465725016142890004684742701515622239759314716275723766439651911916630337251284778428071002111885397482813249467067179349130819831997159986369944661072978302854784576752764716707955955682223222569812790390503406037105597511950546945560916987766551586032809134632082180001518430529424273566845421557549163863124160068522376350199398532434858520857437970973906765770886798020514399584627473853580393166042059420412726985084739556484680520620410103233336432267204851856706477617509317428861887229884010050576674573398240151970081725230076557521439418761772980741306365338787635486840086870779472296749092733159472300210149012408194504990441194852852368960267599442802104453492470191594661193663825036550640188506852587942092329265099895317168755201638056462132259767487091023719893958092937929974441296738398251902436571795301646089830985853100876437387105384461852196384227800913873213267389082348956061258576007393378399907719715110728283174432052673507568989691016629034038773905360949975724675666966972014588905855722547147949278010795409990354647932274348745228834968365547217169339606879492435616989351240857779259299495221408516220249647232319030876141349904843728925102638396851196761742715834520472754830433778332446509672530093364182836053118273047924153235759946025277387058265030965913333331221544668050727773045887510055354575186404134881236700557779429253805133089137844447237097325098376186555560686601976518709655893356292047524912142682032271729200153662103427575737268179540679374164055345031599082899726493737949980860443300566186590790308020735033019389270526068031038022391282748082926838180353349273658127709921665031448415128156562958295993138681539984933459513938568721858133934802817429922816984639225978000489920495907689702264413491309492086175236109706943421176075086160192291335408919462638944316210272965796441885735139599773987082704399041716000788598676045110918043355425910619667548232821279272785809566155986034773968557818151855567097086455742022129452808934036324166405429312028685594793040086896323174859963589843065312005682387843232966976180441752474451400697194424975384190183287519059254617329532827737448489688915732196783478341521662268821361665081667505395891972745638642577313331826680823378200867092323795110153899648984263858497090195479829939618798940923734909145923756549714317488620343380807214655366886355232384749334402126517567336320846915041720999813557244888936255384342879198477747815193397607333153188817246486427810378425428928306316227155259758686286264778588993841300974045133580684851232655150125278296856841527345892046673240390553564653956403104468135878746610289779259536710628609377814040878171665784051608672750677001737219638373553334048560712240847500423026012541796949782604039407992533619708545463702899425649949127485451749138642183418721479029245557703698867795478785459403167888831353631369333161929943962666941137917906968091639301357397493108126071132150555772600748876063061228425536682985186335064157761907771276330276475936906805296649712145430225770618654809358069735026563967253064633364165221545033081868615963345853630467040038927403660854049871637339546481917524559128213527244106009949349235117925091282550095577569683949052224195977353944241870666668681631858644067454171134989704395101638227147481002708166859075410441883519998343515058308995442865996074590259611235584564203435631529634107895142729124158241248372077053607424637888488049994262791813947368874748419464206571762206737490253665234479806858731623811530127038402159611570572191719023237907190399646784063613879992904483990417008461270994315145370497543021729430599756754123788664410660112820458189885701066971407795780257147352969224456850738805672362814383121579311562295974197835936904814615301490990493318496115882895522447337965323214387643007417536032382217709273465767492137132416014433560066428124577743720596859843329506928194394827846850235656820259214852839051715891447800328166840971613150041284243767842912084537362166432946300412044347913972788341147671676753386329265801893192853035839593394850608613606437385922169291819927426129301766146096865977470196836516353291749940947337634687662258372268135271303449516492643508033914377903454167059592108684421501454992033891605274063394884387646854344184168328670389455504125206555467364301302838665449127582472805570614888076819427604358231300153356694206322909643245116090745876090692196526210336154271187111637447951443210456815319166906268783613373087684757224938978561346021102251046186181900336858130090919084976757015536334840856289462871647883686422283905466218446222587081267067332107216781223600101852510885416508660178784254361447618242259690889838793836421084557865147303020393689476478081724658637299774167560839508492646155386075731479183264032856813261169631052895684822727201405284577380582066343636576499102893941684555181957698189241487748107301389431697678691683997443563516537055634265269899991800156171817220680098763820234965822472906537633623164106440881211526167074740034092834996655238647490113783991530628588838300596460069410856751526841421888085396868720821094561145098583358343822337034640337014747322353602847181831482100358494565468449812212440216999161393502844489461362999498589914009731147023326095319380325194809784749856217845630222293815042575436023949922600011638784209184638560977348908713209727903078096488715424510442626347036002682914726770737327367728354836566530527306908198638283119575210396831431302667468917979163158169224694393838091307766429990861785049142765823165861675251735489074577515556919023029724981637618579307031941324803942226879052695766532200108202982364613876739980400462218350767935960409123703401734101437094126583156005408022633416776826928644182446648984274334911049369804407814803749137727664808497946521846776562142397258648885650119956903674055758761659255432470694055549766937988233189591553747789134609769660947108585449127499457822828143870691370543349701058922937003630601327956889641794648503055214306065511480766598697100978847644374130366820837890214789163482125844282206480953680513941606626032504490611112642506957465545483695214933709575395858721064460848980698225084673858258742466542891419447796547228502961731539175872269803948810914475265250543266341336762636902405214334725723461925056644155795889862739545343879138670287288801985505842390114571364220747724203007682803853061751840878488509058320754007673471423562776475725964733750032821798212934807060480000, - -7602694181285999725187732214269511148086240158827529100554305376519170214351526274686432773313490674005424244048390319543668804364644368387012109559013727639425467591569909617669821113244510762667620312709457551671886154782078319309097787637491489895550678778724516870439961805703615527404776044373822299363604871583072767947140654084319117744734146359850585936981862952681144996018334536977991484783048036837540047280811050477365062332875646768552843584422195778414983654048826094472008218998530476397068072670663491093494000994071744143045967169761470594780851910446648994220289655047254782469228150919362843337579575587834049681042720231314479945720789105304419157464837945328513424101990597401991242694644516276150464814595531549724956708158989140286745420472086356555322149086747589699175033360594063389900262929904982174384442526370594759883564372001284682770271145971800501033657288341415049447287109335871194182461587144782771214149799315564408873817110681645120724216862927057374325787891600612137814488876853678600634486428212586424222642913568800916435191465540823919326204232084457268476211362818350350561322524062999591613065334227571350922356338602772548595173298594986984235397644243730828958516842084542486796495283704058641026921905214159920327284619190297784049235571072322172085774022318391488554074918273797478495790917025054880387867554123426139409361229099269768063331421876833914688458468609147070645694639623836675464339413889528417441633210807983582382417701416827212118518499691950285096034905632321908775622824940191927895697796916493450822616151327909409200857452596261894354992880482546417992099741888003290632671630045545523404763152614492510363192983568547696265912908411030254802920572414408160211879910181151316643587380618974330959973706411061428674275225235744737640115103230226518356061600219344963084895139212096312272622588839809018328385457030204958767320394047825496570209311367505154717048436339188902370528685758900307408211743399918815205492902398736340671294234590490490694835504628409228336173224934421651743827911333809628855039204950387032817778414195083559183640286638805379138944999074818827732631263689406188273773399410627740480693341556448176390557563764289286244808043882324057853124409805512792235016945321007650017707927822576124963726921124943417222819761812448321972661622233699322048743316780308583719980545365938597281380726513750601519904821826957542252375077226120933640650495904466624647401779149272999772002112464976517700830920265557863611080614141197673086411364808999200402945737568171486486267663003558951323310994011116859714345102620408985266489807129627982641182143422867665019458006149218111358877367249483837355080678282155475235808982992372419275053198707916554974273772462389746947805902420124047682618655074648393600992344228473755636732737490623671866064531180459515390945787812462248075367980407186912255776933038084697819793672753432503566685004040266917890284646321760948921030098398657624376147328820037065607482100240641640657925394506166663934100247504176744488684138627818174780888398287331496996971972124426297845621382908030744724453671977502785040620606275188009461429243524665466608235624735698921372961803209293854014213881526263594154597891447048276112356846622078493621788003427337653046862971357178718250815174278265687452934521339766763485857676178884061043838985573589264724671514586686603347202092047094446971691247019600170907525680847961507863631169573579231983134804956124159044859912149339160515965735913604440655988617571919000450446516017156106706321796079512146134175394444426596214608923617264603306104370368717934102813283922387797465088805999470738299141227162483369075111977790112460499890826171098946447776838065421941241238727606123419748336691824172581914618579476689433479379368278212886541937057386564340554049029095945030296588115598614351544895405196951869824422543701214802526640184028692291358871060614038443747386331662203786145126845218839958706750566709445482779787169085889283771417180125139665243906005391653321553675176897679930487168866105533293463909279517936408952356450133353591784758231124519686807662471934106204909084113052678733411473307342980516045536866291407428309915132177947262018141742264384204731367454284943576943387732217503791858170003583058129925191313449644400768270561694278892648825316875783534017413565897204606909008274250222854234256033524561352711355997072283715511070099025084933330896195793235420634238591036672611203585277518314273227744600114104126788034966054749592129846150809043798649763683795406070896873560057289672067936322407295770766405277501074143479546193751858278539367516449381046231371205581152930309785646402313176727430031602717501571840868374787503164271271126212558024442810241374926848144875077938174646861447108672184765622038754144646448283067104227305763188970127104401615909775740003338001059544925690436049222074860988880638600369023026564867343561848777392255893313061830095938282944289899941174780220002368162557900529172830872521982360619715729265269556354878311425865162348606106750350278071456552564858376778823579462982187544599653741175979768031217083729251135053956005859113424692287797281171466902321861020843313550772569778419410271287456288863132175416335781379724732128442869511129459913548765300527793615192108250912335999917399212875904370527395913943339859524806767786275179434590588028944302649413433878893890631271786294672493975018935311052888108035902538564323160318469363639557607783859948266614355682561395144031935012044847453745251599468021207932169277228425206664107144209150913643232221098234486729576447511254047655792853698039764438199723389570489644482850657273904288033510643079811553505074052842401001311100435581855752384890215771810796133423386552829704916887549775522423573309157385734292174346992172904513774691964323181862006860410548956244652336647387454594158857501639499805424521447588189280127331900592728098506503259568475999952754099814606139983788498371478541592920349920483744317325231167799198789886432527049274930553215989528399026811904615956621720356146415248848598387511636099981203717845586490975690180863667386608181685786630758958409704868241380066845700090531665297231408329557804604145325487954863053856677847378950038815563495258172812423423534511584066206935802302868636392517377672003907584621900456461887146380172479223737092956048071436308019090422314582342993859196098069510401486367359711359472847533897315624617543659040776091848516575213520036012979019064838519298734935376816043299566755238875886000598489481994300280449175322814442686177953571881438762225149427720650378070249473418223706440645085828969850015190647236208718506335601438326779557180606501081673217847751437939002318227286836165257203727440037489459632753872539108608122963597411233628966955130476384239009134115344367028685883265289909765312366008902528215406534283915275209972414939373206194685595679897756822862611369173798964024847656762741084552158574195922754533395340445139195382288350579647233879537471556167618731770873795806971677009840154063220683012459801062894244059551753024330547467005688063847630825335622502354991304266555558851211466985169035040978201746275532916028478454531176983137130865069682090165780841177345417734345142360859390178657320891622967277007743634840668119448838004500146045487801873093919647755500561027635637829622683228079907968591849877257460345814527088782333456674195240834538951515420089292814945709734954596532261188129977862308417601484905960688426618826382340071765675653219200198580222161865855614900536664670989647923826804435307380048737196888390986887878909499527975307013230380997232751645249133020373649459831433939039186976154718849045639751598107383995327323739360230044808347457365922626417375704237590641431917016389616036128983674347321999738937354212192464174942661858013484763186616511536764234841376510063053441012761572378367976302032578551223195548365927607012589495603660823599103234730519865338160019547161845697569119512909280377566124501464842707042001847998654131328862190959809253020296862252061578307580386593270736353645029709620512427403577894760397812347364912937061107848538209634279910556562414494235203259630024396650630443145788298352658002450464119364011817777409558241293600452007127027092391145533787821781704524534994382596087688162079417278345631300317170959184460899128277303838002122324709685679742771178558810535046210111664469509512229997770543898195325532982715203312692589929788201480310960868572769834412909385246500940820184503512621513589545724576073198794978457578625115880620198028979260845733559418871188229756173552162085507743116097913916226770933316936288515749461530929701847654134207150311561564680058052469063680000, - 31237928310353778558751885838841251894535734041897934369967363859205191504945881358723553225014912980466037371946355116498610997075499951752227351560836630674055331106730296724131812453588859663993838986644190272429882822432247194243455366028022192968396155135872831872093215428738964639487676318145801671795606994298968107995532144391772074585470093662762028253476445739994139628844500103970892514506671085578417677799686392694290803283322105611979171635880064459120254780510144701430936482067110730281714785764376764626086821357086917302947743096125773978699881669297038757281192227238263779247592170129835335532187956175450770056481298285859652543042753824504425198578482669532411112904017484461163043687538418673269294949720190290436427665039703434079927955007812310344752897688203607578827347745705599501444743353596804047994727703412152564233751732058766860489990340183949725657275714874999510425561764260025724864823935166914802219666983186952465133492869033166692475174863227422020030608045188597069473447163300137766110815869023531968592410284667571908542495521271217361596636430959469976127982874085527208101220310560922719882032497543146755897988647617817219720177587816201997599032450203421994411496851329980344293718487447229889150666491045398538459567866731342185914364080801184725624805694840872657900057800532204676927190728247150160119322746106733622067363265169235005851548500211328064428500881792666096636957832102473575378661050106203129574682102477194513096972827282932699101442969077687265488880744670998471680553113914579316100854805792864833543047560088649792686105721489808680083674970464320974312813073463099168925849110787925204936247253531488890546260843799849727088884429701487783431891266270914533414238533833330254088549902271134568020105861206914726846861486653236683442749065562077613786863117067674261991486571903388117329137414860600686577755562428560837855717479816268722115323228903030739326289482192920363063130941824339127950131504455163747155655363102857138154463913232319876886646560611903186657317446689812634100889441297671571175880988079064569997937217693855820024254729664826713539148918279099261908986776857949624169484497029201695103740009970868282287676331421048175795910827159227669880443770842830851156989253952008649647989484556422563670224827030827128789866495104020255282428548874261859804972424946012712103572825405189025045535505885554051733277999412659847824961476795002595900984822440108907117775192128074249253281875929589189313095522594085197777980626968721501493004790450386173161397546897808738955985662217278469408250923975577969820073665687396621373258824470158084940730809453932645498380233594759603976549087144260587820830046198618038569168035990435499425977030168421437249899978454181565750989198981375801089897688839885262071992855303303830565432591025374595981417432432902531066376862187600099107229141224882313826213053520475747765651661247514789512422464162765526847091740171524829238755845206735506351819333141176324741895927790823765515294903557625852825849602386460202279592790580942426566800651934210531624698580088761017165482422954215585051684884677287085701151201638519811361257299514770022446385853320204170490548597524152378443346587989574132305986723406494743660377982200201200907398447464295101554503254202436951733161523150280684448356322361842793789703800050247407258106992912958486146384589207616476368996700647891514552093878461155659498270007499736249494572259973450558815419901031406688514352834069614056736041788103381080248134920160980613570009079126013469798866953119624271266446157768475451839409583960755577481451390144018617553980482859441617234846182400130625312440638102001901756719474232447775856354388444715077788124395176909745587536497941398355444802846845632459457275732381453020284757345048412519156650047695066296563720017849776252719939058558921086308968343486772035743366549187309065238873676531061937039340580074019558578336442792176732489587030690598468975249762169048012163391455529311518015450312152257750333950571116889900324404984784098924523502523561079632339546588175557121814716900999192589005963450334719739948486778220848689997816278846985815746760826056155697631945407190952856398508528386726930308643009767851045911516877557303533327609767935693806252995515098616049162179679639309459866206317863013580888177371528567971839921948783143472070288493387369264312522524795111712782208572138572634022879801522811761551156151669783475359039801477394085382079300739873718367746103845816252060298748453678981541844413469983293632670121783173490438020277242431331505234051852458410658377855192293580359510767698710671953995854679932506318292622634665453232901940748601290757077798701331732880630702889334600368469357715777020869892494075297039670560895673104721694006003710184586196551049605395865990175778885932555200380523866792426642180568673337181221565371839606792569552540194114140249179181654516453076410170284186089085139304421638864829154309233022731934518731755185865338530902839209583380046460059049561030123869343768395962048423502669668706762179359636988398132492955165121356378795647415732392767463698134134957819119821217407905360663476660659700164209799944673836860042819136019456076129740240421127854689359141761870919975363749069430642128423188853581495011687857195644007086947887728229234506732149255333079582371998173863392088895858256015190238694842628388746640195608868000053980297944774265328233906418633407757296936982742819943643695069207231404895207025396203183827908356463786035173113027530451669564864075791442230052988030533266968672744221847112761928818414342134885926786558160801033259627705805281933915224111342992785961182392983979912003642570883582164541772785179352055216793334032939239412764422833979070866858452248908977984090826153998071303247514208683364557778056101840846368297401571313124554939194655403598097105601030991169671138758882895184491830664341677433002280155367840858124347749939684640928901902383346577396877821622769365457653435943433793200252788063959297668856277314110855549352611509076838286400839709859820049728175972207341382105082896206103111678260447176369716352087427093870792729752749926293230451777391733911547083533202119287756493315929328520887033611795341912705223193867552323843833387357579944676289855193438135490685467599944909037029496466465120156473926697649347255011012431677624367067895398439242733760454124691007652220538606804796211607266707737702623194470040675350104801860883712364005558392367569898378825617418728183085593339641220200706587379598417486122792731561617933660306374966741158710542706469296875008326086140210806545323339377198915381451008331272590943846328970614685279542956544551212982301700582722339243514655150515242345831048325361884522277334683048357404050454506870584295996009681764783835255345258949926269321692523756437722750395872017397389724047318127062373877553261385693283980758987189546059487974676196259458200262482099150348502464844372409875552280521188549940960491368242669222802370509599406234593061831939413175636019482406483010965844269218105409850828676146934978363674430283068857174754775262627654402555418804723890199879159121174678707222841328195336943530425357099648542238703157615274398296351964488790203654949896358734684017173014857227779719381487627492451991740070862321632890561783093079887506669893439162099303205938153603240380281645551802278328301742968476304932078306031538705980528848587136918350515081826344108779803946788672940285126439972855114005800532139736916740450180010303130687325173639121222470519918245994882339661496807412979502313788080347676526824161596898246312422242721581781098219334806779923389694146468949039082405765403788487758219244064878430556714784867471997135733821755955974945022760762180842096734492285761862557118997177623093050878550262964700956467467057359603989640042863621711397227077447193490422451843716673028620513495189318806318330815219203954888092351158009963025851228975945805420665413695733598275706510432771093106755638091147317920921272304420962573557395778159700385023055813750693342037994012261308119162604732465611610966882814728132889572175421227167097627250644462547410534562061451785759529526844014108847176741750743682020325542629259017602563417551904749891482643645128592593415055507838086307828861607110453835697458982145432577376936266997473496461410320933565315873799096105413087481780698207183994250743031395210982017915827348439004977916936386881605522402483699418869176216473915011398297958970841500254972000770585070552795227532717914234545735176187734938868221418245256726248458278493016123409328284645479232920398439891570540438221844048732645401951907327876535810126903735612177146613596160000, - 11891325048359652695610803067846855482102817427491808157858401010500677455436393002039018738081115444485315779219590198085438083960308796229697463020493312074080761798702122517455703591955028857299754119574608732701134898261582028111329747452112639396162266407497143406144342844715514138489165656718254297669879718384497045138688848984157906312319893323889166658542764452437777982672711314473903728998442357586522259257410357592253153234961842489676526005916669000194487400815293056700724328312600443326717536232943720341902727189542674215778986422441818050396564312745880530450903738285089859946836484462709613844789882861988815740526502925211740129197758058172534868702491776438582482942840274400549586923533133985466364996162513698511576597146806378225958004296940139007940510787166652480861976233851541806745687172028671698916069897378095018550758029798262005689173152483009218497996694398023357224478961686431687298553415589692074155386198219689049998256412431983065079161208044631571191307777980298195951534721131472528481867629446910619388572609300282442885148383128011365521131842800466355552936192460483856639238924405939451180359993961867931381615389644532730934817285610305715764276760297363343700187868470417825306326789715857213361574962154975685301823673136962749975538545962534804833150566792471474908287530615476401313466736071546772620265963402494498274278155378403616436786731820071540308850716064156307389052837022610458115717309946550800999658296577885553284122521384898677380302708605479643174228118047800252413443787407087112028887378972310369377497557740803107632830317840378153942300925892180843136257347623627984795422774772770402128012283785031223464775654052111716584291295154901116998051463282211346579726498917065690624229038946170069995924296198488140028705096539653552906794584485335032543710603924013703171839019585330898193573311280989155927632097713138906866465470148924397988140051987202829797915597065770490206635022103294507021346658077267808407765456898151516359956480250061381361888094402812193145166935627208108291015609964115379771613686893914189580357134106609512255329621293383677937162341611046110506469156773181033255771516501084050256280427936309744629283870084511752728690560195694153977126093224557570912016648083591912401430268471644022984838724219956567908127764650861750659536982303669438600825416835444607323513698741068395225809657321106218449747600981109868864457769518907253142845000965213968748621104934710730142362536279740244756526351315776736144807889717744328033284006177996764745780279625250001566017551092435266395541437219541400280595611816569471978308833127907403216435200219355988602745366404801171226353929183368860843171887631924917031634903840255592934653170765573329208320728364443051278792976008278815324255718699731225598804327065403353607726108915282607185917988816979451365625941591891072474736653493711441945776787330361047608472060076683901924435183674913176782638897709011780044788228007704220202212187095681402362708236322811290000398191742347420531985729057537381208921426065757327838882976731225575821266777239257508884456451121609511203254109609096304307883947917387327327921442335561806880567703045824958600172471525983957448980566812662626306096869098826963004755142915679464865512510594885672852033100238597261705489375451710297900212336777871628271737583572580686288820934108165600629507408078635539147485363082234182723879356722882880506259292906143874312607260670400808917340327070917002588166784162889825977228945892230850676005991682630130619187267588886505023745511877968335550211840518662255218216833561826374063386322640234285125145195104814478480897912333749234504207448343227644289786950654811631751278647012386345106528498518139271790164781616421758645750085361013866986775125556861604252335600764760505578223384702555440587710136458397264304131600587157469178116599324188854882026235073469799954897802300725974930922754793721858214631548915190890287000366746593138977566094922876545722685531068342542057125917136145461187952262614952208573887942345848851947878115786425338452693812517318408881209991662335693203832916755415150354457213135715127813403542865993956398851615741549517194204301991588481622163439105718178447601920807548817534346035431433364749219819341099452530404379405278230901605702275224799476785423569959045636599990398476160838904841395184656794296209932571588840938360541690213636137114087241406231980110743869686609929494980720046874838450503510023973268617166442380032648738978442763166672173241120964077361271678774479224999582540533182616831039617539961468615883527797839424692421927027159731941999382897091955477231832060790005013911895583893221724899013755898085909811747812527117646990682552022126431099698827500008112612843902944407003942416162068607859427442723130404452165824816996125105833156705536087347221142697762148710702367269768586338207513095719458206958361943130860685440822063703991180778163247058624768511475414854841730334042192290677265528046416738902544593840811910801630851333625750432561051832719889265140443836946955272696526690341499394350841926241585427403039182202169429669251469684838446815505944012432823743878749853936022775360587320833641638404466424197954035131065293855058692153359781165137868409159300067595834223359892669742335564165494475660618429758687345890615804837499049617841729439974717137119604462599374182352438639860641369332896310303490305046720432482357764844515916357330054665006678732858602815900035097529891310700267828703680766640254697562490652958298609500344429402186594938456196162884962434119605922773353466597156142560157064984214005411707569292456504148886404808287482193439551223187322836126889971714968426813258476748688649250495766799531750216550242767595334247432556785680502290590363845224583785259279811354922665839288403177061028127888630734123936620825490522309084049526799114963596917194759475569418628240990977517752749977933032133478121535034828919568611248587374121015043341891645520037698283981103985174834574811087274401787027346683965561744978595917086720959991605468739679537683476669324565353979360486130725480893195214086970946217161503445988481175873309882156153566699657092191572193606180453963701231252022239443735935169492821327762915738435957031315398380737960342000274975385061329713391661213254515721344057348258711078179950542478779019892873880862094948634089488193201414862758233519751541888576697437698618501213117056589525728695886793396325380413909606383572943673654501194808941485369219111299144617806899792691649807172948204595750582783544181858649498835849780746572089340100685108272307689840130814288593613254975682128585177413200136989814909682634208071651060657970775798467152995491867406553699525650653108051929839965723447604632812630038650019636957790673211474014244986728862914669133628810415936595606998064160981671674051332003665222032876620159130247647278687609010478253630649402282221043156512039775478442392647736162379277928871095284956202859104699792321239788704727158873437888252643472365053863394230717555069267269333790721877368937963085530792461454407823270815250150986694114875643848607718512670904531016554665418597173836326671688572276290240009129154898870044587184719660392131704530725251686637751176222994684916539455173526525249030181232033788517594529106166566024016861226070213429851555507453570147264484085952868101554968280937109381365855580561425832984920755419956923877293118786715765097949902191927308115194620145116157615917716390225487534611596453540807105138849770492358735385933811519175983728875825312501157398326598365135265146317603894891378921411333557473915616790039242899731966961152715039316974008627646876839671966937903333919603246969174287955560631550116913386095418701676981169235519997136341638959084009095038300731562715940741591396687332351840001886735219638698257885736050563449869988193393114035759554315530473001110867502300442024352654249472108044231884230535946592741525607223966184425215782559927360515976612943401705114924577056813769863835635281742212872844630022837586600769672839581890359320420438579885708779900107848535084082231248721852366245167280627692680990391481621596887611033570367377863621787165983196357948186015415460236733755251086487429307764740775827852611041542156321781662330389006499591872223252393779043646249682483585604071462505880018366850054840245005962660655788991458970006922364383418314609763506977714289726836555159422360514664487801097881391345673537391846240586443026062846016657070957215081290335607933681425704669922286370078577813954167352445928095314614505043510822932632925442062943031038546651262409294364896034063970508913510243082830564088751101711482880000, - 647246206316100484362519261875072374705655770881673978923323875503979044390118451187310925738651698905014821556117834123690609715873827227456569647139081866070486610703594386233102419892500829085027539210775481619902192240855044378174624681316407196718707296145460460926633936877803460385559349491661239289191391838617374853688664639606678613372164565457312479236669095166991603840057960247947404563781295152661543418195218672932689717207011496196939121570931555586469342384950829570072758881910770666450422838338802624487523770529199007612515460519174096437900927518918787392772133280533088487727497655065975922542740951980412823865059583800714217407656023955347082297985302377003243407987955207401412769476783804814848638982783848880819188990311709493872224788763351362295718111650826766075107830986755794011905545304455202382783987473124044462972711076883642507715478964736661308140989088943229073249604784744748360435877117705439089225186066763378271405167916117305956323165368730325383288409948958956205579105224587060493903269590624806454360386156184446502052297260251882776101130448686948618371029700774786959407072481687006591587778524766670659442948995004699709488549157367795971240480084703137784617284008996570122113463552057901836882694143791647575864683936696417213366474674096409946194099172415311540763873590643682035255423527414077943424093576105017977147573461784958228390171053147327286402475425100554079060518061296462633363654227400417887117482907566635219972839544875505720338092261139626727734461315787121665019307003824589922763206542651307827706371316751926093207775595677725451222061801172652078394920665448401789713105749891476160666112860676871253890776476234520104603134724789749525729525360907537098950324806741555095754116888501092411498515886697066374526629680836551735752241871515769041094199697012985530095053562212543558645435995295235841758096294379435798357628783204647984516625019499433386517275085546584223473252089123425363096298467895606404132156478550459668953557667795013892216445304641131533220116175226021244980478906820085592039938241920590835247830746833752129803538854628506319551887993167200248228542137847555558587212161041235845799063930056537592895976021059990888247734087125227478975596590214668049444333029964985362625771319206082689719500838975155019170582630525421197136432757960925681787102159926042317957372647886041182464489896178924756922692833955791024711364523754817433170300316099843386329775911762968121122106612923307077109823136084670951505714277709106041015708842449733252838672624757983249777611446752153406559775622314426428887780022002714336226424805876747615356916310988989722308763044291960671268549482022390159180411304209009644172145528755373391896754674462774673323099336482198985616566356029305944500398309930385624732376791235698467906094996862198372776969448464025058424271976830301229902425491665346540720971389803280305726351299690975486630792889403449367699357965018853451147772844437977711936547552639942080479159190843099109119638424580242865606255495164172470046679209077040105148796640065997205100736271736115783642204301950724157220435646306670398299255457420895216089570828485197511709271526176308689891355982101398620130968059155314522847599209627376360138444619159113010677649834693194951680307839178481518602361336546961136652075606571581172957901153261676885914461582591127821590709499561849239288759317730355017999471517610126616174975139863645033919030558582716902230607470350029380944480430148742923980320357807388727962434062890280768838631953546690787403364172856186491785994091376011269090425779572685123203670325445186181074792900548423227563922571556049303323746660700929890178902904891952131003777695624842992998330657354059774598207657351456395168242889473163591027424493706421278090649142041527163286800539010596035421786010725673934753718226976182892734924777988721597399663977171926411325671258359228248300140292093199740587190006186698172056701554485214226937799417558124317001671207842379215912313978611524826229691306957426714572272353890709158276960563255958656927586055160418847946084542323756170844287631721255030507116479624624174545208170880518269333852787781717517992573768366910312503100117162200400169510226918293104542176227987085173002514461101527370400619038515517957062777183843656442799923493836599698714206652236186271079426948839001940219984460191268989365619646716950215490998460340287607569219205675601157801086686346903629009165224500099174245152934692979549170849543018390395945069345371301728746990961333264119102604535583578613729669059089986139305211912369244462741774282973900422491391941920440961850577076340303126438172858786095036911426409968016283028300448987281102208937301847606654613249382344521376152213029629063784063834928147890917165916651436473933442859906276223731284904755244458014336356555315703479001044403684583791389490757752425380570888617301575947805690071754972267041765149632998128793514299224574000755494700705222721941734212782357219968774034448177661637473391885000985039206770587910422327183789602870949416569956211229052290132822683797428078090186828038384937589777584215229182671939616922653032061713371068791475081453588573472062732565143908778863316981357211096582293045069876187265168618929299079007667696723996372147129569227058134080703275329675976686894875552342447893299579340645939639748617806461971979421969135978019150448737842040222652590598185990093702681699993007568964285538720792745980046864070163164837694834439430820350944102140189422609246540920759717041172819827054043339599137906904035099831113557206444910587464080003935078201370367801496388301878893880843772200389691552277676798673308975586320001626796873615992282599822845341962574944425632016416574774441558009287514469264603826549511419099439415044262342592355410226934568927353440152082912917730425447163446384849070271103865231108580237684246847102289803000816662191562067627222395046319085221715721632948879591422899526704764006560583387060837436135920936825352307594250973007377305435883234207374113632664304011135198049584510843761668969580382063570338295102508437743613079323246789615259985412358819995486024886800676482267401538300967135814464681448584741986462970042057030182720293108049958105001774940499695726311925333281101021678519036065002203024374259053092332749174950083947334263481978643666492021463161902207855368217549389252925259037100314719943524815769679654852903609081505383217343855923577603876099307256433393498340870715306314403769324622908971895391835145236132265863442189944177363979476008813073832258873038384574752063938411145866424993082774955751192523642023423343798490642436934609929851753250056172073418956830728396577488391372488763412673035833473968418182231686773954135381148677097879926618527729343448728510411966032573790273660654715473470172127869852858724607259471081064262459363557720610627793321665688448001269335174221736129339190417338827945819001653044500619895185343616953021719850281705042466623813193983023474314476758421817862992323836272623926890479131683057760950235239048136529903495972408891511862710468623174271256018548622249581875431999571790478022507252823301262486853548182065870021379670549476274305473451260548618471766246241469258570753256063842803453203851793163290154387633123103531015974177969001498118582425066119940560096715867899567035214141792748450842415192754674448367964027550588705627590386583262326532517314788736352075226026971834891561733711573088475884517866341179875238173278331316111171806279424386442381885895091608379937118318188610655575928910237165926609724274315957317862183171114628498089086908000998839831285298090669165190807625364817798825759196298437210946511977850287507478842413724556292551512948742022953001896664602041023637599571885271494405366154290924577154448085797220707954156150084881530720842483809540619490829721730341569945515219037263620486774192236549923336408617206792601829443570694258439437783503484909318204553232207741988714696850907272349658051915815967709177704742675091483204132125527788730282294541296232099177823294445289871324165253805725209437276962687344778246445641791436317601607317161922675126455843011484266913434160468025588012997374354375170816422555464934467756238059878493032895790229269113926421548981721050657082872828512861356580270734299332017544783375124695908261057153977313607887078051657240180623353444358249565563731853086231649331377073847718515390438205651441240403339039402044060910999636013092463545455084645716396908961104694161634850327973683993189426958321902508091505098770404449547077367887317694779188560758622643655090553201712924757208289147575336960000, - 21766393844293147540508010516525113465325220535748775493407746496909822516941161392104734782691529574648692817803573748994061440222773030282392742130245034935721202290378304020731082294930553179163038965929224869466571253405953263390770428708913572162524459587992980046066628295414356067679698273544010439503938940757443214167025248923894555084017942990212500664131498345277916781293281482580237846974311222410438898558128035552114948212448955553577780862472349235240442490028987587391629843908562483969107355577552163447961206746646337491615589523879185140178502587939884707795088901752912618592737031914914746143194500525605511384531172243982968794327001698679870678585390485629660652616045154907226856922245260154831739330506636927046291824354134278226161962156009700254881076481310875985305380377189637931736139215363848155859400285224366812666341400465314463919308023298495467165305050299132435536805410030015117113356329771137589691056665477797894878409094028733275355425674722957010627874248827730287274692779017640637342604493858977700917254295642799438639094486597602611464617527690529722710009734176490732480422668174250219073603712226559793881480247057425878014305852380765468138860760292585088041319690322203135337499296291126124831996942955082832891822574528361674495550521209721024332328407999855403366666530417627168730991274771983798860517710454704230469471534141973208792838962020379230315390007035103552066076013151829326697771801619845420036189462653782939215997150872082393164646620155409385738944753999548763039288629526897845199191137389180896850048892292565675289260179223356491185113226131057014642502038514517719175908972687372213109904456277948809420557556063957217321359218770292756129453198632266431015620184306639597309183972515510703048171307015177886518943521151910677008785109467961137350826202977395146828305706442306692098621983007723952341436715792322224758038911470537376936067700443970151759921947085479675099670000203891425700300545177367401905987280067297295730052306736208513422794752134399463195416030720545376872523984608300290233827766246676584115005644281961141666795321877751080323671168222409447058088529436629080270986578738389390498062722974016336959630291605619202901555061277672494275786077506608388179948271086980629569073506548457882226227650556235583320775768543238466945874886065407640263101824765404905710692438491480735837563569004854440107250264162375941997206260628534672349662563580041277026300987584950854551666203689478692576851072287787925189261203318855839446915480174315697028354131788504968791532605372613318973415439019651574400216595282798854126888872302552481368042101700781480733917652509981539846384256763747709827913086022453984483953705020695422332227708565536198909233961440310372104399345155113238961260105198718370722365242269277051128387527141134345489438470524436894235680198760190315914328253210652050527865008612016804167510900237342756239313453719206558603152616333362175912566971867527370348351589600957294987624385015802578478496000097031888225726219234825499228142418577975863251088399281825215391258029354856215842346951767490850290134792758146713504952744953900206183298811217240001264793422568171008186416600865542320094542366602935596768822332424239462874875082052945801216625726902429512406489667384307633009030248921400354072182934645416636201011584102118681834577111949079324310820630154504021969298582112615221971003496265668740792665027281500546225510766909100128539566866580529272219455762780511215259033872959610332541409964765641141799975895118985121061749612775402227823033794716095341921717419320143256289265475108507881259110159198171932504638088029326090241075616290815282455883592794709100342443235920583959536890768812447110742186688066107213199826801428363395733372039974680225923397356412800601462862247679100834497471119781759350515032233485339680227774317370400222552401760700593924571856972620933109673971622400995627401264354994339145456981514476246243772671989595797537626894475370671326147204710754414849271903195423553913770590557659881746790047225925764938451866785304564280009315928609271739886008377071172622456723299896020955487381923146679333275442649926187044132672464786722610453334491564867878939932299426189286402534731142880071146057771516177219454594258319184486646572760675484829402808813389198968587204246507741227078314113021125119056429032342642345283189911091528850782119790163103606987445625120274180656128145992216654485375947581649181389126387305138690265015178334950974218030784394649293704820175454624653512785986394770148603942980829177364963410468051936031284358547674133971458855207898461450188903436245373096083644680735104015719533046629888405470610643188076118167174689588487019151648880272782945443696598988035336414559006566261843288343639570618406097914811227569222915604670163822969166888011657917356551990109465470098062250584573662795695771719723003148495162647262961037419037551447825870691843854799490271472589587888091643567881910157562092044795525466082219127977423646270769447459600713206252066651810287451140013672566409484404655720389886190998058859648003549317788719910492968145090992100845226343763060863946709396589024339362203442029670850543980401399175174055672192880263733405068973817900172431269434390585376630812625698399239565182468751271051417215154258471699668261696705338626554104073441893679331721155503642208483153791808205052462028802407666430134267601519550134889686321053302751183333360537238558334933973751838062923338574688726090178561617083108489105137927388264684279537806358959278064854362297194518783778009937380347350469274476833131882765243479443490830368190742508248034877125699369297131537925051150392198344778947132169760277743768988810300704140697717455031983591818267632100851046895351561709166837232024130223881707717305402351087975971810182917403509820200655516718525975432067788875086464010589819090508857936187745384659643076684551921848028194735620704400384789410731482281776747788838796211252067323414339342032990526574368600416192467918818557222840206930282691721600801825955399585400372607577827165295837452764565357763079142724291685596814852689771423914911534662995257411437394980501332777393087598208804736506949245076058437678313254219015001442127316102886260144018082619598636565805757554274756426928907128946699626240051489644180780950043122316062516310597214571208520884022096611668270807919102402423484999534426081891855310327209319916840642893489590621158009135011136644018160161594915853331352180461935846404446744078683034521575369190750172600292874497507737947983007701960135721508333277187098109921044047039451332253261812543900951458641575189856082491914760380556132301009631833421487273798852567369231972519442824699833255913505958067175146963265158034700443501137779431344888926421324228799432024424391169035887035370208443718263630742460163294797117443381397531504000756673361607343399137934871022440175321117671032665926024540072877463895983663671646330847059261492931186886158146403675084871636662172329166575156761577053713421664777466741532630410639228135734052025097116003059157821645326574155549068639584182826657249427459956445121219866296097382002719280709850974926130062854752093989884625447176043955845930782603084314713901742696980725512421646677347430581889819729678219688904917354158985811743574133263051227808087516931837040613343818737667690440997883132376300758259093938720485016753539830857252849679328683205068106192024057263377816862800038404143075579390420120380230854586994691070234333511635378430828090775168319775682002590015598139092978206266240134841616625255477916219180571904457502978786874324141633571321066849488945703228135489303537972438086731740479417162770100949927204038113458294049997348851936011620182825835890450502871840964690315040101894230376379431352098293709999043731682585716577575752302810245270582136672305635242499942516231749294695178026359590580681368156745347019502203117643199585062292849843995003898315612119091570148218128106849624140040861972354191075493879082138909407015562704082017465990650926832978314535933266416115864271970597614958946249631274827758817428900629475267861142787923029834049757255928282154898739258031949296466353241039612940737663898979129576574945056303962776005919014703679050846316861447516107651360739109365965207958570374930418646673747641047207151985372427664113211899210923169056824522422284350976302665198646704364948399439249758106158579280697757472232795013916830210425039465180986891800827370246619302154772709767330483973979480459536521568711739717411200566848503536831740881804760689597912351786896048783360000, - 425056938268900333394825753828321382721524041946182335576764875871195199065802237160989554419522277239692248851813381413786087035649989775231748311804134731304609397988967039710954252452653830231445096014936822678609910052468541908024142506135003749248809758655603752053032006756596804128610669119661219607946963714041477525024611365398202051197573405828148955843210110320164497295336756430642466528763474005067262678310904528948168380050396831753708068011772095015624927396634142191697751716648176014189880319592824339997250009073303200010225664622863851911645326563879401920727476118635847524766597341273339680559047400088230330652749476602457836753890294519124656936907777281804977410617146917996920060344894497191345431431849072037775648930143270562615514637029781097549156755788817067293917821884809151302430594104520240877482745903244391119690982845826221062597751640008199852442502688021396583095606101686462826774405010968073123528502199918625613402008502003129160198314560583162216234878191307056738729280599492840582255012101406458334789409490413526181699497808315667405310370255700287322219921229142987332541234848347113329460018733351887415795396302624232169749005899506272683245083572671325146337617527430713084368054564073581439876400012685943418009914195010497045224142192328561906556104998319472793848487754542328304625570813543671692629912980197087771067394697076721705753353906543897865405736990817934548549732151390979031260997898593539533599032937462198464679254879355172664686231694460184877636177513912359420796100806324860630591100106667636862239714542992921286874756387509905702089045561041393994728363386938151122685019731005846614286024420780418686023789917359047224087978261205887393440179149906577114335571511425584968828050936015263545255461931025548344526693302576113012321264419467759799139684731402622422962261253901107573287806679437020868517998649388276488449117586129439562618836834922712693162158996472383579467762706450366958637066980813835100462105986922993957650977289698448442582210933180036767070833288851637187730191827731880905722320922142975300330058602839867560925497100159772699575687827677156419741701810776253118040381890361262396471674570197971502654681599469043040963370617348662208225308009413708458166894987127166114019491299706996752301594057458076256514893714718930186290081639680467017683590941211114766229846232034749671036146628523406616999578083587589665632987430966704540016464820550787449223005345359901097372585577476975714589694273287580489131576101103468615095197056222746908474542412820668257139016556833004995268452916051831503948405135011872195930333347001662674237654968189982130320020995079948684562787931591225985080943077924992573456668326073246959445184517515404624189026003529751187813708076547412723447510462376327928357615899456995690195288231346834930731395727061955811442295309796008691842863375204848997755380659055708321014353282139270250089020194829655029818850343097273743007957557227854847129131153854419611492913741841771865653873435706683295279725752303695148767425694851319327351484434213778236839174009535672429047580956631990521626112235934371190648954569542659920807339573728028623940529326926384038308022095091944148195785343771524667364393369318807902044415246514414962679106072056680373203711349480689619032349844009696712733722625474649879562978496265350118793625872862474594051711075603021488759428013151616588586207441796039112456448157125519123841985949515483121536800903703424323650384771589904384822113249197336743622289315836880538114041270595282475894532813524020133041511883193072912636227578040922897135750890985851703504621881493658422484246175043811962362221637170638891545154958290833590950875909717665765250629657202330312707390039042607818414388547121728834907809612770807659166353278594384483214572832118239531801481884911376712864583560598693546774692673279933850535381095322922127125122778297195396669263790487454742460429767668618113582459202850477771422399921040819475928206888286720423856241119287592176146735111443182964849057762214938250787824127763542480275553531099423724201372064028796531317047193890251050094272585970543629201396370553094734899343372510962690342679180094157030236265381942129487523512869769607864406921635165754441869638337932342211271050981900318014952852828246178905142426630017812954348762203516677865861703980746104600935223652972449038097349364290891406313130534338875134296419784672090238936089767445051965151129708737442663246521913521741508431701641326505073070553860914528750044746918001061667756759164593538534664262307077248291846754191619236190867836695075292510139245270567893737506241716368884187456122836369542610219715556845605522473221954106275846123041925211221246135687178892854596825188684706357891884017397204112827989722267402472838772736530281286342793604748421889696375351649009060892326436060985186565806494116925249789297935733426107890412489008897459018801153448869230815741341711492352871354334499590628860031986186754456718344504158550335225747037512471729648748568486180922505430624266087630402750922659056386307303491023156530570583302153497229555453498692467312482490632943767474796780306330496072764784258848577214471675364781360811315699707334190583836740660474083214950249588756264403718529060556432724602755787732339211716338151785457673168356981207496528078410241406519530961919689637638453452614373948895258463740921923926250490717446884967219391535921395641383868405641787023736281488219466720057727631600290915789590265471833972916706496481552488636083705742016900564555066915419755266490047345266141384325329312640100293895316231008122358467101397081534523522124307360870996317918047099085762093668276282002505437328795953773314373580342239166819205535839383524981695586029128676175142044439521370339595195461362509215845336395754997929678216967215901800325349062139468352721940481565983658993664286627997115719830528904660579866838417510534820047868502045750323627697442392468512728793136142412087786885422072432139134826772520118478606286067698362946820132162089321917766108923498238076598064065235357184294125885601767265845806169049375136424613517003401972389207768129583374551953306041138909646401097202506370662299907365230358786083349017132210791196115788070761190844955240874788641607620311173083159856170894950810347128007306142086508132812192996331839234439583120368482610277110292071667789838307814028886441130832145745661725905621532254751634181884982090601780178548724216234068553783328656241647294345603294448910600321316007360167320369937916327002650485169187749842855771069140993961504406535751673389832751427939561769209755634258101641564606811715163484205426495180100335206040244610220391978588354129893413097330309611610758732376113683842403279428557015516942938271468248608183513453870143448723295080992683153066429668696712902145412255767839763035508234490034874612162869126234734443382889789459192599520981932897104877188609748579036674969460354259076483942309778282986020657962699631226939543318922190055174231575696970299706196617068998952237882711932808000388336972731497614318457308042412016254751579492722019891074025985409568120985192084658824507408219649353363641904239565654366910379688326864291441148531178691273276058671940195197069547391644038958301812522377537972859709815595971914482447877161852800702082879423361830415846028372507034877931163582483467952965379323110961280076513060404231491622438446882799064785802716482721526217322869246936858155696594344795825873699550675220059551570346339187491017132325392461884121291324994837741752968811046773056666313839664823910664841136642748233353675752992700962422661627321357553916395748500970012811140473734480456210422865070774822569852157030583289959479615422495684192116722830486863209123780447394688014657382384719938944605818531226018305405647536194928497353304832036537536739203513497106081154591811497858821566910734764668632682356316586912432985952269000229926209811419842226164707096331392651747777200506953317768455058069449847596519227296927565823056818700949487811231583757844630507154538120010791348083549703284294052422663820800022916860422948802957476430089068868389810522259592658934331289192853053038448590671582198407184060070292851426307383804054298977578490219525296923516986887666766177636548414829892407805279741834104618094768343134880632384296615014444541827312988110420990998998122496381547627603323776324624157905583103045446452695078452066843187876170525766226015963329291124644562570097075497896363816984149155914976540729191745502076258232774559994581588464433090580428409010546278400000, - -2061967671022718926692298861893853195903028262863191013284668819586535012221993828062019784801003474006107640479947084210322934142324374339644203970152565063865489201545587507708330549308734026752408392260728384199804625848435531341526854627952553530256621705940005420540389475647977999595078922863401723026750382889896585987720483554707994273116195489822188694377416202178342237332059095856367685867610297191696301785934183695884716799718977542014590758291048607730520301871853843042590226370947316555914111935424039960291162170638185237433358035307764643460061388764426308953932556575551020869397011054493432992839176892420941453752564786591754537867587457284185621258825043684254504982527574171695852453942055405756513710954508500392102934381404806115500499553082348597578822181598407274658476889750671779831136126914609065586952896538198784352037890126598622977115010089327732026192091073936492780203311613558490103679453886230996580658251082562649239877309736699231455370307096632821159618797081423094300003685667520765833638120514816592795934105037013365776275341991469403290112562711723150909643295625835456011520435290271709650169393263627887537840293601711688769374537557729259989177795322884921294141268387179045781077626434866209116566791189656466887711117560444023822305592253429081040823469711334104228685703114963061477374490810176700347402556211294819914923737570407430964042822811984566852225390188006561618642716355689669598734986784035292866317722308391669951744875808369344014648959523828663872976510253770539014330102999698558466926362435713082192941676730161511749783866749367988677050847754929479949034362696708110279670758365514412496589634702384191112077350657354458458513111734229519948873793996409218812144922839961640232339842776154992603733055021042107703080266208208417990520220379016188721861327543279868983807756315446236588631495625446886204041065351202666546702277676621853642526549777661882003006943060291749172092225720380500510938611982965076197407591001500092250717292460213953731136136025097550642526438640306412582320459591807001303587277964272222024500775592340807353663239669245159226244071336475001586510298673097318775833346026905225102613930504130206019231152919706209955327256708359809799980458598039308137577988823535220847630334499338372893881779706770783233400087347288384547824404020538960250545163389617716797744037109836759454447770488502245556351473551431771551345673446676715263883519085292333179780419262832324983871946773945759231484529671155631355883456737556979919034624217908424373499300009504779197429241906965627078978685310143803447890552163563926621068267296004780103727821916011594886890450522645053560735290917585644257344013486330003248192382317183755368444835900464025023251791709058201390421616664654773192525140918178936518799690566032038413276612871020347039676152019569297801051803783928786814530410289818083181562922490241476594902092602226728037007712821186579358101196465358976352833723530298993902183531820284130397396032319801975601249594918975856607788715074053196830722089150775310159066186008672614181547511890053088909294824778286652844062547890337480130702407366206529923533694882768743075630094511542666595514173707531669863321339197956050710013741250151711790400964111719466359820323459273294218395263896631573137817767026650138973838193967017177232002653761167035798479795690878166963173480665103368055997169060250525139292469832943700510156291254055045163386385286970841834186774612624084833556922648185059039269244732793868111428838990573551286876276474308566590039800333743751728730555571672759934158264006434600798728052623416841199590950939995841631446099011498015719744824691798306934640035255116633040016268536303977569197372711543161050697348009019449099753021122518879263258839768527911420643547619228847943922006551204682222877742310830077086821650873796891082874856165684845055363313823231857578075969284110860476249197459292002350310280445313511522193897385756802711056317923605662787605615134081553993937670984822802829238315349604702009438741829197486476438300640913321516543373509281044086768596345692966408985960461515571356245519325888415668587488550333480601709479854431464047974908236253747448531936650280099275401361132701191019755874316661713588362229882298150797114348565152956709439299000179548138329396662072108734245269164098886630271177118735137898050434925255111970031405129900477290713971467522115391886432916792663875754205034844538869746417829073582147361803540703256400003075395653103063830229213854125584673740821189897550875283051396717669954642542406279713167390492198827108209876548100304210800614280170187459645826643833048567772790540858424366054441239435940800220275752690215009873067800660316158439322829736956541247771884230788987671051585902961659457676963750426072073009454604326629155404906630565002743459553140537420403179879683699005297258159369679005576830666208700197042806080372077270608413094375846034285602296507145866017409502681212705639008547207020556782443866241251916402856614589400438422853891197134713099942041696642801216152716462442311406009608308546266983394397709398042691511562915310449225274974935155700229550755182599018194499650374234283957321017339360994448315309820666246994377237049086879859973105866153637373516835639691233839333569733082678356906977012870245766975590903150750875963773326561728933892411601646536806046022947500617448729595222595005356449180389878206584769377004809829819760686621378171435613687273368529271308140428865930396282687690816927940441138797578598075409672285586987298744531010360602897492726473365361704278492312728553456282491813212645601466125443185591738490572991367655215464005052699600740592234283693174966418929608888861335759678853171717309920921249089123536060443338501913087696788999943026138177604791698719652589348112915746647457145815851501662421644707456147060103651278519301195400300464440266204911167779367982731417939499651498402714643362769195820940427695169782758617274688398833740316811930137260819469908215313819507029892937689364080439024275312822335304031629030935144739333696096547530887661834862758403011719100985451350450510945791245399438199415834797631224838487059908599208578320663322962243389332006721161408112595982283611151122019058054478511895329458382467141647490796391616287081037761960368778102677116164150843310137017606729610039587780902266133124418985506488269472093697386119172528109803610262869714390010954715065949379653504963277678148944046762105306359012168308345477959938006343615438482974413880535859274383911209669695750892241224512881233782441433476538866684171400487430449631249402609388738684706301278280170178785386475053088548211397374255545318619287083847054832699626544610131087399347957886794051519499619408980239346390365066987753297507547897766082618180164928659165760790135231402649550868114162020222488614416206440813627131830900367794535540525257655460446458407297434795962947441547276272077749267967789859433709350020210116672718521516223753697006960620345869617119900344018897259733308412462092287771158589793533429871852039573936963739318941738012147733170726714686016746373507186034855570438986284290657002832892101288439456639183106198031626053662241310462271758380087200214630526189296344058723613198145947347737041064983780500689914826901108795965667616240323117989125770603739837555468665817426150863046382230511856342614660517708849976778139538874346257089143069057664747480940447335028242224870644665916632888590405076120445316054711683500434646604862200372054876644707377585091732930351147443049868583253173172449857521941606811794109767104579846875179157073356471861505477382581263505243458645334127653063358973545502524302954373160889014774573206677752873105017000356680945894484539533575903983487173326941308429809915869580012655570069763500648274158568332842852518489870599529531082862919512659138932832641362354500677159500321365871288503951210343594509115461743428180252313910883502452063697104686589313397823381848956064709102553025412007796150675320300639590446499978313605441198298389698289426578717573212711584683909081250826215864493686241942823328314539181097777296609372918615570466904906192804787279662731812605341467953761380110013755388496825281916952886768108751472012755495576599484239738469526733775157642058231896486478775003599349708750182488231676875395351605936392956066050158995821147100788247163379438187308240110199609579303008608964506905799471567316900816642408432702307189332217883760467749351173098170474931462020977539074859827066806153641596977976155234631680000, - -564185949577708008015049765863020439399799476430885833213533535763523527512000207883805637643433901669258399457043621648913604501349634133228244711875661160633699229670490977436483749675264798414497295515431231760214388674101753305809488550756772134561674227720477152783038938551845755123942823005121891310985169905218660205732516854621719078505342089691801704971100189712968282341515507004588051130929598422464455298301394474197613400946769077060650927892693210973030240268718358940366343724585373867082563354182857648828371747718298184993053167137274436072763359513780637860771905091413074350371486708728689528904252713160502116781875585265947029403363657057471446196228411411206739813997902642961037447902450488137031080830418525561030403329132128435704396260909590729574064942368836884933860843916507887926377512536033227374776153787458605551587327192431327642536265904293998423521247885084274138274962681708527654072512927367646467832466358854616043076515477260880842794068924757360434007911900231007700722244474878498191160425307167814377995122140835123648576972250466314466109002802874963865690257390239819691162551436834924411540511346400463937464822350022160938642671582638908274969993885031552352101134386652795655226229287322171236177499538104530693295285309557885267811257108380159968446870479574076641245921594410416967922625847618655918217463622575741665340757891815318993022566353772540184856891918865559947113405203355343880037266398977108735424697547381294196138242351011004631226554083542755961639458250490133190346757004991811766304210959491422660837261372577101179062080958351594105508039098821640757893307078660702570117011427589411773295720789497038007413776297319784643190226995883730019565874968493415598264328210380200405727527138222061324162620664931144490414876974449270720658013257368078538910369794137301194044511829252014235064455159482938961670582071621999848083605322786628001278136093635734907629356297040570863116472325686416308984426787764422666182515129084883867351863773935253011233506079220512670993887179108050137608898662057178872517291165069967395951134539357521237042756354691745181496626942948572337773596208759313499941080024074610148793602463140575613932993505749379220594445907815015441905143103160502004010105864658536126293651604961525553338882129053132470939775312997963186434031036999512794063985677260016926068661605706781978539833408917820816238639687938648329476953208282578284535761046323877451257313477401043981913359958351660111210934302263422115012393998687622281922611858779685071948738345625971860281024751000027475588319404966747040938310244187645223979555350391665891972369160555407399133529846567293448091842074755451601052445740073872138033099934215182036390809528663370807203257952049445624261687416676543110517156745930801408445862755307011307208559367587009259548516836843965231537030901365926272017840325383981127121741679311255001768597739846385614087232475762433046691291838603542412557122771096773874887994983227517399375222412823610067378157188694810272672532384169103294067305348373868186842330654565224503217218213582605097066524074362181396051872361643625436278196338158545219931768500742113178696169730522672617251625324900921434509691971320999282137929551921580642870005705889227887122006389441603476557774782494016094118974780332432469835093338917677149436393118905932879429888002051672920741187230164775737866204297089458154897861544505704240170798865666043803167810022183370896050225851114681621391391346684321472967619944798214307049728138911345176269394498331777326117666395354970455998633327162772812348592786587864383512103431119641003476378372151826794239315651259104404384503649356608651955250093851026108758089588890515952496479295021574179205268107598955277216193571778710770970352394692883315551942927550573644317501610030905441252950590293013628292316368807467116714215819655603725997263630634992623840211557420165688722356885307114274474537476991225624260498335882959994603027857749008589951705188413174799539005609409085285315026185171983325166772861732154169284092987748880582100281892314738259942726669372742873053686640298690092632038943097172320159040196891384616109933759949599670701128240111719198649222656796899380941666712610779252648202349370879722645466111838396177896105238682249472432866834813764148327329402413900397072273775108180987119309646348068298958141120890263293516825495011677366646057856167287480913557584212856781452033350751209682687687313014725860844611016956631580022341517537620424010528938363718263264223182443222865474801090312167384540620015050532170015158215432681752150354193274971795498167247837279021931192535147788008284481594022075542637113448194723743533484305834902235444883573043291567911966256445690399001335124550383680050907573273227534602717154068105396527212123287766727652301706988718016904898390808384527621623080199221274730129491081754203683568329731459075944301685652770889896709844486581907380752449281194512134392074533245013631751177953936354145776804286389378266999872085148082398714402965804320492364699608650583927908682460773403001396875285521188160514724726576791326369223358411784917239024876647026199220969846723585340900310109735617625620825883915974514205869995939930225985423939107412545262953501334949596390538380785508922804425448448985842851734840533908593129597215793037638757428198860075881165148689459929263748343136036984728546606680677717132882257262493771360121260362016813964113945950160388131082039611205062502453477280103200368670904691497404969079393135632329195453549360167428977375101164007208640823484173344448746849885681422882080358120656724490696246284668450492957611427185665479510424522544780645417771829917045909599430647337955233743160520110683523540742997207362246918558727657290001026293179259995798725723495750181197984100322649901500688515080373040005364067042514926332595124825942429816537561687108686556099249331098304671931989216643407673837023905308367335230215137124103720277120606538505743261299737178574151943384051562790397202139239814077605808647399334160337912799829092457317460907758076959972430641498500466592555934975706090059617013866630587822539734068676649293132741605967757304971513160761633237262300425793162648646699308827356923911966084949094152221134863963754568297007091241550676638749449363939906907385446197301279980365657874636605701988647530126727671174151040719628582523051289047683941576714753198142431601482943604660116166942180056287875461603405377314557691300130093066142152381564016773908428129847409763887705631118907885499518209930633769012703568901749423186605809683990452592894490329999037847789968473315203300166520009843110791554138609099494053200837856879094524605634311422774744627050911395738659140324444522798042194128071754231043195445514563487021480057122370665388088020870539766018411799981855165805305257321249983259881897214774062830282259084459279267494333247991266723384603994290627310961369246508912190751534742484233752830355921713200465992523814780651438141984690741515525739938768965764435268125595109007081096310046696691484776071974232596722515548222326718628291886507169677109143345227197517903605341230934440524128810378630685469995770528860338183982545212067164370790009124873252995548869462785811312176926808233874307586888506642152276924666818937308745834697069539100944116041369648749286187374026290300076476008279678826894681769287125325161053972242357730279006390063729242633617035037211691571432705655958178557366954609217305386464103868359915829681390546839672460729346680671304029956165697554938537002160938723877005240796499242311255807169987425104569877327517005710695112895535235053636474643743203251035503545180341798275733649620855727762802321364181299700429117929139968431883414150848224201525339283492678287670269184057415994843050785076983591485512595603228064103233890406456226377149924700020165499144831129402540186206921740168802398459011869777072285862612694343817913935310619121507681634081163865736267647799305916778398036667437884449063641811507365824472577797187466402615580721279709422946066258679260745202143197759379546188978487543169072721487671342973630693457822948414251925855935176905187171057963821035146603802444170218441349712486777232818747801660406130453356033506036896165829987470491252063099767119363445386016590867635965932396510604605920820757950755347879103710849619299095066227580381485489334235692080332825291966314671190507612135642166135107176965697418555536675829408754851426717163310092775150505761628568214125530207899762032640000, - -25857452427307160063934724943286071318983347658061618681847801645775396410004670866223671839584955242663017600012850651893019238280114026584734526223637950672944325902650768017672561653677420573286199358604242987217114116460620445389101205332490106301008771248560091518683979323859427708123656151628619320646406094840023293187011216588841926063055774542098375905225764904263892093213519463416697837493504896436535616266965924245624812061192798280335019662303051617570880012322947476324479652161681060918945424694461075897005547416629785958860664716421164523912162382249898520906975930942996301418317043512165822257422031502235195160906662529744845652758271521397359638179902054684954821097760761428222674742225727666299936822136591615315347377758837827250926448464175343003777412364891162653239508201812833458497674351349126404671426415318017540694943916564110016115254697373652443173230274562784311119958434025197366812317071029139900953083418819994918170434496915980116344049470425639811971310326072854666552816681010506083061929210092188023383184636565039744027411695707461969275407627623654017120865042516723239944506071800441702026147449785419043570365034618713534402077401788810819738438063989422429712978114746718775066173749473319294550061786595590911220502824013428961179511313265794838291639093846403682198039497527510722712587550078876059679962138969551511627625040790328666233942845060363789774557264574186533822610953659024696282474452739548047157209236125067235597758047460502009174155838276068707373104228513406434080903487814380073553460495420084916994694382524143190821496509337198909201516752451883480645936714847162324510496677192577813858745374707278570020248770539913693595681560872287304179127853208592878824880531807010527968199119832934090598207360166940857366210839828012423195451892668451797898558081757349318407100323207398987273298457028197425022836572166468362994820073547902790498781563315738305911000150617768537176836086884223730003436726495835924341824296310948475609273039888098543036289246158035111843567257841259303732509208806843563522223499467515263583680992276198075544987305654814729447674236085324926815823583056177437698975801657469053845892703282539671399557292709946122438036856162734837762772741018032281453152929945769105907518407038707814177204776944454480954551197954451736217608336780097543827043956199064929220392520033004540620246978822751450538999100005791665294629024797912661740845858667615694750588602623910174461222246161639472644229604387046953886193466756297358720304596208052441681356010009747543544171934736791855101555830685397905878946696980570678837739112930488416918187720848030668465702921098768570843374465652981151981728025024517999011284569152245836119186236113474177245319633958223269392728385291976215000065752764730590261367727960186329693363601129639976383535773825372256438262676873446121753426600783862540109871789462996346566093038292347435237627001404038571599195714770138081079435914210180284282204674719825257701302486606810780090205186713409935426288147672778496164561151559047063902317953569183701000036809928661048066321560830945235101143858478591742044539239601537045670851212434586963745058437519111583895837711094816952442127974357715148993521789709994896033934820456171153418470800071448593770792046661843135933421071761355567574853424300946676649116491052161608574249051680911257158159542305606074894724978608288686680599710748568845265685761304130375671723554213103311654044560749620562114370576503258790120881541983938215179670586301720985835243634005049283188380501317022359983665206418536803193005306088731386857874454460586201034110775159104187920092978761609707377843285987645781920435152806654482859209764507944443788220455053282166740800825102887442386832313246825163283865370201968546957002314320056989004383124542356832870870622225164206400376058110382632248968224622213646539192974232299021839640224890996446897087585047877597081407230588534157350595897371042487268330954273198496190340067151767422275928276478282223742107199356006493782537388136673396037152640764857271335806202777088737408590391197957631173828348545486564156681004271722507966366430769739280129784430842828051016801397460698021162072852895148261438939269654773769813422946869085577439116190030188472811968022360864568137167910279463715677491111275601939735384278377486277509769610830417344303638278498860520019696546472959782002209268727061193955271953312403109457867059384584288081167329925905194761426433519173124094540527267889439775522720315506953855677408449905877226828862585199538435281844245071087186103930097982842524120734866992547230964320149179404209198680003717781636951863489180921751967173411652725043385824542487607812139203728574219972953582678508389995945126555489389473389702594522202454995694282418305659689337616031227139737761077892725015108325436308658928961747316937642329836092443775100636448716629246722641704834439280105485494746634925398418213308900564444685772353834629667481921657782312243117607141395285339683414014090579897888686907280858096506161914697768353671644020661747763069316644840489880877883035630380288054738136464853650823479989133011771367435990378955557046908542742713628008100088450738761354594558266620170426607415110109322565504874940066818628776920809685194987881532312377974206494542266840079888008772535302470096843418025527952666601704766326685554641582654215378917903286478950064884827945275736068256346159166763205214935589476023094474125191788195361496575915977400201240518049444333345841129762239995260973948236391691723440889733680206124834816718721258755178032082829491721227643551244674186601063033707342367538034682196017303287875940223690144825169449248286576408973659103717926282737969018264443530050097039019051679989322410891128782116132910275961333291685549628813725645931240663403568974468101124373726351780982075312359321022092519392272380850919448618164367707301484665012760770664645643240505046535769461187175884956228607369332849213300160370141336855513983207007988682123642534605357391066835612178385803867862429867885956860707520648035758485371063643657080465601319674949866077947377485923827850234325222759118099507538589561432016856818300487124716675954183964697085952076864804361437881385088599512737646964414053804721015717947054372781214855797408276086416231483274195370525161584865245804572301646949176033051453629369666008067994493502634334377061103094635127871518902944045341712802384126771148520042229827540535344604797667817477456406565683696141206113669065215407410810395903678669997347611405346341252431142410580114291583351009794332988471756731179644567193685404904750481074591002647149846539252839356904570948043889372767690687982337376888083639757620033321856089699000473761324622165385745736082776978386217976788728877230502928640544915121456493903128360713565556481007720414504963765255413981545253519654773788325139184603516558514241799929663728245390719865189636477124159995888224616543778344716112370286213330799008067505348530510364337368199111668263140668093942478350051340833372498709878590939263790812850802511707290556145366537674672069921520103479748568642188586436178213368844227137475558292630745939196246083829096366635564021243633316911630168688468659043698036947463026785346022695349990508118154094381656157979529585653746953186084097646874420297624560488333423761922114172794922119307898362889729706357400462901443652651437427157986332074637161495877540476643504345494385938008087829027669305169280531307429416556655819801911621478335398269160289606224671651543412914143471434338879516631733081640320033120178265844541838779221284647711089100390275316334548050239345656893216053139406085323973695601535316702342565021856541465675618171897364938439436395850167374438202543813968932407522741391649287724200782059360081909996661389640094313132306247227886668688111331066122491837118588892080365310893866261975809569519450398888147358422300414419742900337310659539839707627775699589758588534189625547680886151615238804865702794582227973507987169283908262164285966689987428686157774104071238194652855222305020698626315471453800720906493516094676537862562747160169619195996329851608829294942653076262328066140864222330708910332969400286667229141904502259019796946366749913028737779642229677104156536051003750872223468914651321592308278581466558797531769754739387152540310471569479123001803020132795288826693542672460983092759782081958032034173504774097221430950634487717079837017118738520257399332675468442681125350932480000, - -683601215794970510934965704869125929054561899104780079443292100471754632610864881492386231242879566629636608508874165701528098504461608599945921097541486601381796360274525775029122159744805576556570492854301912069861547349233747096322196284730596885028002089662328725838465376655154808055115698678962476388056452112873473007565030702410784994182525726984623198539509463294825278989247742369645122728054745041608933437549669238798016677277571520329430703074982490349358394101968653703597988433609696144625860256125300981320506929624345984342121395755880948407618130335517053196338195508432204248060913058044972122789783002232703603404104142297081031297144502772652387433183428072008262911103431286242727587323804087710478731328038635612792706491583359735303437993136763723619242679081326377775459170305287596064501210457132069351953269184903141621755310400618169605375584390799207223873234522654531574266788482582647610655928548843460991985699407739530080999149384228248549913413927849768352005882517823014971917170235986839911847577003907187200043370531602878727981054631764018387500964370042933068005047192049204478962510571735092684027955603904634122237434970923872418790638343090207588717008224258854159208589284435039350787853090946669112628550802002005190945261667373857257575170290254652935145128582273282360494621926783585311146260355224797982668361896827641436124865362770773644474960374547542185913323220607898320035326777483649383134037514540431369121007240665569807962715609929897000988851130125965526045017606089181690294037868445360950101906463093233201031845691651609208133252346562717869008190559168614419135646262339126410207206260945869031988739372292713981501049768650702892230542124452678679099213574659622713309815956381775166636803971494029736456099485913592618709072197201041892783515094339434957924300990597838955465875329211780403610949412543582027079948541158624195331901255141771794351584183760345823588765446716642844858937596311396509477933932942348305900988294483754294717325075737639779765679858011175130838101482814359977891462116252562786575753817365668824345573213428268848476879502451103022378979281332960565537472701674506782688724142384087252085277796716000953582161330194790310751199907504733193602695701035174668595501704528284985799690999707592797276183061109598553354425831391311982226745175906983373192518497327246072497755116297698758241410581271998548844971150869907702763638036807198317949138554173925159281737553509915952757888447554504864281335075984804614697543106388718863060216309923808423367293905101032072408987861069567693187808731020965202718927339998672799714018378252206483852888825552424694518578916391218668053236091142679810752754498897310044427243171713389896286758822789803201045265360121732520686052435072396154341980967337852828861893219358781623263057094501647366831404243888221343449682386094869650511560608459277524690622825958402137170734501742685526323710915815040709685442437954952489761836431792723473726379075481970349613732224689790430615260495708137391230244980576714044788238337181203174792626083717874920262734823022218491193441014151359900479934491486701532828541860530292144034404953512783239606994289659405125521337780877978792037930830495053058415978766907733720420270247252337786222684546079227384663793399236042098844627657237159376662035286856303053007313549474567656267016657367299586089788402325767372274858717380043604943739546662394698397833790247208662814365055862569881254160687395794525296298410234142050993440211932763846903061175427258287005021832109504411060367461462475379925453576788226213400080706662755244560732508981333509466338854402277993301753804586125636403332421078035741862114009460261638980774398595158864739819209660384951144145086946057338973237156299638923394916902435045345375360483834508522121442566289837945629459432598559668401658501967207147895719603519614796717611214270392974401810810244322894175669879622336992509594835391485943732011274602555121316135525678959824813139000748835897669878109284400986602474603899301585533746412457492026269049024339150723993444520383152829067242739920771520943431604544155785188236601143915077462320012271361253663941332309871286687120292483365244209240293669745780939048385546825162853011745100425334626554360800191062796599100358596760844042256179760851523768878292921553471727223550503209141424292308448571588100410413979644807494463365561025761827196920660484906542531718796559611750179042144374502520800741354316994601312937396738030655644825614648925089672300914324171204502242664832972973559253879565776685332774790722021667012523426840607457974534643232957601669212690001091435615412544288879047814124294558965536205064456483610430489936212541160717113252107642078146745172783384397217645774866531905823712082649084385151118122225988536667851856578278845935967486880029080884121326564659793182299011990999063096507108752249069223678035161562910496399416510590149993893782942689754625754904272982079749444066670145990026926495588035415504589810357153514094895418003734817624073762836929533518715314805335016821278865108559863927281437343021065244221237081242656858786353281493021551267817848790741730420240705761593563583092392383734558460003135305454788361856454994288902029785882827934707312485657930125829581304191767099696054197886927638248854417574225918168531720937988490189291629315022370541283180777572215987979700643142870844868240653893962375925009738000127008469312205987914539071180746244964138915223775586994267963444597952681037942340901505870780794781685956956881954536537481180430196616563282199379741289777865281403234095865161143863979171812527925295013966267845384216888313735745808277280409719383410348575317167456897124243351967567471050795459274219912214397167006185974764476197748190217946242964172602020136117078685791600704988996914571251867855475533497127942650950238890882024723025660516693068263720955552204699105020605351183412355242763393187263340672288450640759687810041547294804375640722385940199827928489227201116392952258227119906620081162136720818739648789329008802216871912559054113126698885231531532568903962074984027808348484464064572535720957269120603962191488206589749372819666790882868139675418340622042805839492852525967415481286912328424190242595123026637550010522413826353668871161267810969074207925423645118145202221940772257266334229683446121514572397451940328243178401463602232717207326986702794808835779018725756069166227993900826562763237322081682472022658992437929694697206245085313203888615287145226478711707181358714207973879414477943416147332742358577063085238398757640901476897530433569936834434960117083985352559431541866176452835977721442660942443342923831020700391647830861489040299063682066535299852398831135141997665789578813105593577148033486267163591761612472483786918120906714209135496400454630142899989107233994937018315703407853370627391145259470893079979167996103034418494501253574105420006346298384303800647324239189362596619553472019783196370985218394158863326814937567769276492031061772013034065587239475208005473389521784683671151225688697133217005375649246113128953335994314700374222789044904775248084159676351603993854820932918016251546199560041373421103900764606711060452032716938538643774681483140876118661825100768101158706104062705349325273842171069012364699388089018292087553614400808541526423791246295581092459451055735340248147410875838199694304324720684236691870910180031890972134463065279871201161139628840156157602352292985286686157855398102639800688628855940567997439591341497667443271125731358972798845892671067912005380696567527752879033724743164170623675688454218948172773637005151156666124047749236176744944821673402130989363889314271061244204468004754190135470237136947269435485065098940822279767486017391097776097545889756387791755138251512994309311182437223031284597325538063376960388825742199155707994227466174754298923601283456602470265351405166617414577840315334592386068174203144041512901136625240108143101226516801653710505733626558584719800814643019578207877373620215654778862648930269423128072529739628643859515280758822052216527415889519365658860704217916843229170046330990557277291428134057866712402124368347425086522388510392019365261693727473325968870245158630770850943633749395456555312695507655463172095880303969119490561099817886482854414809594202627930921338973814902615085683527777295595709928433093247488001302771091206027767272479853866786104849161930233756490953924029123318898937585006941306880000, - -7220369946717906024152672794000339927507882833903634954152983594029631034013460279548080827363069693102463411620592223393564668661091645203663038358501821860259185379960208659536204149823911892105961067289894444106455473277683595465522955368846127118536335093477096690489374643619623863803563241981181181692380002621572171943921432882965510635770077137728139487706785667822295800569610868971932573672482511703613135143248832011621299123959953052076414631489776935177478033454331363033195841187225791889084020204238824794740130775228875093757007510946276762559578511479361104638624228972135099826284564074997633141225719982519788813277266840194507131730198949392006101545604760008142064892187434479941961476398122633278628364552278170024725586936946257728855823568384303458704302205380772922405794536058299181437822969800759599641855611532858037665400959097791334173159261462216159485750278029114049418953674007440279924060273967725719222049807599242600113547307745770933143578878336410200875436664627616746240596544544919756545975863137233232558984818960736054413646913465089212780487852696541455737223296929397418845441509053446828804958865713679768732404170595624135750418165704384795222966837232269172730898917984298687544332204312163967580412698208444610668631358684263260549816902964246538238101982614170023882054754748240289262780140779991264996407597320121050398814222672578459431115263743517766625916521616936767558679835055277958043849670043017054320710355826264683518820385776655444988467081260925933834367815864952081787101672129930467248238211620750487525880894027503892688344046574526248779848056390514904557732123825748783292845197442243598986605546468262883381724488165063609808194878593952702307744690955403533379816510342148786093550505065586617306186731890082393862679371462776315670442055419406396260593652266659222597763252492710129372918448296346794805827494744770666852171385972857834537821177401568565533264770654612457359610293328433703835504757742601308048339878370227659156029049824731772030036951633880693169037859994594870675099576293269838999566434986271762183482730804021952522079896358658956933294506559843148041798492901169583185091967074760496798871649613809471292481441808029447599023483429623365815253556771677777892656377778701869955275412630018055952780730308094423359122297768736443991255427022690291731188175469962371432888465133323460013055201947335596884177653430726570617175979578404375597607533255783943987591426081106050948339425339612094315913283868347452793783458511245156786417822041504209524009100724043848504432705672032228098594847916908104233580196940660223410062660541814581192316397523536068884938357041478562640744400357165003573508216617518926178657843206035529713238982933233876029136671653403878877211626772367703256464708633148769870297267386128494937208143912014020457753296474124391740891213902433918991098730781089258197712218231318185092262295206573948650581053486059394282825093463992965479116590452812665960572967987479154738593520096010749549167710517730092334711038197872256367522728253504189957668974822395274877957186973055778185759185659303246516846427252032719047458188643189520014013056491448481808224300101286177234370434015719556629217882496250355955056587002360741876093888772113151408827363799235674573763473178564067676153662115748148753343414082610454790032214059752850836011812401470155235430564742036599902065595080764334433727881724488085561014707771425278694129834149476022761011856389154108387070633537459907181934382081540413911132663556756020025257434727512675199776883638247855670845674776233298449708283810303063552244787762003249341340340196269475704282310821187892276547037950371586471753109023359545120498244895450176110658730402690845383006102180669774639289506746995742482039383893346520717719878233047359076957972908293081495437957606393083165592776742847370455832017856025736012213144138276879885338508429846526164144179652847141636358877483180248425275387565682804186437738206686592339211805675288969886630076132247145662314348973984899080283715794002676850906133081259469120276234733717884032328365907641379233899911210256894897669070258697944174155658481119145183511875923025220089830402336429370530070708015081278014041274789973938546238730111043915903849499403710679255954638733042453223890406336904129956232098721109985537536296190663500353430756945644769286276098511920821336464157705988609696524900229565409476413974545151023401955342536771126584042995130320950389225931613811570872291574972091705836462988849524109239761116192865260406721032275677588553261436749218300688708510323137596780887914184423877987595653144041727173719963895737030711054535912843588775568632999039611851374222208025952956259038398628505502143475669592915858210974462968037382654656134072992883736980119260992073099091917649014435720244642742004335636302908463367810721267953497128731444882348562907349965474076948457155764575555122599989115947813341795086874641921865622668636622461980048147194963595165895230072064847101575837250647238856572463556054851190718829945658518824400930390594499090356201804500889922505857817511551528930366004191940337788295260463698842440150070597232118153344355370013869718482675321742703725724119706684568835277376684058111394098534559002819741911600021386945131939835303179770875831810506740288873641024478583528787880720086383824911847415638512636494933698883437267539391771027751968874189656672348748465785913466048486068190167874477326101251166389107518812071543998660211987523670691565754486579185912367237751556988740549583328415152121903130589705448964834805754032086870064419469669068976232870438702891552171993522098035582628834289031576303257337594037221940480634406834502238910521611172142424532027367638777048544120807900760912430846671573186690798782152596213689934367827321230674847562411194224175480634943232108700845471201858321679712346316859839146572784881732378014818341915446943561915053171087287121006191393102177841558519641728948251862822693381122675352192169750575297361220521926480855080994634386433006641084511074226490438598776300769702037887346043074525088677599508228567642182047166238004574573177716770242745545030101685799163093925197125666937867089853729721956194599075440907463010502031616386370070145992860922998869785328235834584611745063073267422710562688406148682733093018448903966168870745320465341239975366037835628429207445305537392734040443510994441117272546772595866675109350817959491786230511225806822688006421732332209320470847690219532982257946692863918334110731978312691650585605470055689168099332638600042410325249322526337388327536619604666485244820055458684162463129103915441494493688119115649301595074916785042842304415264383886500781063994002478460661386821526875814102057967051611502793199559869001377214449320607632836115606999843306248507725359682556823587407379619825190216882411052678149510008905207851066855313503957059954111637399227575420807825467837408588213131260544728330379276929442134358475366631771015615664638429261857905530392433367055456340636813678693207644990143590202276347460934237708959594510474264949694757253964990761102325786682498242582005590946965665750640699221513132425775777247071378154294993266440783099642960640060348407986354790625406345885165554643540114288764367296927178673443767951598981030866278418221615592665683894745783900672067431540603910401216978374661522859728753174081781744741398842329646802277094489749207140725243383507311806706714616686828628019240919957811981607105414657217078384121579976972387888491432536940155413447274741512538614729830140585984416924742602319582982370184470205829119727630118768487178976074600488807892088459976074443593471536653926569469735609683590593647184911274582296968226106052027392481799612660004132191499790623072658094555041269706425994302854951767714100841181980375275293710963527269939394487599590934940673518715653966432182666057252905840705708403165606431421186667597790337523129122370079289834260583804291906676392939339677126613203679235818000920083937742286856134905420630036685409271498807575551615286093901370595498532677546399765900514912160004759944599235483088406530832594247580366124778497017982075116901485623060951604791206842075966458730274003909484009867628923091161220020323898043172248067020603340508811869718506761189021700368971593659263252737323929250936257402790104406264638964628513903536877517063128398036630532777170181533747491466041155415041948301351976960000, - 301624869832239288078835559461238998958241177854536435211235919681575351268044094660945574337171372265689909647369045132177616226043942955260262309791301349594926151139469111400267025180066086678597125890814679299590294942767903141171450669891399484901308551544180709628520692341478244875383349140138086018542297340975389401448351427463104035000434538536826290314315264155859171195343107981085429324831830141393547076487913112542064720309029705744356752963939315192274850325204167482714581641796226617528424987258121540103025774442771641750390412921204844948257985776707278607137599815075394674045508487876662973390276406902354666526273286134530615010214661750831240758884913818797563199325459785444214072753747357766936597192044352847994108962530613675955539841771324135292454882745596114010492534979081896745640471939602762223194258009791364326541484952011191748102907075199725026583498707292707448261423148463989224821923492810965702183086790056125216970993330278674314996729277082351930404351329554165434375073642072080359923472147358797716379165467181589451623022249861374961822223960280039667049299244899389635114622334411922450176519361115563513696385230469562280618812284412314067128263620207618597421040408695453879452257370273521486667631083401459557078917333187917689260224304319500549381233267921273920863605910979709040411100855059761514304505638306737947900344700093534448894014112456513700291202320612751602123059011632446067105259687297960811083233046914830835781348733862988473826126673704909789750004450238503845975963968494992718794084611957264321639603391859113003667537878086086056994563785183352273292115055884527834227836939567348316303849871037673926556590462975625793512205404407192175341161221277189735179963956097534631703072871833372906428922516197427545349767748616316151504476564199549840497723613007362196351324586977590839207062253368445915195667336947117756505315605508565274405586635391715177721728769320367498433077648011376965109547154011057234944557614215383367039262116592164558450697489647004074928965039551810547893190992378373618540461426638196039239661730459181556661143884268340837363626791470013747600710119561678167488749615369378851588954013913004491346209865250821710620906315026097811657527305699286545007710483168111609530627294821969078456086583830177586614209281050604376916147418140588756591856353389626422741063076359855118862129979454525602224972338709203700637062561471768913727301773688511243681440233484998518720809038966937038244323674519732871885300126324985117691356801859106483069528310778543568261482702738560530377306926118840260370542469525245987843123649822976361775801643803648878768852902316428286859561551046675253951425282073806087348341498484158982626974620009680484262612933375481327429024557019041151313857822731109001231138809312254558137419311841333901435294434399279427313122351897371831988284229625872804003546264430940940755032955868465239898349738462717319995578583772748800789354034932700844976706248105283731651894364915886441356613368209026091985111821652932405344828293253648542463074374382655473388998679272117016803665197019955879685178343606294561799673761110237380004949935518504381525763889205307887920528957653680476029928831804239540501408356406295741833736427141578810716176988792102559935734921704502472620345358492245763949912868751439205471772988942818738921847990253909290685998716049219030915954975003184289585989372736970666436375398802741400730229309231658758988101002808291213157790664270170271483164907569704435906761174496715007476833629660816705294388933005937876019320086320160090837019870565041071996661684191134002645964004135830621438401986450757160503495962684435817444970254216155941269687865631436902739952920427132991102005430922313053489260217117196829978319931851288950878302445058917583785293124494589262904819621613234528160631029794761621366822673648821655834518179396239729719318620877189765734547927488051290023391050878397836807375777699125638919291111732009959176327466580660649755389318854384188849663000783883270720443386755622973990509601759372668189867188684171333039259656484285573737966626198047917804305530499991459740596421852502891681769699707596721198649008738924657368839703621663578766607786537325513794437671854419599284140907396666261695841042428686206966699244542374799808463728550088814550599298420305392517663714846022253792647245461457030986611028378389731197938987875999162264577240743194408734277323041747693762621551335023839511710202293964202321590501795883931864670868298958224462192432420611199822133168751290604433398180134794398526459648324085184427032157251544803685298659794013766308818399937174023955114497907252987093168611462746049376741409209520425039525694941826759808325531735862947804955374973102507298755662679260138568141633273195835217127990398236360274811821290064166595802283530798063760698567655811376735031830385390693389278691604412529338323535601149960237307838210730012802723412410925526979140346117302204546360709985532681423668733074453043821756990539056898807331152197391217114541940038896154863281941344208830999369783699201787210871274308010886129980627605000413726371993269020617380855180999837652732333789277235479685042605748209103221601484452129135020503643436490287849870470544625166162784083717416327892967798747899585575196564110059232034953470136813573029592590510542049485048612433185651659774595351298866045228488194629091965880944737350372675178360975000952908197472194718057520300982901367556500332582347824326451671353533821968995275328140303536866772091104331750425423453557175028773629541246147532526363618600229473122994925367803614315886721341133231679252657495910967490093086163181706031084234577178290378598530970987897068436250283834089290557053311386067782171237056482761205516036098806391715280910884797828742754136034681774709149993529355525096732129314037122182840495016250418983649263168142332826380491529079418478566274235576278186109426917812719229318350902288545348162984702101430916601460742699283714154389619379025100131490815106537928343746202516418148461683762081644481106098736492570106895836156834721874214364367247158617675918777523751791048944909792374847459688667510441250122552956680731702194160092220250219609568360846339442375665726232563054461493440097515171395142422401303420769652907599043839030143190910306332860500383594630941368571237129654174311079725634916541731395584020589860349459699319951223539068702384298085941324111667429421721608625857579769091988426386969242158599332169471675606921143183582208265807143473051749673153887879427151805149258133325389560160409964150536240608688887038818363549589070543155694526118437090004200245103768257133520209166493204002436498906080572862111237008763040630139853189198325519531465677548281194889978198133311358659517918823662030061764065841520675895687942261399591617277056696242207041284986542445358097908100872051631783635157018905748727634872624216405725692983054276214529546855607097070859908861280933785174549538111145886003206002825129835992439347838644132135963139503314441959016055420300773887867314006481082038834135214578227880916496140068405867313696810784493333910258612154185014387151873373735390254687903920581964019154940895426547100755037478494659876517013944046738820097765324982697668660533468629779999020486254399316121710106258098495847657017509399489457988379225817257258421707098830138962207716810065742795184896080893100704953195742346749817627166529469783213747817179181002051226014652406299089519476531647794154134784358437936997651861202675800968466167017554686566198549440175292514082595791005749874996129101704474858326745358848786426001948281370793175922138179790968770516805235831335648078973736316438578493319912026781502074407453994540372799183631116733070825614518901376118101312333110325132659141935259733496975197703537473844543385808030270846991874170938962546022287858696695154758142663344827335120145800252057749982324371777563131703283858104337414661069086784593619822498780324479807818123527838297993890833126238742623616447776904344798776265235059488599495118844552353416225307777579661910133779793132795406496208259443587900078815967101043519548768625532148620297853199477096327829984200175861463187034544464292798961976612828270971933354153667962658421869377272325793141429906976399991982995934384505748930515596025928691081946338247514061432714221780400055889805095362326057146277124557651312640000, - 19755175196930717731480672848249293298552766106426948581890109156041041175841627167383877412182776255463353674835410620509993191422517471622770744955637782087604375505526869424438730086816383189667019448604631210637648872683832441416200045615904854709848224345801994271147503584338165339694967024336937009126288845849421504511914242380043526709084382884190247942881711948281508600298713427899649332880377289513644923396276705007061772614323329026755883261535399511091041485966623360818338333639340229789013417081229873669949453716795860427791432928207411432743596732486009437285079690783374897006374393710365098499392353082489493415307890798429072840801751243310208852743781417141262688468398041277024408014837608701044266822008057196023178664864761228761895628550881207938092055176849261155950758423194998179165164783189275066716220715241866554146795339139175880741221417503590407597812920878323932577984709324836905725106907051694949633829593839076173547056772671811897140255074764489329293039193838133103332523807574612250095486841087620490641626004655009122084215293550161488022625104323163615785542888625093122136276843474262624784680788368817177635551131845783966398526719202251893451341911411938493519290593102278046327329112075469504048287866704485253067427431802639026725397412330376677930861084127028200642105471550351273442428235298002605887608310967244758955938671429624060614034765053270159533351095087242474920361094905862645204373759413823935042940113991499005172376418600794030035201470114862687169867740185376426598063043311753706906662524557719327400558475982188025352881622852901174211266850064339249027960375460490765799273320494876517016578470877979247746834165658818582481367779772221378641206770983155585997401144954698610075638899178215125845934028973756322242149526049826153393697972596211313615952402335269179048595326617761421386205963597331890213592883244078055591057653469921545429663944094573648843554376108596315475788052644088827741577411400830438103580871048488088827237213160181829066851601100489864881197389191348776233741836108606123507993414452489484014683171910607225198577108771466516760324046054412957471174193418996574249574437479877270136833907805651363483583074842554699166454781341313647355772839553789378035687177442475361698975587756831998961062491061048296542397586924770588394702559987986465469381213879577260700163969951468310012066460610566810546238807509422890050381734203285924728326055438658345054709952025135438301033175614132606943909267531160620491661140069452731547202517717849462146625390909193061730272192522125932724333363223356527870903427718946599678396650815159548937723137318159488838686986992905923990913689737206729507067421565047484409356213462401380260390380414446579816854312334935161063501972094701142775486972004798318890261693385357156054002348645969600166107326736737793312306338328809363954887549959297494533200809001558645832102541696136381790775104072890585612228606756348862018266880946338462668989541373763396148225269247650385407016587615821623521421832381346212610411020536298775442602868944214611456692543027207187013785009847157507724320674811323406494149997735797308804906674828678877460779791889682471305570305085641975322688846143124668333250040078041307717626762934379824256616392062703029312401014099937677394951331886038158058375807083333143963952305941243818253572925724324867642821851483740460190021805966072667589793354031333765063934863911182500833468536640840859713870434895788856158047768015264689327115086605458053916257182895977840617675943622377922280347514392567934680051906547874497877226077591564495715439992896491680039380266231260118818767554210208760595684500980001771211594840121687429329377100293728288871284987291834617513821825577396539871188980989734065208083653405879549791330681253700731022485761580695997998282897305800633033590698839890872635429869722829557729950644817233256779474163960321919324698772352749404146502966078992976387475837611290419812153620248227503562059926840176724969523671701837707314672375095915932260933353856055004131098477083569761085830969103807358826377660040603101748645982753622035546567885289336647898981091164495066315725151029071774692454051830517237342793272182489022829224711418195308872150769804280195587957703744154780495763324870041689673058395715761188017818715683940786028113066223820486461915465128534985622750991049347492124445914351666473501671556559790287642881193247886731513606920407760754653463573346506680302116604125508429627300964409554992048666810249257215694487153173463263068814032160494797394310926285215709146034680059168674197077311936489349960467906270526694398614066354731285127386991203257912455626345040151673089065839979758337740659879247260743278761808704879437042838687797121234919255855192455807575174553233659968134778248132954804983760567008123921441229441874555753970706616167341003308347761571237275911292824567899682812225764611198573223869528774495203605496068336424557381284321120252526477803339585176880115183050437977176592501147426113189089532255842678273654705311727963466787930110469484090438152543018037268185001430311705002041775358670411181010851440528091549067679171225221274806336568386662180987032052987140437745527402975080293875570440957406373451659410552804290656660932087481551129312870920773447292831143244412818793413483827025349097041801019446072594594756165768047985687348013252498676186449914190408373172379388450801551276751913836740390090879171992895207910380683366850262711399081920164767448300995541924137988284564591066630183698253021055176741522845831495998962005603771819158682730389694329624890042955004648825251071303832447939097873883750289950329432548488604863504089173672049542160150337956278017957398573306431306610044647399683645350121337966361421512832179210870172267307458264884237619726580280306002746367959624900228866210509810506817538062755726494421636643101345674966852408101303225478752423341575685130960465388629917445520168721911890501227872202104411767645102622580800849085739952183814444445062638492883501223410785872017010951237542948603267226163887804844080311538009347727251842715300346789731249805962210724000117854777647693419714970160820850323133312529922249917135872696442245546770115283190963926143595498007452889527921332951725580111218521799890880559358772328502966235564305799213636945431367826030512616082497863816876809486171267414581094106540080115997075329725544299587044350434471027510006913471388461176360101548542549824633235269641038091077519833346962376296209904144899319481470007669291783896154410043859672879903026964882473299882740098063378503130835022410940923583573597431933632505325783829414936943592383354535060638489766796384470692393921737699293802293739264686382479477423943488177176882184403608456491210643087578243352099022280055285356123422006852546677227429925314241894588110769383722265122642847347492619650180780259765592757032256724984564804700730350467084706584567634550898751273555822322482552480701446673346494184658870062908073765094350766879103616892654895524927507921938756142403537917981035916792541530014710793059763835596047281669645115984718183314032588652689699556191208389242049784619058377749572551791890856585421581376685744466249215660170937141993238262401045320086783109918016492615366556370489440967417627642944404781359149494160722113524021876048109023223339410598806838982276056905718716740626425649581562562594353623690960166367060012511992768014665673171849407114457254969686437911981046094771222643130094229238198340913935102092835626892354872060005225078556508266364233027491955809123855469932509416548125628272655608370550519487926455569949819397582652346548267235978128331083734422233464664416463270345400188833288136164781179689540716002782115694523964064209139788035127553126572782596367066645204373169223050989808482483984875352216905717691822232918141363674629404238834108378289215756054813297736160851462817330722042400286358243537003407300911367582331940430842870983428734718830661071511117377822900040927091795651668418533011939586761836631329336881163381366428667968716575746569467947486191820729898187214822424001263034099028244886250861640685484168567128778601852529163932478519353539676750777767337127913440976651530698552218756120771139075534993294635958560426156417076594205426735180413776605372781918028557423480513474261686368297486452579287081668103870541182953062400000, - 593472960432603352009666258058573041544230047326328280069614626559785888000827919376249481884435029639600991630755135391453768673795862176051472113866008555528402530984176974682349677229855899396144785369269421478324855549048171399666654136494962839486801855735697514084241193381242908195399758597493571367786344883287607929323153754297531198624721565449175474426689659683776356019389368797823951104567788696563953302466061267234310245909732724372407567167877411219903334995050528806096179502370413572926045908351886077260972469446321996679806984124830853807325920780924652154240544042944198878932703043026860200567922550455844661546648328686001913754994843260478790170292620948599956277191616414184491281484848223695179554824294323795024920385670391772653230402028090476664868905228434951114283828375306370293324876110132734477681488349252847750094682197905824612546954923517036292352080540274044078784013235251468161970364173019892517757063608431287405202251595152913339960382641459527912711051774760257698042931167443730567677946533364451655470095073864017134351814501364119379924107130979467432852464131682710234345898456710644259843722603131155731805220541494065981340135767691378836276069127738625067633437311961811972395298029456196257255962898899590758021377441783248191552064976563273078363177983963253735967466827350509885048380026910248890341953580512263845550270249266007381246118603009788158664307074710468935148593128635275747262961053476424357312865462681856488997616802056631056860335714429831343635306411745588796179106660790246434293048913712859260986590517947262257020038392009336495799429185911474709493455578577187168056319104290156114875218083717540773760387978799348653447545809136434946368466096201604704916160306558577229628598345973457038534194808412067790136086972712195139152661119622273643300967911744830332420576865960699900508332560501704355257446032761008198011914162111189357652864231489540954339655903256293181168862846647662676131008153125833314352229782545249205236662641789896685151930889257895614282535440875046500608122263912403224464605888888523885667638711317126058632052521406748412916281287061313290959657367253488477067892108512386980990406042680066547482000975877898520602749204628241797948363362112896973494878813950768012568753485194824020252553877316942833604713742427226604092872463983455714902874564312278424717480058049901791026150438163631960833790336233290867421968463721355165831401490353342722643728756380473534733563032715754107748483776311097025735218584418137990122042017687466175347843097668543661318975396303104030679641004651334402109140358323357453920391642754396192487666109448553641256903919836188638328579943631262410179367116112739990869006584711106561886370363356656357627876226264580406017281375853759614663253452852346356633965297670527255331768087830991802434279104596621285210594964228320428320962044135721363458698520354379293185311461389638134428920540446936562736520778620936199658116515648150695760737319532504005991665721256043641103450005982777635096345363946188449785592641719842380611626268556805415039145887828810614725545571006781724003078447989668644224422275581136220664201732523908970070084542042795324663666225356170455545220724983639004495979348664353492771250245980446462278200227190012311531998179045018194922548289589625790977439300154943763970266834015172279097945116958675641711674754384813724509335373466083806707387422081759737364758429366895657519163726663676883041121700749284871909396331631299117472500985285055841241108277465926628107281074211635391345822406119807120773908598905895938667036221297102590029412638520091357801558633305109167927278905307812364349856109110104103054306550225392221972840782278891977128269357306417632075163735218562984301618550232150977884672662475957831410824792364631182879212561063388920176001137800077028674557255812275619491428616663906375570514454025839131162756097124497641830475703099099780656264752219396564368604070562487743596763233725127769394301304943850037067226582507670720644931512839048341617193940717291021769021508816661283435865142774081031116740555060066898417006931212368474000527564662299012483949418749710791172054550158795205301028877817565522972072537605501636934093444335597709292546524615299674437082917579229424668065614433740939447305726529464375142396202785897658563378859392473792479339034169800933128321215909463497855754552333621238372894037907350931183219215467348493774839418625860662774389122548812086329539525301353055977634947164423146870537682024570749753820541898730587979364571655562645648552372321771763164898964488424059573753481595407399595644505010000733872575686440468081049071896663479578222861326671799595764456938106615489758026068548295962190620826758845519962312176039940266856976490803927043776963581253365162445514002460929550942533632707564026865870406813981093814102272716077111172847018041759652910625017081229876988847523877340757058652343005618397255466784470409155868578414200872625203604687406795901623046586527716675905506040029403246373003293519061801033061553585727185925870802896462764128647673454478021458924026873498012185716634188865168913326592127654878393705565504455018740694769399800774553469382110206946005716500122716551937086623948520933411205021551016546123453179908408027132527086082565989931188224158138767903394013072544847733389988427839522282863852951980759362282255000035223549930632819181896651000025551416019608750183653084809946250803213282834765018423636695189475204774224227282934750879552729030544278761183922818491579728063251319259600396630077451864369492447343481464414567195648035797119364033293122540837481858409191616141024523055477877650830139887616625657138332041179813884867058380138133801367669096471683559136289363058114618189312088242688738277570277101836621330731952386698194970478643339224153530801926699110626960859330100925044263125030783895814359038075394623964771716696822653161917816504026347129532234295419880214289814553106112678876858670765132010593506209931872006601257898951095364451000112392278356774993641380971079004583484311204118223565192798278585184063385926637133663353082799212476807816737346528483635423442218037039527093545548704839764590639188106619234932674395693005012110683983876005796388056060834699939127345892665137623521547619619076839910395225558378608738035926967778680710780863887741493636381120296511038111212421028505665216271995226668563208334979802982357134408888447782705386181628020759819873756299003440649739602226751184317318725170077643819282785644631854986823424946612231526046106329062453674058548477425964953865118270991192806754684320672124370551507950814876781365855222181640517727330020154890064726494704931341370113079754149037052638780091627113486318125766174042379028460210682997751806389032160761225304607185777603483555618352352849797584747742449794773516476407691204234749188214997582752412270975528609058196664352162080431085276082205344986256402430139334053641112702080194757000918914648819018769870376319013310484146499049715482712345105620645188930353338402092414683204552530414267795520409156462582281488580542080466329076932154548656103722123276044991657294422882903661642434109860088999228483521709606248409362216130361069872362179843795334383229073786861752408491422374358069850659534233713329951956922136916981288192759758997086839284824670717295633625408962950884012842592846886558519330908735690040309802219175531569630979704925706921478801125305970852934283830029320131832130547345778440626158889195537037343106647301503572883877768368573591575777394215627991684368050580709765339957824009980844036437072526493584941068300589703688314160281372028906603269941644071828368467239650877701961341731083945002795191074180755226627327877873737459384800866277619111601072728622389625921615948523124868088110687181966082287159320781768475204298795634838640785596989566061659730710266177621913459651342365284964880366438866772341553778971956220361121415768853239238258581825989367658370652628503372188959267341685488445844534153457002974804323385055433589065914099008048005471578018071673118016592002915400398474604813527340005531604027317353418613355768965420047898200317757187611334899064462996069387045429818539599473130233425967280940916519999000341179076853019258565112857040120562549584908667544936522061470470601044304829643967879972116541058204334817280000, - 8662748986861037371214157935066508634020706806268332852890609511414247557073249978760595268786207939667790105246142046936253153266858954883442430052949421523585829757052142967744784803151055937018347818296651200479469445267677543335108985132747721982985500031189104537607193633388936161254591718355942903955476255857599992970033461612222167427116911503573707625371873172388831951636211614179397778791146438469049841161517429158351958441558858636133101221257975537528072139000179902615550270365698910373873546103316574854759368262468621152775320269531306865894477032272733921542877053552451620173194567562609774333854167742033173351727989196778752076648548371894640920287107017524008175498655541891487441985574798093201421220619496087659471280519338936699319343746135997986763181392378415520947036146989082757339537515461121091408770500627904195688460267016416739956577359802237177212142537616227789775538764969900517868401038500089436942131002911136067617778748526993670062987102165936423355609306204992069579989988171514571665142007887540087624534782347839210611211121031528740306836332866945573348570307479728849463619142697557575169403605372119488321232667417943490495000141062457063421231836210849740094997397242826822444679627298408354187390410355714090599310256274129382286132406398842847273274826477764280360242383957880528492246666911159361299596288843206549079920736743474481575722273641370443669429706386421051685385705173044861583931611430816153944121233935890338250618837512293699656628079730878011406639988245919029448774340623163365259227797431673793201198250873334075161421438196516918461381641712198668552212770531917562692513346438231122238223283155737596987224108712301300623330183888989548722560074054475764259995247440640559264283791389264290345416342329691824471009562509247558960782813773550620114561877579467172660737392926286579281963457430474789123945181776015497056943325722638923190530459769685705815696816048381091208707150463912726813133031964430771720090391434016771855421435269950321680212963689677387948214746878747908386983346653628559743717178520494415420500523484645125144429026041108638255461365580086170418904444152868087396303295652236072666263143190615866919610855848833155046678325830314368865916626231092894894945272466152234563456160271845324237537991617605167832627538279243897570106872870667206976589654542104030175835649421012519971865627212792867351242417119601991360379059961848810954075687411132139964050437248793532562678714383523280506654619465112702008654798755462867278810205536659515902850644493319986648001094160737442140282942958036276170073453128754521035057385935249464277454635042730397986789867874613931105535997691377996278651157282896237366326663106005453381368109430252574726212966284013318118900091952982346674497679892398553290268505915052411379756358972812919485596665030992918030383997205009178927673964386268710800469686482002547823110844268516528519910521395048729217218753657750770035785806927448477385045663273421099580038486900955826999571484537567078841966850233363035835537418157400141710755823073436572962599787411149363456324715245439136558313879403890449354130035148671633437857535516924819572697957539990101020058775333055268410929285915044385524087266620232864404985554150054189030224357502189353256758363829981367875242942872047733157287963783187974463545273047969858418458176047715627605984043566616691801621816387497848580367600591200284600326126288447269575604274766859250030290820989508215211024431942573088709723345499158588538312355114554533313253344023749036711992082886822521531978241043648835002076356416555917823734260636388787175728477028171749653086540252085814385366055610217127451938633723801529645633867032540371520213070619390979628763091090935110905339033626869877246867775160822483082429615020684090775073053754635086971876489492496975339761138081543186701550958359446062389493921287360806363761782095956876591954523379433569725951212593072515299482146479752831032195531867807825166926390433162484392526507782521112806090370170070202602068909514540380498932476699182114335833999902228313445971298440995178317216936840620313522479137955473277398114694317438753797897583876327641433221442552706087166217598589563086676198027018250763929262600914477376924339283607368356146409017753644212504653077361862874743712352109473844508691820985989819593181420874113319618490700945366981063592812619366341950561155509609643407484834358339523361750892106371625239931623414453033445289457735902993323177380008920330334570600520172181547236690346938463295010817418224430807478298399256038450391245815871197761800199263001367326865774834384094240917614058042087359134919163664020687619934473740471396646265025806525215278776222681151682026145682174142645028917775516362954861974443907874092759101639255740268185277949661807137970203739191702451347818841961725979812287588633300680917453464308486078288075450051232113614480937015003233092307944856337862827254642898780237532182256410257811275491068192832919086777802464146808630212539153749320489011613478775111799630358490613254091120872594775089218946989001893131511293024415075824266542905676288390917043039001919041512283625941814420737127285286297755061842785253679726695512528470563856938375044018280426311411133235314031061080345892180315915636445258407777330626204389850091090532329939564246462331811535479397693817915946179352951171100640280511252606490199609855393722801101918135028654431203502591550746172802970819582949647001148768733201236270123757416203716395547868961491953547584550662583098892100923798794147927987543563440263313383950558619180629047227619137330259849700653957622040313679360742780311498027588829139023452372817484579159997371647719088234341846997423812479591517110005441896099499998281998631886192730371022346488603446373375332256819860683208277497272121388592088643383770060807160026143853035378099353137254053917824915905821580045534815183197322669344024594311357780361253686947055745332118634434894018633508557834482363967799221303853018554638823381033800018893013763801519611042066855220920387832735466168181992233512572210340771553647649317353834269697989556438354498494276460631731799818006590379059569070037389742626461970254959294789490626439167212081869401899619823857601753567855671763051074690226051014240383545355598748094232825893013948491088699856760094798556968859080152026052612504375128935501330727576660002336351818665839703738187901314546426281578636527213406110885381084031433120817686206304148506128329307593788428759135318981792468996170147784860379794167155739575037267036579363155879785353664105695840324703458392058395250758349592833275795017284371327198401898079170135266876538172553931126263778218615987424577966029954017580530889276421642402623606719353629486467551388968456272172901465988033908600916356053944231255256882808948576318539025860771063313110916823742822697543038185882579465674671383332543424651970683461965783263226128412239564328563177767302119243638492508343738342059707108696616213161547778304734437145759581661994360455424813688994857601236968320483812271394259755433738699614359482966365364543173804926875184310457196048344146377613412916137242386756827308679982037379067654848577934446393987300351394465270329792950577705692097906655140373237614318361357278340930706821994348170525973568142249471443237986771983048425022808531137456313623807602171466725695750235241887101769527640171389412116909474132463585397526445926211702468034604815105123822840228641999977370824130161067912510661367671724312654133813635362269165213084622454665274690140323447987353925299244543012769695084852241813676743708338869346358912677879413471599741168022520114704071961548937268691605091630961180756506814904817899373232398190580919291274832928393666424873315853631173541676982928360805439177205018130812169907022035213804481328803473681241447794643337144566917976084442808193534405118720620684918701811367550713736720741904713706392246242537859168367796137742572978757478528667425592104545430065593436510778223481434125381509515788635837863655420403755834956967607921738525037326458069558856769527657485071233898808166206613796568634105880293866794556651904674049670381989605235065604776498238803643348361719853810466973832439956562553382821175199317257379392601172749410654869206505321429429733216718717580933679022080000, - -115030708925969517122366356494432014474527850408557685657209798413466850866866580931727480932937392268492202293144848450182733614188615042326389393100582471422933650466871496784977113947566104615809817348930664494330385902544422368529912598213721924624126700444075794981299282039524396016050910490136376272978210916665198443740277063430577570868794285516849864657432617369014943797209618369415266198222237323108541568874835895697959126006177080162051864411813879928943710818248133155192315989021699565552505793273716762328227408167010430776363610246393454291186723057122259875076470043561481283582864466556439662784268760860467165410913531510227347803802455259179271639433280275673758819444925012095382262523997194504881008287591850258275139302014748401589062027056316531662556037415997204983583913294922895608836780518222686687916608929771804944991974599127127413103739391732737943075731853924289066340066061486447468853715617739110377423338968104486355697199190230395339802747912137683541809380877407297587539095055350970355758315823564018844380393627280453238658001283670401336757492958362883007492606345992419954729004760735590200949977543736433233741350733087698128607197806469747613662152346750179201406774942706672873593867432001824993797147826453751451674582166861481272552946557729224600937374500026150605996825467229880803620052408914764303259486846884299977172779441511455056877667323959852339023228407458941969641069117474728682143818661504839740195340818043936818102081496436960566828013652768807057373074038636150857409703073986065569513423515180837998537433767887265825455431797506985280900929127054333067060670129158481595115174542409556500381226079419594155197910765559649955489475668337221479198040017583180538472057236599872029634866575592404546851972709192858585791167793085873832220180336383898475510587382775662531100915900037995505916486360225428506140648016411304183835838472337096212322719208605974280669383162395159558893094070314848989300658889896715414968498811144797253932205585162316154497220493360862854160738147374893995266593646756705209608572085706876630525759084915910937974797707805277421401363153466152418741769262551276388807490186784880373856764526237951607196981887180154642141611634837056026299668135878639447729212154353978606169354951636456142144687721601279535800333777047730341679514741093640162864547427982461347820679584071824863842360614259542978335664600336419241564961373482513843554376994851718030875246240592725442686298610163599868242109363706211374583003015497233139249280866270761568049607720434722667655861837429323419730054219892657703994329156209588836686368232421058232236927977157821095967693472463805826357082476350944505027216304088046558030778394317211855152459492566270071211620370317719003650264181971409330772624802815346454441004147622589370648531339742064968519450800821024807094213755951057296619045720150292208759333877310536389922951674195353548371443395329291563641480628112019701398260047323759783630941456116508915719276352848128075382231233605826892378263189196095851408684892524048991245713980324198695862436748303896477562022956165081531799853148769977667724906465103976148782987623439082793563905527940603716413781367054065482580176701423190418677100544165006366934874582840826710228783488291625781477905954836033877070365492839224731625934413244380946581488108716225179521989989860505903781382696123162634835248856980622751763215653160199293983361325140308391681039852796031356055613513803852375001920281104447537549698414758008983869581097143349936164283460458370742005955185493179766532515606866670810652354788418887877413675295800347297618729409123386736102590776250308158049530531932398465010586456285512498215622381630336277002653968250083388871421737863491732407710723230105879560348682174995362742209034539237752659644867954462851515577505491236967360809070465159844920468969785275703215531578905800467809562887357336364759076511436649655424128025411728861990311817353958193056675514573185672025429001442012673407945665079954317223622544210977798477203582659287327708907254579313002515608787248926663283534076962951788260286729214759117736101146278138272269470241897980895437622709332429400947101028411656179581635399559062864569350661612657895977900616027266067109886494453019241852820585321340552788653161181966526051374908027207463758371026138318066018665335866350221513833259228105794074266799575324136103401883927052640654336672214087698869998528486081122924477715860874717474127725273898652566522942461184812423534489197164079754544228098279521281320097469853391978912649567677605497208959459332676062120320233736410975135090825041506026874501526898997587165682667467698202747771765996297226373003564659465840220660869923942200144480734624128531864116972692291080398117738514177747561404887811809328762446025044621559393501577523760542510067327741465986661825589893158131232925947133150704787964509412296124948657774550932647657623445630598987867353319132885913211894569157417999685788923585736745734893243485735601933343805924670114221342933157253089962448471629184111846401154685753169186743685742052097683167227521995903544545128722893140444542317314446106487522314131252576243107515467722969115985091008815281843563216547030211850555491942989547616768637058285467910482571065806520532475812296766858867461197028749155807314013421891562911395764220486142226782210842481489257467668003341853084492366983066475464467024610604347743663878004900888857401726373965234088086110622710003088902175974602306955351448991291030007328118491871521573622846650102568428088759260212491334285350831619040030817008537273749135051827572711046929694270340025583161586338782623984029608496254850948996437708249016116334949191784619959229709162292933968317377337084866318495143348053286149118647225269862000804013520905470932524388412764446202078500874628553504437225048560973752199184606417802184319020117889465349636453755643580971014303330193633248815663436814387826630669894993598108177466099434251124481911088371283569083125347207084450825092152305373551148734861634744144484395359631433654591667486899943481560315249288994307202541268697391440464085414965682756517991738812864924261823419330429110073200439911929021150845369877725447740246220136154642893061900509835830131413696227754954318449442236159977369838205261668806561042479542005497926780592055348265891587869679259314142195958330428439700836887530824636650050546729090143872952312386606095641833800389291133500279469565112045534221621133210092128609831942898533341665706421390201202486789705452270033387738808788641681972779554606383670756180024372691540715335659075992057012767475598192879854367593981722274640170097864782718393763178101587769652441071541675906246794016565111021249524417835483282048051185647810817299970683703155720861074837328477052413936805402669050396570668363974817982722519392299941628953808791247688458167986277084858338989895818354047710358474097794731600283666778220969431632355465302832859400683858847580515274465833751035120432989001822540511799508709367104651852043745558282783534989498678077270455509065582767902806728309418080896336798896329174605716875074089265442528367243207634659766076384326197064795951100641969277424690817062116351530251744373610334706679741366002470830182978952701624318712820698909506611589818761640194890657425557002090418523470004394500677560500889510025751472273247626905750345216809991960027122463367344190566763374847480277689927604092784618638720399933022050983635145501737779447457973431424449967433131899008397014072386252151689430563485027867641099781769555395726431833146191156078973451169306186563021324736238730293700833032378515794242479620909771329335658123102697670449725797857047688226358502479383480785399224154105279545264510538166730077592450333908718959439300563281292842407063308937521324335488651148006168265542097428558304042598150820737065019588239931443693884003187620421777242353437080559877240749099308828523993648800567408951635099384535838859912452898206889675056693997093966614182638732412292229040418745306585451950257988004220153790382259381468949950196094064291063589460920575866136440384567655874389980208733190815289680934873293124310963674434979928604566180391469865711423787274841984346733658480019122199289236442433734274579347830426943472464633528320000, - -11149878269328452534846823811318532252673455088747212092359509628192662925534949114533847071147358289691204400995039875399701247329634723360312510166722190312795691575745112527674863491467918597815051049827341594987391963465847412206446743341674837092979712183638179474929787983886574717476993864033064309767586935675163436370528334223959060528945946457924934637628800946472269837385755922683734335014860954965765555672579188417828506394746645979171978173350678452571346744494366657873976296782199791457213204760120861383531693788911566985756891052622620258776136495019434806842494978012499785647738821625703093390566666188579858696172941096183803750230171141193753429311070659661150074529781214846369028345657931739563810336227134351253513875158963885828019388867885234796719703938120310382795989524301260993204969170658886582591709440153426184833491534649559966798215284921628002488437256579372205446016337871847614319650953583802215254620001773364095042710932668707011602292644427728793933444233145203961400621768965965673626660857497447190409307478472782008670527741773610248172257514728333720570613079324626591528044795464336836590025618069655869071057943268243975247815536615656791546444412095180921480043058502128668267837378076211898278183673127238836308279770695275876079915125366744908515628426731845074089932092126250762279011792373360330510397187259806771824309012430750583685848424369245186486225612075699404677169404089879190920378709136959038067182132743413908168140575075685604701633460518749064218391390616401760119173278969334864253756001398961481250259593296892766717262167101050608680942919877643727288697637009872480058988943704121424964163180534559836360471383659477255521758995861715597748713054066579111739757965639307936467340038311652055065589332926091046023012269979547485391973319749220598030138460824765559950083855125941289378360440971129876055695925299675213136403884278865147255626643370002904019215250236206702262485222488333243792209033973605932231053092570151740902510130905324153780547707146733362083984264333204103501569959612257702398115172244451534330262628594611331952449556771821606097883036376846636816450696648850778787473023952358783859621379179479139930099119532843559615408740385036841319386605588116809159957501919583110011902889070826914610407349753718123170674300466553605907097896634412253958034914523961637919006094364893628190447165351566101641557060853075099085956875855373126585463966977073272374619689079755402736852563933406781481627692976214480439586213883638651903260692890766152593484169532424101146740230255995133273310322639845059125517387556147258698242847460275192505771004204629617120861916258589485841200800859723530283450815371224890054164427249712237578076201527203766663294415997061684663632596487985771573771902237227651954266547903714805783038373636731864166206715548902095245120874445098495841549007361089925575328526073690327581289328247096677148217827161703812800390893952563046921123440822920649265128119309621534467695363202502305701058049303435883277782530590014101252910795733960994507555002059492373164364386660828692865985851888450164281969914939624744008128838770864673210073712706294911625417629363961299239884349344424950407299605488967885601149997195079398170371360767766742226853933051341853618002277262678979619127304099527006197869531413682751530615811484824573652714496090906154576571463858687628996792526416544064521478296758526265051803199349543079026891374733127544688579987195074350902103885321453000064378462094026027126139278952771434358586639232109538466305390137964725672594767209408786692085493651257515485154006838832266656202680874610876064201860008134303404130003994712342330652941625126578406583064521396127915076866728371322475973291640646361768085080342182243278744017007482973442704288642466440585760794377210554373947928734600247774790893703664682515771390765436855805070780150289202621688848997724231998069367008861927676956984072060346797528899923476156226292963570895938614138752969655879796098014308784600251039077762240882359620741605866326393951449472751789122901193297560885699981335854995927765303410279035615768515797876871434125584705598085975581839238884619137510551206795963651432514395018923171848023116192774585876087677243560749160392423450957033093948662200067218869751056612007907116381946389322490986197683371883204638550266363410115354540132680661879896664694027041241512214087533583287192129833721228078483921817133622090046964939142489768594870463016100548711799276825166266037003996554301993754048357097990558486831839196284550148886726057837034568772808065863825509544945787593715073824563525808986446004079515676174529884365096002560734344976409904123754599606044683820712334039880147930449376315228538407241008545711421197066219500499633697824950377885647339393600561954688193877929115328808467385528413531405920056098864868958402906033034644754633671538482728468801187583370769766547477596122652267734880289273184512183586504303370630701099974623121354716078355140639374794827276625628016960263820548664911219037439198621278169762095886336090102614461566767485706576331049425214974950792608283274170651348630499693118062925490633198346251625741618441403254611025968333486428413144997711658584178442743042679664855038160821682317826914919614742639685938132928734885509673849677807889649518371685324257294677144631507499158180506199832449754126411721961238683314393911074331073885029376310383986191048446255029918527059264586024897728366987323598182492294784145947019423166692661600697123517194287210017937345747238581847823968984374429290101640443928589296295341362797461910898874747817904699933457080630395147980170089551887300590736917042807385893584854171737568850867677976256743170034983471983900326624360408572717641787948800504672762933837201260855109332278346955112725862977557330621476632120247430642669175831300697942749786003172445584246685072662493921171981548856579086145046745953559167015870902975686249098276526286103811911035918573407530651988886968255796289977787496738038409765231317957430568338198456880243455075670256225709342411066740060507361307719456235552587338784114402018284075712230548339567829597392162788919710275878143960537449711284015220862818616112652234350261575708020085865686420549884890761772011317075307503009940678140389919724371463666911828443010091400067957322685468834637119578247599396976461862148927428651090362978469169077989850831357153872227669522370322620297850792601121912534315605542125103584692966842883096472132546409977205223430248935189156202149120020506388261415043995190813825485171896232526198218852293076292540568596665397558643401613311159937686797181356355557757087786558575853342499934437867920158463046268382967003113065665460113761207306871355566718500854173855889710681085635495585319067883361623638108395772652278379541137994942650860321601366794673453949542554765085968103486899894287473824616787922805883882783592008498465633007551405642344336971099282146751348058072002996051400205756024273315473466436392722845633347395349730674196217074254781679378318747684256576695298975384444887721503721220047898048361701037083935583101779931993827490227284022755852665812956390520650900833793939000274133363327814692640508658691254700338703285198238136162439127405267673406631304202973524816645986197592700134135070147766955862056287197631059443646908211329053960206170345928703977653304721936173826361626896778787476514030648197362824022872091734258344264148166482355153758658306739692685748056878053382847086989769625438437671010591165335565465500259924276772747180007594457961574169240093662084562153289117268698278961179207537715087431427107594883042405805573110103055019598047797171702356770943066893616151828389888689164070359732144514435390851962764812502199096561267808181144117832272262625331169240797894098346068853288495910831004105961212546654043517893401931074409969749949998834972123314498579693509304644414138011361124138946167813065513379579458434193505166508609423344269280076746184849236822192700829740870822183193297915719366389665863412197501130724182212914108988211644168387137440780593259715273277863859978366582874113232457338909651749017631309069183973593887066693074694431024320591167334571506504091967894036388051811185745761403890613320941568000000, - -347542778378089621863112340279441515701964186905408897891029388445583681458736858027711979662300561939882107742569644562242531856687149952018762106329982858197615721088871341544924951722392083154936486958364780156301067012360315888553735673932296339807370476980870110695027257552123187190298849476150152918471478473391721544725835334595339567254601004391480747687570841997736002160300857123130007851288015429830830753148587524999236803239208431966461352323611260288220348565104926846797600871792067646775709897164283800707718191064613079316953473956170929197946372297360124014987093306551593647814150883916953228589730715335385494185027970855988406419269198414867780337477287122865062136422065705233065211450037026334709810285638866903455686958993521607843010180351873966691237706264193475422761545165450175891178877005867033376619271227422978614447997468726051845912567407348591639421017158397022422675541539487037428363479049616691223575329583288759413432617253874519044443876144465827891716828869383305422770640548606289307524901511923726138224723340258544605752008214914105520834200151790562097723960606782812150492479551143978172687669692597469664739092824741875339019372954234138857091605526741024806084939517729679369641890368928158225271568597784929461696537693338781716082079083982129994893763530801500571484531962389229157280047866735045803828860907142242908193803524494177783858116952701590909210561483279406918318131503647311679040094773127798676632274534563335246049785469457027529444106781850374433205096308011579616119517629705522669459169301153103833569673604499082124987100916757564383648947103471512757705047306419394572468726044649558878661405691021719464383910905547405086443720961455470432371600186909217202441183225264025158383753319189992837080511582853083748447078007009951948906163527302986139083331109779322838860651439923354338551647448784081422602117166714374592074658051552715077610039085484154889990733077743487307917011839333543696939495430836377620252723475949794904324656632881741828626363316097272180560909156152484874861214584656461854569439711187789451784906370506887290142272298894688836648238600635681306285684598150471877761522023927166650629682949617644689276385463331380908770845141616367841636354651599297811733509793683141788959550409879377352117396431445940341082435640971185820226458537695687131968398632319704703849187537619154782046300289255517354215255560607957808687421586767540020128953072767754342071940607592512392952304982202096238485318210378109273531985719382249757567071517343303667223321781341859054007738088820462543673591859183151438141433692085095414109481299560833739872244203990521583699531993027638083621089818805249564596581656296519325819575270844479252804466143563907647549165719790336200705295111630159521298756384658870155243634999675713165936982489121065519577996705816430580350435480217414799378381784256615752251597148810213559035530408937338204145468997887707375842501255234749506453414204814780061444300470524840704584668149759875840870645213289546045115606663545189367734478770481545574828597220648174213775925006663784702925227334529487313023402470154237845533316493712955828769110657368365380279975813566681705156446279795199841824548151374749885084851888632590864490140140390241717369989499444371889419350952305625565342440005235560577520881514086193591909846773690364634228469795241288394161029997211845143671902302080878370180335228796016136282520215711744869878887274686974584085470983803685301540945409171891051476363430261197287927616278306518159770006972739759342863563971726216201051292315824851632760411312941604171496590344813570646723479635844523992610203552893083422887306148826115059196033868837819490128075810931889367819945154808992279731325624958452185512970415171451658892639577271056174866689495287211683561370562595939625575243187045387751808441928814067894500296168362882441199636503848200420913867708912059661249147988771722590677843128623481055752151964255455895205904471351285907007971077162686689106035599566757178395250433478235649006410343225059559964953301432187832296027663237469499684967182803714442005918035620702392030222600521426034028618632516344587606407120032761742800522689103171451761932566373818892894399304445425006922283009424176206231346452545827312550527607537069186354156028769314574292437069224830727604044112190910916375214863828032397730102501081631542276110992610782245919747612117358456647434103023737937788116452964290241417501063907390847634195323377653570177478422576320946448640402216238573419053946498622894367953461047486477998625839881807501021885811242791555718612489051593852038909668642087916095730639092188426894234359959716980586721861821147357612036332365952798032856604046607524146590286407794957934025636868075541219481105011380406806353864877213131597647891036854856474208154872632475078255886706328256179568393135621685792727498902424387601105281154627222876075571555627548722282445686720127315253481507468406660088377952210646066045833900231245652869906267132944875726078295017664933661922989539505077550802967164300988495912132734550790137800057935360445150594370455859955018229697670475470703291441183823742812865501869700756975307107631114128145658357390098570629940951356966505375689858119566070715976235499991962156958694151348738859285336459781447078122722070764636597265337041762454537356291251225652339471439481019855340836116032325557147114859398569685438450625664432123309162158092479915452640845841891915581893299683654279198900414444620703388515966260924757437743070804887908384811782421585392005402559578488246959097858036856411533403197092861208267287882613912298523292793582938111545342388080898408013670452106569528661927003745065428631357312300959395562089794766619523297084531579693798877738438799284756334478076258609358679145126405921963317239584256195773894247495030812373249055457032612609071789686236548635748225347691482256566377722189815043307110178330967404912527167184056757302882080103161361495186202654476868132561425464262668988838876646332887194564310640165775478656180896484921524530768325093480184612109651244619769976939479964864135054520202715609023025342166644379065351057367249841173886752093637859013826790911725899761906854724062163375660648263950081740492069730436286191726566269532343503873632276078490551751463057323023043028140989926334930401727277772408798610490424491993422888120778501448805266515479129072699838647688441395386177827029500750706782467660498335938352338872647250883023980311301368320506065344468228892495200746215741096496161206505989933790769915911949276609016039708981392528018047945776530219158695880262492085259144808722743168605028003347286117206420897318679820477255076405222152632865908736636789878794329449281901091201717417894423647633706410302568219521578275403605328108303621064030692317299096158157215591951684124253761988877367134616042617417102681098970620083915574097209605515630449046563185657580084515215317964986105926066254857994181908978532720731242138508828924620100628910848508521413438694352802335517330840877608604122283809171332664151902063851959429836319692124018027923663300759033012740550768019177080042352500283192031110309240165292260915190511293150587175962529409535922269090990808836409035624223511081500145136327447368195184051826153826819717350384015867567787877780584364412985526316519613445820798852751352821402103915474413796535211457385135965616029468128082361320141813802386564455707388375682837987718845067710449476321465602637228518031712591856099113942220258886544357234211659892930941892534715073629028657730285436835174316731325550187724424544735941660887391291171643116305905776639157283426715379479428713577608853900174493369636434534122424611654266889627562122365791499765491263059480036158046796974311203845873958900496496811933118547876643735510306922527363552683608638309098406323059031198037465007088519662347570294797671103111562348053649131691671259345341419210060325754145539918950041435676827981612311149908269838526385962548250545817945588430936208922758177818851286511229464558173301022040970647637125489186164769654729725624942457287961545678604050707606366440698931742575672769148283599862937730055688339328641910801070222832270191529592549496387752908488873953198080000, - -5269514732666670541891826471166637194681239308721266759918464522294693796137855505208613868351013607645651540661677641118444658863654884854651768524324870044264227703769619629799099348557205110735506961704900896957429543498465050254373296963082603169175692391047441486647017595246200898122754806197666985065721021977847519342745639825247504196641421366861497792580425996954499356906116091018738585699919075191287760359007585371770119370130230171982491087273327305795146613843536422588686771771522984907265305191030685231864702384138692683111151767746747777738397935494834909148755929811251495406920966077212365184745682322001724868915399671738163819721815626320953482608805698940471595871102952423604085921130570603333624757666713132727438146708141999116293968107152340388036226560547834980497617607258252286787468335321857184746723639777497797065769948096645598767850933676727897612935326098505230794996961925351522970711256218035077557559116545275514070317715496817074240287497677951303558396040279091977234324570044880756995043519157897921467031627274557576541184948275472957485775044957270255221596495258666709163421296789631432295798088334230620942078244607090882454568399616917812498213994120132984881115653292738804806025309920993635006958849127597545484167626674962114972086886300789899789331960423016121678134150897865549937169247001263749553369935143510191026836416888527550529357125846153817510075148926928262114230980218193362478490164703951980128612413130610616013128476299687116890848938321494531622903414847298435312533472297287572824407002639020946885722666142657469675865398522443940070272419233744409204187659654326015342289936339629651506362956989598691822486893618135417877214698730512699200482456676039185888757628148530733815337513388626319772095348003611943044590174442257870367180150386352221048279534697275768096385006407476112079116808758814969812775863201357384496658386007279553181575450673006011040837412700560400034913895271911359119728324561968882712094299845629151902893033021534560052770493775487890799034492194021136015163425443406552064525297472068409008498716374849532033083231157826343319306155111142902170926472859256244171478680289102320052629986675174972119192187177215736817166091623487288878704624535324038267865677319807104042952428719249417097286805777301337055740647776251862056177472178533857382491796081846355330089748706121755291964263153633656294877028578503612363236117905350430351023852540699206699348926768477402886976706228203438949606673384400724776519898778310966693788066296268030590591037946153452277908665811142711257923463502516130975549303889708141298102625891264081053487843160404911373277631534357516289998499635646951145157097606688118734816902729385260879196844629468704242991125653710073101154104284269881384543452695867666914735793596287896082890456197885722428021792455993803908607847868145490172947454012632141652538754767433672078563317787465532073713120980594598719610843521525292161805152145523407556898783166032227217248385307049830538814466297683218694400245646827508422456439902467145533731208527288087503279183506627601760281788667919036376936239134167996199737750691453693434801933453674987116188994036837698034497765837329370946462418758083646426344827967595813045702943536857420120570904955195014357021662939198874999087045813042277949297108047578574764308557069527230953813237902722715631658324140749095236272568874661171678121608023384121324380383968863389239078336236418141188677464210127791838016140531121491984195683925961292733435724654497781462366413400172105852077455538805929840825292767057273275011754863796412015919149193015606985893061442114138136009395733792654443971363581245444109717564863286375271392758275787981225035526302703229709018009799925482632103050894936754327341311589689125372169159024515677060401543564421430676205808865203638230377700510373846677731489495560699607542696390284734982610716870343218064134813386254040578898112577929189564072593367165668978341919909967254615061023818769881717807384352830002668380793901759216133380642997406382364309275066666888968259976692509200137716699609617118397470254695269771415363747007355774127392787231902342009743560549867778959147341047487060613831379953693400139874946465456239657870611633115988717752285558133558221365479306737127458607242454567740570213019843089512609366069537108520432978454750770785161275913360608200070251557437808171844605173429821619330255020410164185653520793584618582616650328151507742288437941135389528144001842287213311672844735184245670900811446746931596414484828414201832772642850814947398294589425138488805219609031142219043150447913006792106568306618771604227788268021662444821720540628682199568271862745942640272114725430580811097299268545968136466637838797971503197179173258335249044528488168952135421202599389360489054697939896951611745997519758405628161919641490862549314057108413976820229901969742840909291970270080622635954077171243845802761813367511322145372251983546272529988200702489427730893507353747626235462158234138400466224769392661513048355343275050278951874770234500075850162308119621203173246644905412886570138929253065551547949788373613717951486905163701822403855286715798766365247473483168291396785149227629800775014465976016051635229102119161744586413187359464638568372142496037770529916342659931257048976812794279686024469555684798511593182733546249473913319622171064248723091328123203172605570261371777021415890845419220334593671834349916237327618976228036351611382019361911833263063595595902245825098771976321897456709554866131843335041324394887973648298368799416454462064885469585116543190435505884568300522044584936878353958500293345966339420108030490801567648038878685435970882385985366255779343155629209127335981097937137264428115146049800735745815967919391306041474560095637490108045825789312932038265616097930831779040261510720109341728347983424395970148109784055487880337065754395451633697157950100244664198707364365357329356553344049385054866213154676394503790569838039199092898757241049629099312942483025178437479595352870639594794029910402428671911935313764720614493936615227442238726890830987869154977142584964023343991367685775548712368096562717166926101941141799060320233032350024464346887265461301407225979911226529714181050143273435390545876107925094507177797628750136838495603143976433166403209068553315260320971954071084388819018363230081413236020701254226039842552449127026789636548853558649982162299275198366574105834324910989751302067398908964080460301356259601723169229930497546709974361668832355666715145912119221652048324726435051946653584239315667993132306545857614090092576081076263242653378641012648559630840585630049269043913787975610433897449185722655135437308777929941399375033536843673479351570753896527035025719800695044095278902167605827340018837639695467764533075187117148010632946879577095591898846845848954389290516582486769265080090983347933462920887316632126634811603989559465284693103862850810516782098122008312472845642710683825824910769810316756658981396777794828584085949177310306397410262925993922192808002039246043014514993784202869028291920021716802025483329760161707108304639005563735492016639283933243214977985475056601899319294589060959014531689424969555790976740822095307771058247273436017844269392717529839637144864357266622001563916484840823827759807057202525221805688804424015068207371738982113772188804952858346535170828652883585972521766229542726553181094594901267913664892392167542272278618569744846239220719436710548962100684796768145955387153334428622652335849129660168654768421788939634381459947317200444465804384205943168284947016767406010404952735973047998395111382575106310639051528216942256849282979561073927022622849298414453746909140452656438820484711139556019626765342736006407688226966519666081532939996808951830273365447331663922338254287382584470557464325987909177917199835846453738541726882958313802777348427135706657609270537006539692165263511703338219465368782229478788214387322744360366404349009134082696813846078593537544839800514799746235528870613473273518955243556557096629115086074894455017003196526429940063216183044472637229322665324311026301009171611342524730065359989117276768822763238680458869528060611584621281280000, - 41440493816150306783520549377211050262025593242023484674176933541307817677013627957331576003468431931986436806332645157855170535601409650872037397504397271311039765559620933963199395773714417636991039515339070838761886356536639822632619509281170927810264951920802964334674944457714457902298003742627140483282795750427280299753590280091881689464978886051266445722016754426410584529738976750019119800413471808139486670777630131278235648134327802027283662428827952566031999115697158058454063637034673966055314290572734516869804651900895216023021845333400451166486741874712094159511542224786395925454146723016906172152701109203994705984634096671719931879351945224357104814478576048513335783786744762478916362588608821884768201515946130434703572994318912730814611719708288535470460620150494790317206833940090522094898688840232275951536767241500526559528445627505221861945361563662778727149577884613582186342104774537841697360441638644689521653219790426304112460450554822245243876279887199564053300704223379342985115923019959414631499679754468893681646145571299147845893722089174975576257922143760441787495263452976818363591160970734606098466651839644112797809986819311004551429726008070507796925757674907411891360142850966240251028390316157638280225245047748294492201904503484073828709099553562168644648175475558047331861261674365556198105762807131256185138387249151447710289095767258433432482241022535251185907409247546679319323596865244552737703945571518463358538639865916318674270724786495636852191408854970073176619501677221001226432383063114180130427334178420041782160449895785595042180820393204050652787508063546832773874618243900240392663343131554457369327904407784083172610337100237977372736791620297371410891265986105356311738356247232169294856800912877406850045604727689685277959310869844187517514839342820687261488403741319155247685108969911073204197802493211838285271685771977348680545683951903552313565262808819638835915026859618628799250536678354111563029005648373279207028302634091740248228811470295674290706532783916623995757435337056036135067179241409627844878625294994702177797071516240545182360802744289811202218467845448912409859500016908744088840524317406248939183354440852549603780707920725368277512292993344170251061374063950232569027064709061811427026504704444649575352002090926628614055163550869644103553235596686100792881098788157315717050259401374666509843047390886123306868209725354019990283055228993907105568647532329626020056036766196590128375190046060145567692568877636530420351094871548472087287351139124149980789922687660746371526576456496119202079733707198747660247957593011572859303865090346970919816498747856961905812237650008366864024889554118500166331208602760379109265038815557988059110911438831604303753459782856668642807562510684622093258133435212561932041431537321830675354752177863186642417503341386979955966909804397311717975840874696358067623232787058235618099938708385867845779840959388233772259770183085963368838618198207747623797833799238127179046806305615193251238642412999372454519709647854226992681099512390214966518145832015620577430270977420999783722408916927384620100652276933549977473863069803560285328036202355965388979036770340190454784299383784720135753037328302718473038942291890577405300285799590787300745207323303409296554993134668673844434260526326085734399028012667809409224449623085267313171431567529221210563165881837012409094300394676290146496037896711774229791677331383017441258575256602104125901656522790515449440102289285512631387398861222507058564392932754591956421003567395132269159405601074049404968450501254664598714296467229846567301913923920910383599905280955832456323668001796560858312464120416911717248051066789784484647286452167020800459875450980619603470884825599145540921436638456505129980049859870539781746864039431270814874922082446980307822820210620961984448641449410938919284704005836124208704647082018924931310211210143580654972520735643294028892583258939849581689606344993705971806720981445281095577928346745181365391852640376368484306258733446300962730663029219134897297289216890746160444701602507708256855217170491593978573933345044699405566999474856678508702986043876220267440398999299483550502048399783567364442081716319225565177657165587304674606717136346843474489623556983419607563296248607962073703501145663165270446162120108650979901044139257560262115615736741000967604728471752391345859659891627081411849292409743147592523703325710923699729119673635533504428500645945194932366344525378909202320835025447557621578814122606011042671331133474920503686614061843216047954023267738554907995265264125790423477845330317257771154519960043105627231442107214606188657381365035540390263093719175167772322476172106605885278615085006552084297060898729376394077973394864952055983732142285479689523270832950240349279452066797728169070176739231031606206065382447196574219537842077572850088448930516085328966316268112120335413607942768815600664398698976531607959837733982490845639432882568337130707442195760684855575527112471896844126335462142235261872604469311960837114636972645085876404414773368068064437876817611550514263941839305383592586053829453027599671745826687420391609892605676356836168000748558266172837041077874561951853685533771465135894773889829126245195698302604012311451482721590551621666689139046305960582676274995266274678389335155079433649123043637040013890497833280468019816012416164647295950475431229356517844468843139825988809157242512724530303273857307282076044696838116580846215816025337117625624856274088433223559118290269969748764771391060319464859327586782934297251324454004525443200715709196651632826351211884244287121747077996551969910846598903212359997857386978003576189853407897326944450844712701393986267502826328080874626818820803585594970105044218991047753704696964586622875572739011897614741852040907300362643351017165344077237731706302082845828596557690675431690996204307652412822520056019048847948348419782859114550122630054446863141451791489365479232401035791477730961402121419947903066703946747958968466904118636859397150847890891444241577053688091043835571012107668267716718811091903756548520295858614450897682293204193778328578152297916791770705153354221615141296091039681729153216699879668900772191058478806444785921370822805715359389469583542470450427966010048537542014224404217177358255327122219715515815212797274177004216133835431310052249656839428714716544273466464805633061495170098721658303832601591740455805420481092168343999159342106507122078704071767913953057138659964696177484212449123852836032838285072119582070922416300961857516155038195788316854477422885799300550523064372217993873317818039960342932986361858411528519582484519871689269377550527494201892826805363687378974300936484452576920127816952282102886999715610809649518496134416295270500307219901778620190991807193586331816982861382814618720060805278817623909925583971795617665848064639652713839600119545629541103408244992604798300596339827884973103835958412384445331415037356108406185882614670006868804110349840897573075976005945251567202124009657509871967965378259168577313704571021828557677561023816622072164580089439522163060982634536034463880997012570888883740809975208833898545961781359348665093334403135249498427431431989528834458818390184178168786557922846750638686139316165712424931616339926567378115064481810624157409625644620144805331535998613124176448814638623053457166140782618245194326971344151267239787420651705470341729828005721690344138404179811171660193356880610636427269884274614768459000931347582998577107678051073340089402670003217050522892606253464961376444314598907767468680591105270705899067928881685741456928885973149997412661076250232874378293343082433582095236894036052084068099355211161901162391593582107966503335400642167665080924743189978778593620266593531596685187567277872170550829226268661489850172322024770080058871317521321199327184869019104124110507175802881175499566665788801425470874583702166885516372812011618808964334619976742537225256916713113409570731976134305875166207074961808627483176072780698884086951184844648847193826645761718729275899515765160840323763359484246143814585033091898647128951770834927361288129450851016847255631095214102282240000, - 4919973573603902976343095780502470675128459455265259707424669466992991121737569478388969099235442487469423316466615909426047900280139582487035457545916421842121728491092056808537482881564931397851799950498939759202913347295866172314166092932205730624028881301451361379896606911222276547907490525160852179947977911416811505366288524888584594348257225747472219475295460467994590947725635684643860517360809183648261847918681662659029849562890902658855623855247262309520876437936608416052140582593611898723084483456764757045592384378348583870450233083277270741330118943205643494844709152191393098448680070134409274119896791143024477732596721967234665831998911554365266544457109556569861634421286613760882019147570060258855568154101723505823851350453884776560655294918228600016410679519506612549710428432072246926360682744653093749897374046970628062418347270196787143100349756482640975682589860370086281162463591665430845301473291043253462153484830336940976761244860875943716825020756693674919074423905772710725406959069666370851843354552415354318170421120647011875360331494986209794820153943940030260861892443754060606136855880671001234238005657779327690688770979754827403497562508404554592608851557041964294204828713312560204630703780766764893861173204844776238561781300399937612223543077669292803889929497572259993391592086727921268051521995491840378133874165663664692604476461998490772814767511377828589902073206119360813759202215768345069726322914501572578890384305386261213495352614915334041353885302034709423165237710716396187213601500121624491491680344028044347728826126534096722171138248777199958282268434669927218558227978237918140489751113484229317932598164456585270575621365563876296909174135233549566649842056147030662679443210413277985877370837317398773237733790330634299400715622709500591051055786799191437648618774985613257317534151453219876123440735594431949790102637754250027061823283775822240283283373893132999739699420693200599460624004697513502224330671428406929321058121948751286823915675695525874485119681182268605660848795600996388907720012890355749203065688587200490924010363358588116215891061827604623315447605218200517028218273808559471975466303308545148473201357515780436204217667627347822628415015905386276907849086196486109148367945566910343505942474035829202555586902656127226894299329868030298537255889737382116559258406042726902088932571233404628479954674944995310169216951487008262409377418119303617686366812860339373834570615464307491902420384401738535037101542224300811750704554090249320529818436273708516593424678352580702917382289323483986061452982438096673945413904482530858773263960537097329196812056881404603497188351454088259247001463296783339664881425969273025706282783182232867128718017046005775590698065614951347444106281112726652718458960372406153803218599772548461765753456532436591834489124592336391957073039951205790565729036485053811490269334632259531467119281785259676052468663447278846586462082986216598106649027799903367024225147111679601658411390513891922072282713979676444954753941561560079045382212504529367158424604642281200047761437323779721338915449980714343854372471538431103938764741748961344945851844141203298553780448939639813510968469867143580482005505560237775770747781454549163921017268481012324290725942083900457883798464279339370734046223042629639911649006497975906476991057823132880140981629705476776425011282449890053156777854410854661751673818192206197205242409883614615617949038832600508447926467359385105002269201462482689457245435790677961407869804094189566180182188713245737367174763010009749451258091157595240965124657433713093754826084242474107460087198745219921203160009038553279579060858783419427750203056741430305560102872323879032596162684646207026575858616212090566431445171212354468813583161075659979981682393529958544713939713646369759730816224223255089001432773350707560816753252309435384756657555803460774762767597686124895597789087203689108010602604159387239758504511682405211268779053192504474667625056905385522515098196791033328815751871832942786897317094704268295766934215888208955126364287531375942275642871067480453860254309392526099139046955356013421534803536009024048915512005099737650080596306719672777500918236376880277338692415097220805838326689133726157633444002436809460265492671458168936362330071829020295155471192063903602126257170799749361241328613974287026735435786270166823596518013977019733220041695135712884697848649694904241242689245034400270265464664019602961883524055900187559947779549379904929440641577049289285124865618688352812223252964558081939619264523229311040577957297852272024502742120113582911398232740162454548067131557079218160004377656868684636286679258671930982697183604164324671823784339494289221570715437761391738709861356963616162679258952698853128743025920179111168961809516636459910298257745540387774384353887143013939750387833063501705524385747546922623997644114975028852113934564284242271136922136881756458282572638713827307547530388756456884223791986081686498447767960406647914071930093122867378090715772051898342311053006387256517269386066815840370482213701664603676228084011599416382641744129145865624979460240999959624120927180031159552161325111842997981311538517140392054074547544455864101875527104787598580809074219208828120759871818615422454397178022005215040495054854468688428982073612831088575411922158516291453242439865911794964022727304591928350427432822862327812462388198323491852732039225294008132808576360131991020704512186388126089188787223775398088255400797537684832493165874203106256389639112584717471062711776169113029264879705815999445367819095087882055832930847312527712203187201052835828193443500721297210975703417139142287499880310162946125658877393936239023701828672723272933938059445456598693717555772275086548193425042999537834375918119110672422394351979196390995049943078930007272467856578053083324095927426847945618648710045254214819631877373394509980671644849279670129822555456379861132832085255794634614961642634459249105663837451766871526011763979609542061453639223973189497184488650540088810004091168793195518553824800360129164405667727675570107872461742863741338604427478317174477900268179997412375781964235975013856041311865940094652415915394365255589227990142856424559167621357075606815922472615692502369157448261249649053989513872312234378124971202705555817294879925226975561250953474804306572221652478355994416529125640437966498208031406503518394044728859513046193100470662447984814695706456036460944260184456354863961554033582550087559874872372601082234891337588059178939589040737511882130118739654195743279678787741668609113747427576367163236770811180718324716841859882872919840971680598136796120321237867236598494120721480428874677994907726112308572469289076243418909625917545454903228169833190272081087133982573402129949851498458818025448150441249716180888140269861553717859283043893903290180117140158532378252694206527213834877725563871605810590533035055908051400231090659154419184793669400917072326166060466925321903681565319844168760037545448338458662702152153451813685909525875756956893392037716182175084625999408063774741235792569179119353952206027124298578922652137346329254546385732622766123825009325169759690589941219814272724175928864829621439361252837528059628788505933456546437958866760314155405499146155058717889998696253374961338817665411109987720487244982540002423054178595270283539311942018887096652196991426425314768778377595624088991694921484568908968234458145658597535428066581001381614470378190059612098655980320220570176586209501553229332721048056177853794141468246326600800871302420166141989540008997885852802890841246293354599005210192166345956120847632491950631436205164190220570197274655629759010906702240209011309595175120631367797572560406166599405184237408643392535438867513482769667191155335340988490703829630011914750865775142325193074186443159105581255860251406017687343000009744679190128679948886484452451503620756531120030205621103236190022748866894630117892803672571304673531503825288349364654301955416530620589604407999010133044688032809404987917776641081587987263048409338853545214138216910810257496182393740631573327423589383322243556767170560000, - 146197897699408851060178633232752707356831331594001690860796997819626241300464390123315362528144406799153767273855322546654889556273448003954198829303108570874794150540268805843848372854531942187036622231758229821341240069324393948483321478325892802027234739002089171724942890991123217937292083969865224543149565423761578869920521484947669758831732319285741060484393821449848628495240488595114777563008503522036714388274927965699420005723875973369761564027404984115549373590193316886408831933260835145135995687287922059805470643058083037781831614055828898257569945644663173549689351593435883104157155951270326505598360284339227491188429774745879640060960669229002359690165995363704210746714935739644411646313176572086116474146493725021312759683389309757198878764308046167281338624899343201922253381339062370245503931173022018648384460461076284478939457436626418086983554416556815640567999683914940992164319758562911742320279216778789862649191606110204720014357581738861282353886811241507686862162610322469390893979932787160954214423347233995481622838106843761680868069067075321655285727669762792254760052960498835683918784703878472462432713392418049005363631367463906041119886150993253802527372718617244968320617389414713487019568381810137023962294658280645956972944066132641941228549395206255779577947692720743088518724250054719274764384638691912518357915133236556819812819266634649262683673857522849422096981321771210107878392020544168482834041767685622210009955892328951722491994061333773258102263740608113439894388042552391332002904897997230162892277115548656559852955240757063424483856368074748167252468249895028099682446440790864900624790914966059342843598827432203759311875499686529867708319050119148926981362120858633054317965027375060159749899291378989585325690144663723974866829684675153266717970511576364368326713489442275866191743879677001125585239310983469801535323647007833697415652628823155506155186596993822437085530056964969097635876214637652078699497815877795253508364793110714801455389859494164386520581268403654593211271484050724490643437441984984428858476375903474199755906158160598053879320415367919454756539401944227663456835811348675371599727011655527222524002340738060614049338401012169740316047325540267951955978164919672265539907630722415958317592163986477952191717637656121736011676257766345735956745469536905007022505123808293458034747086122731388188727541561995214406012069500913499992465708060195218441599611550219022656851180592107500060887300493560240935917956607981643098173652228203215635606862311458646037628886904405239114923495499133702053692068229399882387010669136067363716300020693692580930209074443026995951170698496586115062684520367763071739530931620683896472911102754676195610539987141018384623284278161967268530972528621106731357938787133849061549703348283082935055071584765725838530502025976203814526529736186375412872693727107332368178326222245928081827673276024062581888904455780454692493663623046353271020055360752955992602477103411253175603493021552685597142245611974587904202281711883706707892407656542509563327877973873448072857614063580953609198318022058187184142055122262986689979856235366715677671455409921837616891098592522040527840589901353182262274671150833065283258227925049746007956345304003494167202273160897569101434809619314585858751559393120872901060663152663365369725113040939035710445175171784764075149919944929946390476323500132924047586473490268975415213889590489591996570326967396099273799614318500149222691559655674773724687842140843970994268041202210409217001254450129696642628080160452335677045087691422773806778194031738690320813532914946217299533295823407257183135627477634887223260810391680960210635154387155589860645710459328120361211477294188193646924308726700573675395695685041366607948540114964947664147880123377248299453180319018820405334449545536820024215799845164354170947690048797680839737407621512590949409009914873148341264706260430469593063085787597928051508797999370797010811604511781942276194883627307588210500789529295941267570001571865113678683988496310574854760155314539900170618110909769260473939376816153308393919582169180576457843233299676613479198506973955170648967781857276351794771597697564215780878382894478101040300804733263079407203992812634853117815178399339972816980679914376869806295289509046190837030265603087715955601738499568510200892705208687620411186379595895204310393284196579550686777809408932909761248050522159904732399699605239881890041066555086401553271840361511856307863298643408817480946555364292309977386413935479617611406484923070657671568672159741710061794783259156230077946896809468446997693717285513853338215100322931490625995704451523961302008447532033160335827434005721989096858663658658321360182837079319351074383187290219834133688102214641533886488133695043670902236871274807974985743698708039527022431776918684672303712547396230892451021918234658809989985919852459596373741711197564269181793653467273202399873889360562400143038589345989244984567451892882655579138840745314908193340528964799789462168825812408926829682348140051614052256063132647336431179542521274047645767907309087021327514252672721247295264903444761241691580725302314929725684542160931725397883334083235263994662687556250406204388975587236723766221002751487867565498921340931756371827981189827157076359562100346700968465985047324666362437123364010617189803390315779165391792565065863437052310473638568509399974967821007861559295235392323847774746981790551359106813283947301578081182701999421887020225086647370927150504559246056022334310215704238327293875458314094367865319133112468347825912401634656145061162617087550049247935008908524512897114319948734213352501391071057032724097859630284184061369144200132766052655792512072674957372553958932732171241802599885755986187032007366853234717747754258964961712330403381942234081857490054500732528358630791805297659623235440582949018096560164038516117106769532746795186872220394804168887101584250166391580109525785490441343033508069534518652718507350965632513406967545562087726654923127427316527805763807686507369538405781113796882562808265728843988462826579450197075170313458472795238644419886401014519468435048143821135351589211317992961656248352512950129288264778419032438047953827467523243587847386077860977969722359846165866913545991916844323422972784298420459176520243214506452382907461592793371294647757193353651132986680321978483673511585832578323308617605744559413088688500774876579035106242632145013192660325871620309124431374692204396324766269492356293477636498090452200302993517551017023112142206862606038256060467954263018143468118612715750289070456071912020736753407653029992765661047312950993572947030801829721468248572782869707061936388987204183790281195685929949744465722280977504777717602212286155710205203047002082185121842308656150827549770023898360566525038844562983018141889702962831597770473471581766456135169290102462543728024945366757203737289392517386687047527133530146205711601756547968515210217132971559820865362477523857442515571967370982209819542134816007621598366487168763716018761880493567244447603440294120091455460163697861451244669576828683986974002487107349978429092016459683066976131589635022804703637253766563023265379018945755409302776254235125332349699320054292986892157038716168376092075897175398513347619977058138112062408917923531319097519738683597702062603808838890926151277890228367447918311259857408182536305252111185701815777971840152359521961406579598105972043562929411117393951755886012516872008650550414044799798460861866581439277342140622781481019133414315892691706960356654360306564211867511753996039704919664659685839873468337551106838969246648829092095836070185205553454029557833660386190385335091410918713603706045606602613554319007610564051242291975343059261599872996162465998010008649576290041133200026513136733432010288123606812610492493028206920282941107224000827071406932727110901037252840325532293640824605060750797471765903345990548436140826890559155506202804899360533970196936804538712376629184189629082715731825908363377803201427103876961580832877740137435333508355369782600044875962621362890531467718489161072640000, - 2023015173611506620197083155021849230551656416535001892388710685423037211552947821894045110467244666314742593195154766361510646193020032745440166824434538047178890985603820453421895382950367261401079238411691289011903386677466257297215349491704806827538103895355202198923511594401659602894838951666375753958554671746570166149261462986174781493666822832609742961175260912535263774036491999497876688337588164442546786412690599369684412965898802730413729572074894835815829280395440671160083899126244540183983550485651846133022946540007750215519837791816168337637477126067147198177636404210821806278234007430410699187127280934189904582123584644138721897232558879420534081443561313389659022303321674416370704733832172999122308840300064248690476015681971673423373890389525801862803789480345096374939250381616139044293675707432771073250070875388556784678009802801601084395846220783876185531577084420682233110349632958252946944923817131635894678639372601597146120383287808565998980820456327924499078805924660783318725969200127715587924843047679415353415465054898160949089050191523096657599128392562352989461196672316769968231129480144845276700763048606921485412590279446041068681358863577806015943034975796276831903486062549644360712567772046946257204849977901164008196556594956903827911569424078726143069258390420123330284743644309386719035031944427211794351960276007631111439737281799881465725151822116331691583228052456714126821590081114988820981404536080349971302953116060354779271333776836448955261613534448594499081721759692998854827433114450361954901379413204766873395921648185191265168743522377173642059163248675841267120018424718629662303329084627772542100070845274751041716068243789746551607477894344257577417817455966842877170348869379991224875789024812592901110172080988515197492845400264911641996205362493517551795430613743541213233455909220346539713319585241134273766572341538318329742418727378454987441387356039625652375291350948146086429110951460374552914679756081758619306340976598681393978420166829919242609886803816599952800145095397087784795243386212093493320933089208999140396528212181872580679500498585817446204595158364650711013432891583327830289556247810744050782645873315624190311918857969371746643115755601166144291231966832080459555335595600889224714510806365466230587878097508175897606917633997342807191472363043327081794833135745576324622264825925824977346407840548648230035964638544850940607768804289350149002426264869745828594321934536666661376099268046761563621046289454340481648257452007526316119904814134180170154428728907687215088985388943892021264020241793768882021431113594548753561283440655323109804407793633814267972370767007885431384330090915084841773073798235017044713390263966030782740844586807162899026633134942129755437115911014921565222007714382039863967556472204661655375592360249085108488577143503944259638876209861499272968388355743541213584798085588168100858192198914739393288876819650551059318988755516813485416538782602956774660385811507549257574966280945395377711047325987968402781116385693789488677640455463187911536408763940927547149449516803910299754663968420581593377671803206030740983829844295495206469595152178765518128320314922792748028360282753228606332604476530165725877821755848293487151028123934323429300925329982289114508963738194005925848160282015299278545381189325779500232778324030612656682760108091085664931312245619119506192219370290067814125825639236120970509826947063310467089107176057300387253726987095061749604250857179577140450305297311784982743749172243955227769016531122632894040308893225487848482611606315250547636483536283559084652870941876551796309990332596061431201845535890100077641831066748996256885237359820797316702329580963736525059600260825262814194354147581470829709385914369089234725294042206063181079494926928546976711225670441890366543612657181735580792864301116057172257793529670307183353855061293726869177799121845991433490036114789877909561780848546623929684180080611648750586583824222448339200924077502196453706086587727748060055934609269526239114002875404038117389021498342688244990855351659156819017941463611952543169186069278170451284399082118485539302531682983910887160058138678684528183606247644328338415897353188719468548225775499818139711932588303563518997994935765016456480485968519893390775639308916771227639591582029356631453736593961081666723397110647246188909416557563032828780176266332664666112323477273649896835987132751884393767215148903745515681677070720997178913256922617812923998489620853601699108469588808438920906787954393253296400235492979603599896073928357771623131075808834565911630403392160588989286577082007575709361377423701991119203501021537770347094562606954691319141018214067201808032460798030448651336428198542477276010634163714628716119977816826357455269399421468953111730335793015514042009127364064036380952871324846337530245679346338712103923001940412555725825851050997949412544126146085503921653687930505929312616974514561572448316025888181190342417538744110016851040667325953992330645191046568934593728928300106713671264495568698510610173050495410244168350427773151676564382764205553139235304274290421743481772731705644252958331007217470199123364621425964293993470656059407300609988536462024979030264530398177140133137169882441854858340154080297702185015043764742681011065838947480672305424639655818502703859754133035145146747606240454776741296094859951127860894262683691845505533297964174060317815591582667117088332547868694055811430247226259529415011508648317771921761608267853206735202669901761838856759646281618958764059003464692755209792036095014307112168913778005411108206826546039616452583683067242273812397973231421582430589372912511106471448256614452589235718020650133387141232375147769958889340605100124868526322426902369634398233091916630302330708457621681801960984843395299942275881869477859980702316846781994320006743983694938453444906774625110496820990743381755870913105256130544747893056974451717333881983908006347540470991538236997772138908854688350184106605272126102495067729243452878451918818408158303833123322102495204014990105701056755431340404601782351722421393043757968762085604584109455577513057644782070388013876139209322272934958427670528257760163381980840022059314190964677651379552332658780099999654750110807399809598521556888325544777520900687886184235232466032815247436366781786145141974368776449233326975448103848650815588384219863353765599300630221287132357449922366144150138934849626243070280938491954486820600510584730830383450011876375802190210355438319608155948148423093328530527845603345551104899450681314365541254494392705258230583089083680271303040184369369511951710056682055415985574054997937341439503664101683276528484870361162126527867791322419210795726164474856522832425044060879618137398407169221872938663023198104805798136108693959592434471906259205274768608603364533420026929863412932275416402266099625824112382683397890403293449456882386858225852409114995556758171515317554410325867686686090884706863160953052681512232588354786118840697248999762149149993649069751149712143292572434433351508803630491791548975452016151720686008623470097478431572474421806364729029716087732073487871067380914423606917079941777225110906029194346163849992694618533021021237008350168364601184489389176639849983179945463874348966640786998959170241221893007742068641201747740734730659712647580735531094768774818254089248315829712341005137251535704878557848278025195237052515538351458798555849399146046353498448957491640506274587132927039204401824426221323927801067118810364525614154279796649879611631662200277557780692698688717593545570499799565305577740832484493382658173930365857187611939873776871876727160897077240091316788957752395836041048973381298811818398022324689156326391593258742624564218973487745326311528781386304704929753218444135401418752921095816238819457481673262658289596219448536065949235892885280253509267606530461711732125658445096377569097010140098718658911952291963542781713500694262380290473356948142145292945877515720440028949288998714062808700836088018937053401851134061710559420668054840355371917766420131461684264960000, - -17523188729909511882430804197442099530712130510434637993457253948694730023924207305128226424130634496154661253870771778305913043217137908564075409128177328985701179022785429329112570378891156140903097055904059494015481158014573301008432005871706754302918275941880105155717360976545531048137123889080797312097877950240756745516099661900813489704393643906293993856674329449005562913609376478596727483801377366506653951382547831152964808180022690446124872950583425175362644466147839237058715764607855113918523110248698937336926373479043772184999828120513535669980672691558453134136337104514948524932412680109459017967720278214754252232036830644145470237015149271160324801846008185843722855481176267267618533663261775367373776373477913125098950851345163351494641277692975410319938148725658336473864086802404748660476253957642239259637555035063420619910550965348652763270647392748925329190293110799349347584591223201588348497943046395141400675211775904372559385763676226513525260778931485275444624909713556181371480610778898998840405765344466642385563662419889175385970519410042090112843857329267811816758057225945687588302709422110537221785733939537286798773017484649674478294043821456809426704860939297855241109352657616361156706473244252420810420110405231735292684542464586050697447426515579193853954052755065601107792856781462678346778890813376604386238764128794796456140522800743350114188740210336460268705198872175391640150074795923361140132707810492721367858869783771585160627943069753243899274158138658241397720042857881927555043553236564680222905299451435691480005546234913373975073461531088212465252333230378281825086550955398000176377730667934919512835740164315667290536594835125312651410686236180514935963986204883837311681476476385956624689571362369598130040661267595750423024594967774149336336374868963696530212240798970526341777719654671736054010927986631818984742085130573902106164268345131635472777535109597436559353580809941946570093546875284314686216772584745501115557815445580933657217731605555649971374897047816197874479643668439130650015101904790147668956222841066337063737245280064892302963073726393958213156364428529173855452551147073234630045547640312550688674253989731465279570326212446898781806585491114482184049445362891916986657483005177245744747284039559337161702050537504865562752560580643245687114356611104645644973788950107251933346210772389675642145361629712487918139782347727512393653891191564543912816466025432062807537631289355487416202375912322655543292074143427066609195012523055559421697737310583251928850083191553006362191349204835193978186604507150756554997499613247369773972784073416179664945494811772822458727489798539458730542423840633767116609689220369969835752140438497144718744133910415086094190921393690830934156213104351090824767809895620547574454950179092500646164718583389887387359851571593558718623465485012035422523178667561406884081391831780705025322832957478865204111426129745189694203858957063852380935271492870707410169182183788931406146567387304220282934858131728882424237221734125973123948879917092260487852874244397935042604209481113900637267756578343692464395746990702972465079976549719004603167620518610382863165621743825425530645056383224237771224827292689890746046326830375701354600676069747387433759622515394243335572821385260384427162499933972259067316159250261937562181114101348729782207756182136051792896861357256528254920781384229804060600823935659189596615359322611459551793674070747515404313653103570672136174840901662269765701960921714816718254664526968870961978350915998191909250433256532296000214085090145256929500352424139077380970376428907324668115352670446774402233070032607615087166156254083383705255292132280577011065144074185824881705359388931597168244958519452003619461844293392798886127126755767488937305534176376531613471082885795413944564677242501007991497093686264171197141481446951053344558317681936534091097873140391756624101856060140698983142632844869100005098551724688413044638642864979932500082815266873489824489050298481150693780675052252830027588172346458340075832834883152642342637026152320496809496521773464669072972588854272523957659354422714721265728069553692583184570465205290941453398070020622641321011631206315528063877000922403193288412403830989799879725278006436939791233209908929371223972209900183237149565699566959894326732031538974619645647576449334228892223929454402006041520901159039014469486513975826628174937210201207868235796915276389550550198247467714314911913683241946605427168296831167744450038879493983660875401638217707178688953241267031547230039433812328519577453337162372994735169929139139539042281373346853916158046326164342253207388921933859267704977810715326265330903241069749043153116217270924391799902516042009399154933950731224737191153424899259694449932605633899437899210621652749460005492277515464400382830101641152390257567121512973231453032108639471221297835196481004067951257756646932166947024014399426112925546446469556497670700062119120893977842034200314169880616989130353096426666391269229725598583490967035291555822133873291232827356827980489607066301989427882936404025542064685762964174596732502593228843847189723161907520634293946973148557061390636017452759304220324410865682308221822696728708149152524901692447601858516702525351134421939908487400471016353756981120218385046134173920838060111693896539746122040701252975973076294446183536104425678959934081888423986003384094482287409894461327887812768870930983390791357503030202402146498012745988042503920306893417575825866884172735603264002188653991135722446172749030574663758569362566640510843073776666028981503132141409975376053013375233463017092191724292204791668904398875638286973266347604528011966057190570133130497575437127706045119431825330872255159488431561654405255061702747551257907743850957409749001818350155240503114548194159363164367872389071442688138024027816962517637728419850222357407226203813802910373390390108527807421683214188526305307411625741768758250449513203113106285834658297729075359630853178621517767476263332850091258655862139621604415864387449380358439812061221058074559430330871122927988828778753376543956234103181584742998985337135161123373740627232216079717570231129316106098192152808289099052982390837033403412171814977530334329177815307544744088349073990333393890221725805735160935348828301460474383325967868415478556611085691935277389036954145991555436709190446953089768764172319161962860288328837825936704148594005869020202503094989915632489901500516967384033263235834283363360433131385242767383308438692427388478812792627796098050745654648232911958626324656760765157366799198941555081930075734680872696558860178205664118119048425060481878813585129938397550870572345381138275593609199405199689384628687726287258720072952024119140085419538659729524071465234505523767475860022555043007519587979982777912529786094367832279026075477258121787279838588903585981574601106124630437868185234789796262847945193877404557942510599015704618171675033376357399832461851663601119552858475094927771709095406356623428276338716940502848266185190081327004174691138162880260325156887034910970091944768189432420437958824441685704672022919734264611170677788753544971820346002644861878781951174259994736813425754622738873979444073556556481308105967039483878673329274015193299541185139607038254782140359592142039384571325218729504616292846776292794227891932261595785830759028892271149245352760374996082782396583068127984662847944474495002617187927677258292992276282554510994382613799588839808491959462915758464032843505004088312660678035195847691192233823457036745688811597992129034860987969773551002618369253762663720162303723437916869176908202208667350121065579712243799961657410786458632697910785328410538837004786755817323362418027807124562519312844524670921518149556865807373277806809855523744579419244945344459613695874409462372909032079306141019633097816198224847392305397534149535029468286332093813198912980424056012396802679658834924997665906625598447198976467789117847678475591993885181682760815373721536563982682520634388551259780190778134379178587953561600000, - -1702968806118705403780127846639636962443619766143705388948434447257392804725292334808093375016777495974954625541138609028441185829024304744744708940149595236833295981871706390642636742434657424627465996695566732413336961388315959379922257941142823174892823698446535336612170325668813370330289655416718467706819726828519056151247762512018271613827131447126310632480574555527835089464098855496366464922245905567340956684434507468133649884426271886780789995706500813387686743597656678469033370383318874868158766852945565474963746056170684735190743603344466138610570060713532721446826197874206064636146979657495988675820812064823786747079316560057668980967752941611269215316417750532592071269121400478097167645796230210389299272857045099977355741550008189201246667057830504373783936569089360449016292910580668917120308968802405186381770917466387613446812865918675525106829003864571289607903224760154788086492775601888209110004418375636103584952928023192646715930166820758258126416134810223005319016029534105455456587627143421328145988183413029589276317714610643077504451053623544525352851688259635551661291278885039780465665668879624009166637903338779971095265755710353587282856396805776285155839965894013621988468352642026851062070304709189645164737412826867645268309355796949909790364442541942013772461825063370894584311936068970916361492151945656808680692103055311073656360205103546645143783330374931038905989687564332250672895096561060920730771358540674797564489082586380534354584100613052412569529157631128705693710022425771089510837130831630604025272811750736573046707440048284709504675706484755950201729027695095707242771621856708719082695434083465133545442811641419570414095564705376264004212297201643022288231719920904801004447316502439966902517549596606773342109499421088567652644393702992172689744293867716800435624622026355882769698117379444191204315703792947543590020219069057133848578218357378773498426919932286587713540020372999965651675105892275675010049659955538295262180120102247209001849243494417786728245573959135844419630238389172251849492064268911547302726225762154929810554665122028316131839626458727148163179552624275841404160230444674392264374524603165335202540470742865864369782737289798213166935176854706919171277133238480448187828163265398824179871806633087421045714339140094285169507710901137720027342845600673119264899956981882254839940425247372226923480189619311098073785564834551725013975084084768498155392011399378640637381032003866623422778949768705789525579496855122167375177860151906905298092821378706597928933584811778841466711260510358940330310904924874813265578499079364566961325828296664323360294616783322141439314942674971852783247285982921298595224606264405389505354856243375542861487322299867654965040756187492296636703530701277491616704438038421437873677855778483150837769998145445845152605480108906104616705261260534049886261309788635540783710343152339017175105731557985380364564246422294545267022336696980350865941892740441225414676133920340292758935305130029077827421202618220078778120528379846517831507830461529310167080160273767567902966550051401775158526585164053237421716594270527554675109322103455427193512999020495686894379913176069324861161487006925291582684585637380227145683811787910191289058398315857793749770998400474340747662325829565669612135600046086276011277838453993307628724981766005755822107815851901820072996256973307698135565124925417260043650963879252773749643136531905550410794718440741264658351954995803118345604472375412733049642649251232759071158037144794474355770094082196995150232147369331647092585725012711211132995770256604333235537705031238668370838470216099398782816218667906981178764232411702275222714132424336947457409015675777028201586810177565079898058389129760173935565943812524329767308712976975903156822697012711251494006927194669125865835268424533333192041971879343191935727176529766573025144955417930150296453824222482567345285587227497227851109223458387566388122600149711018817750983680192524099396147930700210083837359891243910446184575529552141404631898844209980226263040648166434233281486466394842204254462492968152031894088075410725314883977473209880288047916854680124276077371939849967333043334500477712628963552108297407620314130430596585530637602685971973610064540461232314195290375445036913641180625759209263190721681161887705960284186285919630567355720235920349388839026365861490947497552321533618767751658723745730902185413194372192623164196772281724292816165107924516944276924767336135653186146343602728366136410599150747080312327548969497309301975833337362015809161526619601467793937112149058700028406314575681568433560612656769829142107813355696755880673788170871696606594158010109623509388536101090377805432064588631624010932460313166485925717704513139434176607612351529358835687819135716502682049013647735949442364329441455350315900431482161344164812615514011707066058962053652903408660439061844995688109282439514697472206580767451187537939234192504829163251392923813804876341460993803034456432081363046224990894543541391630376457686399702438186346018479003837812591356984930932573715122095684040702470937382221469375393506177406340230033379710301224424355804002002938032081450227982580855751236917658631487364407004684840109372219062817669535994732301162888387116851784144666672460970336633074844828885589684798504074622306278804901157619597039732987096745943090167839033543007040176976594895696469179662124229140645418127335516104746246282757395695873256385418383784299398919127528247775226325922132967443072695634608386891372203472156458366534211923975737913168858944730389682269141701208724035876910297347465820483690396116835644549671338183702174142013223381296175917934428301070663530688330834143179259831842291433008655481960622767600309779730354425563250562321958688750773118547570850570604709760432523260772774965966635500258482253240918722702021037471563464890246307763906018998396244755471694452248340627010804332476707769358316146960378103558584100193586821257210051909262195026489637516691487977273029041979878919129373788242142546366099497069736626730085945715005509569456199918744015518881593074752681217974090008774445616627116953027071690511265525066051368312341179198076680358974355627773046488976748888532207835753048306177235404775558989486811285585222841892421321999312510196869632924639245291965414990709929198211567204256934148607751045931281816670084627158396417130083384433319605015414571401055070599068137745383076138020785156879513349302528329264063293546775463030983214464208722130365284658772060597223733245103373419125189873975051634084386518528306954487355020604832262398542764927202430709481735510134506084504889358054220316729329933445678449204819518318629050795896652779955090144555791141053800738736847124210895103837472514092032260626194213231348730922944869478402443185044153236895185335758041930492478613765511731277803553203014107445224106248537044788489835326049575456620865178496417377805386824479844963152651927711929748421241913081526974835451784883004783497814166441068565715534847702275392162645166440177621196382367344177589274508864309732022509361063249569041129510191154940875739996404014701876455198098316438551113772379671964455661048980270410935600050022842375954497516204639577162536941215138274157104092678662913625210358187909365665905533235927909616766133675894934688723476325226187279683086289362842410178979019549848352812263492713247934787512464318648425515272267247774431535822649519413417586103812404969497254484048222023022490950795745088582850518571274384522912359284969747383896909523659076356859648529795710595465026494206619261713795446321008775688013503963460356470654552179527159662641822225706021306745123838967024175884896135162793713968160124061656792462404568899291852772846814686461360788788330905802348067397965960132425614158646507243765304208525013681319040339305141800264321713927836628255871940987395316351245030761323235167485398660762574618044107367434880547588137157532275401521624616004601388300168719700800845206465577580728065918000647906567127040000, - -44742002009114581539006099634520235204899339211121833252722768397840544270815582453242207983882946255713749067401373461118733974155738021123991511859218119675406457370469917412501373107736412559979046620177020000785853486101275808641318326733322166271490256966003997923989169590036364770012958288642623872592201649915687833826394129040963609127122326289714359231152518180976264081370627036283807023052205163508014681384436265148797818579936731558277142152169659985086405960310973146390155963994974087518690065439620310022301710887255271516106931028176509338896379842704001286981001835185631244183115085088925786499807477511646002750816026722832435686405110096898374802551752685450948628998239583302525715321359462380138263699378241064571017463306317108491499859904148654962493439655305205568017047228054015393770409952157938455951822236409554855565280670498716130935680814700250523273057091133335889797371498594925272187914759155803097876995621022152391031907222987360779669071367450482479000711913608779829124946864706044911852973035932088595194699637831937545953634780038429830584392448901020676406242160761683902433536482694976590996889337499337288142977730951718454644799454300137887068542289820348482000718484630438107473996755876326040034590967528494386394487261597066671340186842583441008049441234028327698246210123545573685993915878552671336967432045894607919929199161646931291065880106268604816229342916204794238112438878440128485659919207188260828179197754512410463463956336156591180701064282371384787724936368311673505298615570514135317684065199084059730814440592143483603639064553446213189372097578268425305815067240439644576714795394394934807619473001779317066942672994887033248617628972141200597270935413573565325049551460349259239951423428127474691649033258708384410320350849533918343098986393633389200461939546578882059048310905136667887312579575068515967861643694986579187768331029723460717613372294541550103028288693502495243551308024884948550161247925814231183427409809775324078704425417281744216788074884357873867031167930681094288801215497249238488591734714173083807936200608908934155364518670882309488660642287868203156089947347687718752210720603449183823371090979401212409092947342308720631190175081803526350639998499372366811003601824098670787821855249245243466431917472676775719620353630473373735297941742110802309901605661063387672252631559335672761964385643995977410810509480094209309373847907039662815894649332681658882452347641783886157374475915651553304570949442584323873288953518252856685200916650026708581555757705652078068476002954760403886653913723312823134327675892467613204811645033213321667101789114698306508759596030325377626791424530351363781733283308998077988811222718209141241384592579681210452443730880303028473602774083557077498593873024130307599587634670022790845618642071631086607568832497395587408636519693454119115648214484403638717972275172917736631092692967245717303804646826936189276869035845161683104603406802185311957487282466244761040434996808251336238340060739655617667718770888413751107052670446394697516459233943898154759020242159111535092901790291908180419758588864884985791357169912894213210455782486350409323078412623777310162761632535118372795460206850056671983127355152311156104033721343972129057867648885815644941600817914667051083477265161120173866731985007568090771229677143525720509166121039942935785581424919053708852456855626388564676062307892287739322842087939265805020703934174807680757635017172554081772838546122128067621439566517416812592820883709054613114845641811331867009953386706185222300774566322514452138408633416505058257392817661525725748069873168592658657616242332151895243233031601685552624993439305597628438548098271504269445686246167446665945390699899142971825987075489632554575542385546584108526978391562957666294139532587152712430170045938664675297655819884376713260583077589398071904045701355243879276118744493747261615885795002693631367945760558905780250673312120064827831951844378728807108987801700754635002488943404527088821013480864754394330537266104940939638468794918838111780268400551967939585443347314308732788112395250555792565524830901023425678287816338665628434809064979894803826027284289713518011254265800389598741475921397654455552160995806611526999223912722920651478579489420546731735296338704331069769941806612213917151144110688268620640836824637336172438313063868549476888725690409304186070766855758117461791958539949717764716924448903642830490438297825679306399712527265931051218278765002436254614958956129534477090025299826708248026398017075377323773018219504064762291881057767528318117986439407084619776909926408240780458654142416022365396187130831980608939101521854921144755578950940062497685803551261038982119253024585435691959609895525774800600926894242683792796612606306705008460723224406628561053186378366515289766189939629602685461898907022160699850018986965141690117983115342098349687766745858141275873104172095324019263291110864073268285003389478260243493129445545327829799035915467162065346145297398970197846709964634751626075933488021125257201837227020631170240424518035777782628770651795343461555467629413544638726478982646568989467130002452480730094454310530395070459222039435712524946307787970521676726727131692602074562190837680283471177516037689958584560848828887715491477399255667642505348078335643473966652657791109409832919236964791462316070983854760864091529218927042616853540443053169483227360524028543232765924178825360211421974586836131957663688500044182397543628656651113543451750261283715664185829582256254045955570159107711150745233344330071116036770235864624672140294081634861521716139930815205895620254465279537743251888977941319584715241710693848891458821056601549349279746544399266538077274185151757338467417225964010253818616365723172967462500900970914539904855544467658347242084145846547141604131140399374155814866236538774828291275105698890279695712049595544607174666016130871766830063576317020528736659538521619648714247735395072618179348978527035152261479803323241753280572520757547593943543252883034556000182483001881178700030508004369703041291203561578102127915862099746123579169843529669884150879929659737926583356734938389748458623130068573863313025200147577088247078544698160441510431605910005142723795405076004527410419968764738400040845601581960226811891032568387109548068817578405861672974839358435316140469952103800695343590267533609910571934872489575430224360311401329346361146547181142961188272624650320895675999999295077273337901081123231690524091252914962042780199551558530569858177108866376116604929502681433537175890606038860148146875540566655094967519777774532947245045478810174698370592913198804838264349978991442185671568351479822355394002446266839628148664940236765101688424389066649688260325647700404670717179295694713701669646107668023936226888373885944966503084096724965747670982040230203476858630567137992325145419067489316671655535286477660790524256933557832604474077334060338625939977638255556135060759074251330030675663234113995931927106849434469541469396262548436692639206750175882474066436370371542528750854087967072535101004808248853173062531696764007804511334919298499291434310354506162982150686715675319705837783887244653830324076517029848642119531391430855231103361046174703921728783153311735097661997641914947513084749719210715294863358963549363832679318059279780298079452620694646049160595964879686793964905306917273909090759590328940997247514649289321929432676742297058109452143364198398771211321342886773271834718404623004315469833469017675320962042055371084037793774691192680375468261024067937139732102889290170383791187212430505618048287771508298361231062011240610784644510437232023850724756150863159042686259762507572759111974174597990894639836444908407990998382218113383403150767898340113470177898879298760000365955573201768481295389629733698307270839027678276200183727416588393244361036232204335740633424090666445542737537284413728180761308888001801018941321748953607847443748625517293881110454146170863217577468845096960000, - -507551289366793208943186356457785862566940710859538929285532097907894564994097476829228951936315485447010649899453851721476751066062172818703776274436880110466133841629315886051072571732741422719761803830342552748986952913970538698008693046417972531334278783655838172854952506469570688192371487569233398998558637348122777073333924242383770688577493312506813567159834519071919870112193730481701881535494871138416248292299308644660662824937270474930916455242342537389624989566587269453223840852811416610535541271377892388165863666144598252984598709197668355450352913697538845506214653205415219671943549420972437501453947487730071078811542519380806578914776243563141834017399876750427455127132900715934033291894395345054191416904483094013478511000575724300847219606744608435613296758636006520096245403868439106588470953844277495198489083847547252450976225612009944173333501630207010550815011588273784413579390658207478299419215286683255290546225709693857177479212594204334387424212002285637909531301988918856566257124388692985392245049298434631430103342507530293126790809164985594467867039560479580597275462036198348539837941804476236910695032901404934683187247058094005215728719996077247661729070333174826038909808247813853545622660865087900537994997296374844734444450979557028480263879285815703180378983697231989081986886356572059205667550264439517007443839395331560899624703743165296937039863352194598404135097687248602765785690853945908172529951803174871936390250730393520894483842306696178206822927225659242566376111378976869287414202271161882542813251208707609997779024322530714935888243852562052051300515487483711988871827171237501323827157881926955986335897536434885064113962429855905335738576790146083517760684020413094788617298737085604603673925420822245680054490478498080564168330834540936907896035608585597558485746715410719960935071218237002290018265626017590478286777861376694887107770983844053056023353773563970508182561444419638839333970476586949786479293728941144441441481282683702226249127163168005682679805156462778575404310254588961490479251809388601199015036144369711078416466957302347489489929421660337127736701914862206774519744360442587805974812260550978785769492362686916157280091046353047277644550700924942601617020874044386558583675954687616833507653666375612441310018198072596659170883016051297521604592574095578851750859261336393639482844720799253024162582597594219145987056326062241994869432864822441515293297304197194068010480048922463416773627084420143538105011579706658438680676296644065374757306638598585284655530759410581005348089668542459402359651925159644891998257733537268921637360053642191845262514256791508622649189885815157613090159178268215493954581326032878630069104699471278604368841161391035081424434894486359906304069592843855783537749518689696803356277580322353557828855815027230777190211895462378047417153551094629472308860011005147164216028028877313515850963144881552144625356831569232872848254334162713542682685083180155688136641489556163209953942180322918512026141177599417586211097396431623829450895333802058267230527524418741878839723879277363072792739441354310596557149726408048405723076652215346566604762663418847418106324193002709531846232870744287960727123370749554344232860736638675207765163210803248029771480605114123055712284709581714884494850837647571878460732621909289464460478169655501611934152281946532731414035778475951062384921173763047213469544140810934722087947403635274260666384456790883616800824152316568865021144217271425975779023329052008922893164112440905208690637597324655681927958494570317400986931556261096947523918107507793461201686604161772874062293096433669689481043390606053449283270490911961125555207957481575860058195743359739605263231478348583272058425888756725360460257183486222109007887999864944372053561534327067270719078267031686190871326076940785117193017459996067924990997698463245713798199687137536792747836861452760735975359151128534994770747935293192599302769661098843070496353013391326217901268372600897484753533330802983168515516589259084847987837742912208937503099910250706997349496218333999730133096001073648043742950565011918465241250510803030010404508608433191963670949664439998589932158805695902939890587891802436122721132956860343372958909685392829065376084328859564084599629705591601848639548585073792579134800565286514203241562376873708882311384713680871979046538952597926119468895327648516345564082284921855846060089153836823849159284148713660324404585588198775222291101631317479873755406792555855723529484894825124781258413959805507917296112177401651952818886062326250120263412580348637515381284158062560423136676857918516976802294156957394633045026689534890325316017436737472808297474228272594195700596771417904646942965476850778621256876123555452655550983235130609904916921873318794596883519716425271998469926541618316950453576057089636858692002208912213491985195829285199735240505487958612543417947001085341391796201896187805764529569582931460253545814652003804220045076752853313590088680001059982144923920575417251583820910454386371837747088301006574408740379101264693710446373789334048566446427473504562225896299775755103020451128802907366611131425788659753505727926134227370272169489793157189332184345689660975938684040385699149286424719484462506631002841018197097615167288716935550064141276140445018635434044208633519615869786696080562730322108169693815379492584992612918993898127191080393579474350016654679881999453347027954409322199202387289600169696140484183800332624867811060022886722509540186604186024354133547141149715187989282793059918507052522721154197868525588394553938721566940381845247570056515019078946529659370110736215302069619077223376432451351731620788399708187717440001032042367686864223668888896634607075233769829513445145916051112052306027823067441662211354341047526164947963309271009158630892160107458478180301459296052489094711523853500941581228221383288134208616056143549086769333396935953996129690914987810755996355755204623468429731523553740730968614848783221705695693787737144639602567021429260282045520748191501896335547661065784047746932792347460458713467732627797304391031457345464772762894926932311585064754045656452501423399776083025839960584951043428140358792812014927615940610348128765919534570523900293991693724021810833151496971760500511090415562967765074670242678801902701685400233927416881788571316151809694228392245449727974411050851721198545342727688642948944493889038340642899155283519503519269945833008854994376042829877645023151463464548045360686549444772369691227680792026378590559888353292627343440976359404806954950070316480277562259224151818827909235410973762900810347798334361521478687683884935659504512742657004818026039288266563161607858921058082827803787570145430018569672687989813040561786029516422283443140955163883827818305104635755542453577795529297228568416313548454029255070387484162766851263980767459877016749536121641375526841173588179708342221675474972404026324803380875193127804833869114766092089373950055544169621806269577042260093123872228141569804408607287068490277605716880029749479588465865490217037519421261150803725324182039075921067754935536664689616326002587441266840536647661907256455447043484164450902764083235065198105912354553125733813804986298738940653856481374811939846356081412170036437953795092786461796710589644014440031416790607853742023380692252831799094586889970983699600139430127689006855760763744472766553050860311560736930192232092144493737660911838719712942481820042209767675669164235673246154001089910652937843367127815095384051186604569164526004622191809656037777065418456879756284642307218969437526401984087974602638347930594780019621102875783681875282619370357879284299949461033472103564839857394124489373946372561299016393941213719816379638262450021630076561001870127435946093970922810820523451362960706044695472109235521102536604414810026837294533883016995220936797761958833060112897592077343212106649495638963756286835008203301515924832450070794752341519767404845402685440000, - 6929402384130019798990629061436822030468368166456561911029027508699680259791356914393438604278431058447867766057073230573934593181825512772217431178459571799567191968379122640914815621134456899476056185563617653204706461554713237183618520161555110112123190143157615663597951270624388513278839751827828210888280378544288244838752187071953613082389198515890580399181289432216019756238977379239458103501846874265785879383489191955276353474353168930689089401053344746962132443774279305703443439212532645558792429905682103948376469474114491669555921859568631773304444199092151620482889811881108859866692683221942556523489409015435730597220449675246606233980089264322282486301594323026734787417146140192516791777110412136553688019901238220262902280085123943640959424375349301740016230791876355108492173923332774368076503532188933945452779309215388413701745840508128904286095384609973423335831111735274436463384172601900298359329620416673624662128702956598543509472871887633093861379549951759164051225771133457110110036181262507136424576445621987117642865535071206060703726798858731944546867976700908136867927351053288865075646118851264481687659730591721516803356313340539478158412954447423737561683869347015757332602374104497261731317742594210493617879276948962909285675439343839780909072255835715899027558715982549999081541839688425248189746740948058548638919741687932973591234068388832831043443729414207190475275196760206495030791355781960142987803034554386046699050137143485364104001351385194902791680798665967125508261121550077809195958164352395867453692122167594178728096424820190398168340097441137719764963864637538371169707158574965278642200029828102783530045775078109363663604308762777171383393148437630116003318545171526523150550996637927237701007120213655378395619782617964262788719533664562173522273223162295740253068086358366281136843090915232633471690518079074261103839838203312565086983453666125705635719705886323679963854604066884360961646559069973875111901989662603600764688977680091476036943313925062314616084422304793963095686397382463616916527458602122379169971218135056458002903705402434377697924388227588941682174669724872141730586708761419279476691402207907524950274012815605514027654018071440980843217045260786748554021723171783032730731977005399926119488451088275282768967782415570495442806059635612677054626330901032746554556206804494838576333389884555413751827823695116177432684963342057613928228685864331579282621415961073606937389758345395555152270672327052027916783355078873723293502349764885279668412326682809529044800673595043938188900916871758507783668974898478393392008924881091132413790916149066990342042292949870295932336026030323551947935359402467231679005271831683578916702356963881757256207271027490038105158950045320823131146201083559345346416463524439991461127001839618288789525650043192730819939319568482343127251983386676383882253161639679053384636718606080695459020752049586940067439798666074088240454836669684562925666099343473816851113240069724823882102463474228911360353664429362664912481183417262746147613835629201582075178722321254783017928311861675938892440390843011793696367765010784759503614877498514765030607330914589511561831530930106877343716537230948297722670600047331504664807253276951798611778155104755981370495827990079000703060514978045694153974698141976949264398060937057677683873921527294315104900525790118328862735839352045661365003381754588763301951520495018511795698940134830121394820331903762170594100764747577926090105599426418752349942212097961595346853308958705353165577007034866566293098120844048655315822403265446987744270752734797051231014558426459403116602492831208701462964508360464962196470234922450618293578588311565486214052657708486541029308087416358982416929215540906417868784984896125344320166368951612682116069970993482229831422094171488912231071112831138676448492381011658719996740092761319308820188995967397470948968399054772686315709494620582068908322174983083829119780873911990491275779947678901515273659890304828943117382884894192762538446494515974149489442150855602302549893201799871078191693429456232025790459959351817391727514467183441135847336240197694708128179582623779687332190821081885028182800289039186826512189147113629553194565183213417235657417577325859331273555300590247393490232343728171080338780214881450318007803735649280508311190359180641835468523950268682246872322141378551032233900938311633179164775728834468877132857455604101971165410565184820014822105310201226080632085727949693657336798743656772958805316877245604633378547589885979320688513232987007261064988047685810933446627726608717249943281672306360561669462712113491670641078993124346643670344917839245900171651301608485158626045369535932312480535754047814473794907067054969601002309886896767507226593020417125758143927438890544954155646815895464992138127102288957821294165589029779453885497255565274579576717791309768832408197643780221914302265311173588078948764568292506185578032254147233588143920740229964371228216836692824248149096145520987729039342875089507858823687628960870600047524173006575402886179947967104028355852489331132733658740851508316724612099842674273870925098431052207731297359967731689413132345354753988298963371609986134721994834170767084411987296630060850379525256847288223757124922190451055919460868594084581945833142737839727544977261467099489053900977655065637450238120191457251436133509178425511939888406233794311365995830953739515108736945606945815240598265791876630840458492760038832293524223957054994596753871939421207524710947170845553190202077466719214765051632861973374904309999779916833472114032838760571285506196877362951798054069967473805515533790257603160160880849219184518274186832451416449822829343455404139534868449549745789224093209886603657121548140017099003949387951369404359051420702056168229999600581415710016935110595938111098367818755776994203370122934277088736136787850413588147114797514180362167108266217225961200176124602823360568349125459409063455301428429567813993013813629371868171669398402277299763995883806286941989572198509681716453068481233128957954686278309002751823586748003507131592851027430180922591682777017913423342923469905930476337219646681606497247085631036122257212522857776034369013033022892392022800887724205933498779046556617709895476604892448388297049587799398311146639684091773427576426835653004347138639798343907112086057496763425460945003065216312585010494042951315040716279099305819488780536459233533178786866274952879106590508537296775167819721049328511282076986217297771526453148985980022911663595839964497170462381264469630224011052353568489205435942230185491277380287362905068839746039024682372136108828241940774077219235526187383527657222013311587988723179963265225711591311246841525647451154521775314618292435436658544437965592930700747005098062346100033473387164529709722030853303702575773745020140855057320769344686648198868421964254092464279202340458368094959809226062625717727372871170222402677235393368631875251502795010280981238675410387324107590046162090007379600154313172714868841025909477329263305466779597569811510481959208233970780488933012855205268237171998389440990725703955843173620877571926342511161326184948228890504362871316008023684602583284589618268814062442428221979931858728280072177882980755936647368669264509698838246232026613327989688041969612449644506591919649621269355966998089112848064794679498016597672157988560978360167017624130136413031872517184469167036082745309141339904727892873526439016711553201241778706494943301959592940889852158677042840498834047257421778918770824987372348622953528198423200498904567723639320002055673712444184063778858633171502368634848207856383631471364192617111950491148800670447734931568344276954057238649220453947602798186076774771291710057656512225950944428312343753129911527714521009356182623368364362377092476701040589919220106174953786614590490168115698997265307112249469609818705660199356774790034925836610107690568917383882696112898708602880000, - 450264567627229128525033869724028307349143806193195783422014214536984771770296985524095159152763804876125867749658249873789158339822854156750487199617933552028297988736875520665614326630631777904653133639931467914086245801099527316882482648223465616685216843083628849559971507313533095883579026827358770809591661743570961439973764578202360353759319616832137800711426773464220713680949544750890158941543879276223115261376363448839200283909795128150661841170818154867905654974611791950506053354126646455097886466417393757489088941667658659286302676464315071976293652607629517220441729633972697967591724604116340853537488133803067246377220452628559123033015504486047056069104788440376327815994341604970315682453714112838244949331456249999915459323601074092090134319008244901453417053943550428124688130357139079382340269683881334109156499161798856753921581186238617411285291216683409726259652820955489516328177387864292348889851152018530630751574273777078186264042260248730169178316309873677865454649962371738153124854586124122855624965568542153189206999897256058329599999724938613020621451978756751242384887615983283487389970934655524910672124364937195480014773324555101090437525599286248669217727530082024470745626801731306131943235565891721379858058813361550946034611825960662247773678586415361972644517636096220655877852610261163504615231988335341264979773271645723324486054507120518915485464973184046154683525535813982961921047406575153328732162142601830324865407748507532719050699034212594155313744297714781427943267610330875958342861694156312304906351547147729303164425096814104167482266033788250813529893562920536440755916021819851606826465222485426680561305760395133916313917570452403187568963702052875549042956779788773812520220499776068813948663961329143477536548004158125239834449013125730708025956027876796303565663159366803248827873892790032424998803768429361879832982240069063990434909152036817545153283365845094399679731967032722670402604510852587233977408595918475753945002520585603661785096202340382506533903626188216598728791255293425703141495733522928785622757184889999973975304235295821223292507215413096307747789668520054429746132714313532663427859185267575794095721218705820415322327856259112209177070231224642784149722176233309709703844467488450694297927357393359762656369486519316783355889261983879840832519622227848801631951443828723672682052209081259587187535934332862242705001879828863049906296535009583782246673120630443743744762332588630207461968920022390473216927652779017220686247159059311048109787021503009368540091480288893105895417770115836408748909163031136917566719774337322112318929635944628584881655776471157121031831289385852193601941662473904969759233864576969075054765734883856733476391915643818644122123246729289009564177470492483897186455918844863991234937744669555258848091594203184923104863295677206032651691730330167446504793834096236464957905641970014199865861821839987076074447373160397804256854337667666383832183356634040192936953770930708960123229276970448602123986068385457094701589261943429856677262012302751338178964932169177329475804538480630271000199209499428156663161668441398842924233217628234238695275499746035577943962391462201646185683322225353853577359707426700246973143503562798060541254952009251831949266266892939939175010256058674216946977598076245683261943456661405725214324589711328398564281410665108249049942901103555275816287477734407164823250619836513469722588942928548562138101735003700203877297229054216784656933873650435683071562431913764414561688660863994838406063808279885883917256368726335393783409602805079827020482095356366361867829966381015115866970229788394282487327077105446753939402991721272522648449846155494316391330872156475772304218685709575889726914257313258890101869610133942322121885035263070783334640519540481842901867453903824175562048213671248974603436371345808894908114428215071514443178191092424250716395704469610720358857380955331150943100128541807260310115641200071192945800286176663484033789813341476448715758413068534091521740676812566628276901172568897500213782155757878950937041399916332092607682465317381243450145394467969004948468170333072687181248155134487027565617022080382762127542532646641148230094529853548968180595081937227736757585184034595646538227866201391052551452665131158717969117613352194260969974345546525909461118094921612317540517338651160209711766716195496998097390675659250541163682019203104213544072397590889803238464846558220996172674900363380980379501452307752779750707664235885991713234369563778225936244751991060054915997799838929367870769577832164304434278631830842780210277725907596287805235058180578755827425343443437934899077806184246638311181821347456458235921021970492310618784691656251765502767788445450700101482853243510807002934923174202666495384029681315199361653049317392809676112590359255711690541638427167780100765357166350381634160154268354045741288656237657352941123786667137496889973574211800428769059488624807079610526999584531440036708846523064482425692383605442074444788116572815148682524264293308673428058056468897581917519421754558757448330847584233171696229576294568477224300876983772011305720775633700054493161092608823170478460595735004534363661894136606623035337484616792007889447705957130076852339203727583971001633001540877753885124236080399188635754351896288793541221882603954799656664479296884738956852815893996482722606000270031165023491533107030532194119749485778847955236185424792535130454127133755036221998343249975074796700206162836064133832413279669198897278109139214757635854948524686259737452567395764631916851844839727921957163798314476541614263727977886883736428867298476871382746788051937481909961069382130938216484789718964595538490055269899032616268704212793025754049599496213530898565605286370053006699116859781848502749869118388147242841982769972054420368007583015574106724542910259129574341255790468517061453232417927401018931408677608522633349612849994887043344802078324722870092257450240709365486430875756428879709720810552895640831571183626247022032737789829102178807345027897465361875285697494651427234981163010319410173043167843758218387315640415512080284886969312256171273170721979548477471259231149625448925636583076587152483128272298280061189513659954788287104241645656603355408126180247412886003879805239725887346886189379368809959851748687622014105634998762756193992363284038069703152798002176259084562236261589623623586658947558559148662474853104032461854728082797295363383806800917900691257079792571126045370299362093179392214581531485946233481963089768226082241027630174164103599987297828516376052404289748254836872184294316094280800008676548929290297520627962318020350255583336596361128573417697997235913516775828024425719791130648059607467285201049209324620095975887773665683248409437440091310838119440386431672495776327558302369135183979854259003714810571187658907006703402134465644534395328041457488856286171176464057035202737208747285392364803520451811518126403935170402198185600775388288105969595090806868669600071726347876674367460518082582129123665443832911300724429323739890498344706680397704024898410030523790499830367594432690194634264658055349220347241834500046709905819309591767648425080951346637496181226657363676464721473832790613940529179796326194530112501648914276403218010715551097608030291608663848447169731440561968971491352340116597241086245016074289340440148915144911941988657958026859824696595208072299202430787347206209498342861373196835962173487003616782803538529387211248671044806077555906020776956176665865543575831042930769619771918437162169475913483138863769615018262233291938410428365367650029341787683287847028028241070777277362301903100205677392357663979642532877254860954333683116484020754603586201554656115393189437154042826245668731758187616077832155380608008874393105024987458609077667480333904529478666421127058242072086442769099026266388736948332868565820732194655809417787654634429422918885703680000, - 9883240281529382418616945521753349518998462657982709332096376434454633210174060955672279845701190537700760571657727640128036671365371901721101747645311430883818910522495936645127947420298840396262305381775217681271748362315399364098650606240344211529151423682272027698981684048235424712410209221901734464900845328608353516518069668711343366463608665395210128934958210316975678150144775660650180292298770558308342487544252151275458703966351708190631580309470924245131698305517741282966987749356749230395227409958372417887988104227522093125910036128136432101390794879335158887165752366586259261194012590956929169499945106386519536430425517973304951749658219051453623786302925070360850483883314967368892572923674013402938122145356032177791419867150747562394121820040096931663519030734987057884527561987542678192990375208434939069063733224704469436886362104230676502842242326436223942883799917448395309985456659531643281362884365259240759567007258978856403140754374377492425003893898551384116898252271668982195294347267929433307519185753734900187934295490833826909287930720105695464767771612193389014352299406711477353838239437256539880878593977720752820633233910985223610220571621399062469639464892680365822188922932760198700596358578694834060762543105585506020003563812262819948561766767673566051601429573455161658220114573016913099315382649608891400871152849961579627094969908999955871768358556925719477160586782688009833191969017647401259404191506983160961309034778270455800974019010868397241782790148734068664572439113261114383296085203513095853315345368611396710692021168898314983332234270914213537200365124025251967266003867936746389687057125597866749447499343570303547249085511850245203203739883099925876986127759034900880310389986752044303916058823944096311874948020652132740299369919315534594534172272257366909944814071655788560372285447493141204137305611998042599950357314265589858420703920854801999823379411549866495656530288885434364201142695347284284388640882724637661371918197092433425429772755114264586117182444734422567688908992689045383395767617219802047953001536572503678747238487603061279168216246599007877164325865766750803103349924902453401578172174725450675483449187074874256830584567158328690248556606036207138528362002863697041991816388017347068315841790163121291310484993409874468106070081022652730048866036422116659772301580434075980181390372643953888569220696226959602011747083470276362648878797256520967717001062272402253270648935339769388474364339343983483732979340726335545388315738640513711443728161006201258825422089412460039365174185914098222826630934509531510011747091342530270050540322763416211009876774824220852964643948659591298702477444718239190569257573686263013901989978112899912590025313349812402783687851652330280245851952443897741740028260144232764501924250203096829874553703456331278880434865042686849309061070174977663910027676860647962728896645373140948776701222511037558230156693687405870217041755904820718251879844230169754346454510706368901949057860550985347362251811665934178673906229232650760142426657992815956448151067019775088570988050186898723147840106745971257305225899408228442707884600731239180545322132715068143150044253557842347039112453785263068714270901820878078435770125845395376399341871992943568843169087038663689773492186374819234425709358660926907461048419891245170888221011801612238297518285957079016175835576722155429447578297678765423435014756957024135183033318054355243517371038715671532203376522278772648065351185634519296884829927835839793266728187071786073627946605939300656730224686107073716350070744663266783392421859434847540468825996394472585747204700244749592912441543768550045644691435406657897878370240583407908781746950597973722956256798190731866470849662118570911539440893677871672195915897452991594981676941924765486729818949691430833704006144349695485090919483204389185369410698094874498324628770147227607908070752487231806303603684591309651159804221827057267727479441492706563762722009383334395895190962350177835209554270540015511759359477985542853055346397126627855878179500018928379086974024284221143944280007518462628613582692227709795464491347560971218784807363014719640194886303642750471283645390417689614927412613205897160893010440155011730222813455067983099290006287408343598167716006744552694388642967199336121868789032039488620333845118779353879500277445949436968148737207318070345750704946947543541752124760403672551237854194394409423518107330714845588368470747221845234253673076332582339430938878399687292324728289848549070617039032134978332018043818452694029363237037781271975852110114419890781658872761994169554479063143828517433112992376465505392609853457461769451930652664243776913391837880564249492886750646325863803119167715104972363192572012137784371038968031885697487808493196635238926386187706692832544990308879787631379845002489247417258892409830137131970232079943921773622922827244111902134004597019590196541906968118853161628645701398980955210763586021658521201015681052516355224118334788419512663381834507868013446094637199648031984364836303785888153696155709979898849793042157230265300194512249065164065139728495311150795591972266440688153010751125201924249171114261838901061633745863213240103645800217362554895407735945556633199913771369646272695413011997849514909398294899006038177658929646175154662878917413752859466847250568148754107818853284941102876499393160208835315411283269766782410440338897523974032654723238175151410399588888558682999054132037762262874285837963505256905435484657194791768152913235998915593635288572127206070488167467498933421328320898825989840292867319022714808165903469191137781788985047199839116330875759670110372306760973140410954153078302379773627826517511246229702372026047152789094554865641495127143752853574409463669647931835747566366473927116392692379683934318126680910893128411770724019911673532143481686138945825338720754173991976107121793966995670226689735142721120737962011987483759018508462880942939054803805309347332392016500404514956606092869462211971041239607529033255005803213635212601264070466061242060239956682097629450522645694717772280260290002276093655957215209170662656921761022824970670287487551390635724184076427073305451951534378659199032726141647444492711988814870741046468549976476661973201394394198758611684212093458985794653802379155819419983043193188675365117773101159042452943783670985981099580810213650130026828140868059605278014982216605914481004393089270836730508755411859388549027892010385948563307331792279930064014815524523065964958855553698411495362216887663482577509395612397217394968443841899805025033336039024437676545881199635151367427936515234820882273593089209909537251025389451216281399174952810500013370548083432170325619805824632121402096367901109668369359977774537885433922123407415064976047053401330971942906354224145361932964740129990132234619042114086123531639666467485965766515919450203842109386799207285561231841735544509904913924108590044402216008595828725448034577701706773819668499849834566965901854430902162869920027349368043639045657972532971229367698543153021374891811870333507237643659526451617480054522998288640739061944020171489393957040557089313126657870468997297599031033777713317079820093227649922202972334312489025204791023155941823835415276028874115509994162582064913850031764405513684312265394340794916815413893830108668892037741672379083135970433120071446776545733145187075813548214253055099122079956167616140362809701662908664719783718692921489458126251043779954205664780085305712536982293852883118794812875574366969115172938011193267253640491002644471452297359014870818385227678823109296047091110063351378389451166284371068102679106862098842073313091754608994669800261468600150134474357568608609442110210986785781609488506859850958335213106399601267111132834113571803941649903318136705190191948998581601238055330936764194238060012568916373815241121222709608705399410573694730240000, - 80282040705863751760441510883009411069965285537468449229740347711757924138475068007462959683705907293215305405078055867745126609534408165053371829392524707749207068120579568442159239722718729576688446713009271013855833470126788166522878406617736584731606047647912494760631450358823460956580099719965361821440045406350095088022335381929584205469822913130631385216469873221058749204811292181216518442979904250089206994337658581660891096103591825204779786769606388098117555655721848205204238863759634873564865213376627435150526740450638462487606416841889023207942227992915486983267048247499564022575921946107338106084377980856298992917885224415479097741404123367501350213563859947817386383293061337286067167640456334765337301119458357478818681622916424900209562560895736667263307187199916031897873650601414187268747688485859927999641748481364522574564217022544548435555022903047488066289879869586044750629363627943475369254623881189731072379009125535759948170906402383332815934851511452030796570422651113982907519080577151221630378090813657075689139711099225455063636438593504600293164738244879910277389926175655758215607672017326674164830922438513907321153149877817241572640964931068326494076051193532431646034741531602669823404457358918201167458387345110929770145334397937818971484962042922533389628234537200392429342987444284397211836907772348976447177460614930507093039570628447186031091185116726568002552014427986562603151160011207141539441427217056373669546980295481712053930660950912108228243106844566547873910865287073095919988952689424119192939425612296177685528870927489380044326256162887022464910182332787109496651071284297717851004910278551272142755075848023754533324527748134719166641591041449148786065578384028485754919316188367943087852796063060747066300222044523226710192058615920925111192959907596566589429701628262746733729665756160044611492010058136686588779524145642038361447381648632730871957711495389928672364415185673510002225854917737308203658924543685916642424232169610146440587654996086823463723235322866553609726596461822154680487575100246051668286047696845822868428488304239896993884336641980959716142532765761401965287343291225894059749257940932083755147219303952306513345421736111231050609020621715769617547365578030179922030326850513763519538903242421406306590100682575514929696475061696531899728002697000167873298268748577949753402417355027086551704142507473223613914449126414143609222069996456313821543746579755425470326425922921674745890868742751496866580718871752007903717318451960216464564489555634484129249335139936579806688006368900635767481969960936648369221842248792225171691808845284492530266214976361746982463594464408144226982930511645931518483901293014322533905558094987893516745507408832192522334422767872419654297928257534605237203369059793655888972419616055709012788883127485898215901626728531984559259356617944714897885993785048084096403766310912075523665090039864201020995606533596168603247821500564546963282221764337270578774584864458477126363114577985711101024292873659564555792732099341877832752450618416471068980614066879857756509915287316821224010298847506668375650105799729964337229493260551840713527814571627847477541935529966301260536678849055604717268217083120502970410891251818090818812322087942217116451662059407071064140772704451945004841021630289383009264707073647232516147494051580685109951543298681549827035837208032784826228565099289958570565583206910296022681793791634972863782029248317630604324779716788767628183716760351472874522569716066685926317706921695619141784312023233647796179340103240515174408890063233939785220221976244082927390354570459844289138249363468507119069941036245301771586695047691170615168797521354271681610438530595989336583867471834983249182910729645123068754897901279868999396059375539132358270623567262243427347042171069681992670330857388962980372766573148520287901903397258098956404192383737883014487632889521465846614459031021879963295868957857404983613676047976845872736819783481833067275777432566954230003435978810496095861192991642039756836091770985645696587999667938640433687306229319997098586662875452327203022569741945131519457499554278226616241963151477592312481308503941443914694047498127104243112765031036410424901194551908196437653474142401891098907387227676781352820247059732062794953051359593742898056874889403132661553244157313045798988294470609177167615332327861065451190589158306471440570493815440492643431773364358402237309717306951653372300409381459870857979875313819177852785804777859434976828439718078502473538726017963452176547792931282936184141431451991549083499919281564503535545508520557819880478536116140466797840322222553347653321708042473947821318126141032866485306942837750944038523042788824778308013584517037838414385091875016126362382515034542276710288192045700173545633045134261052877099081074918800658584282109158924891459295184498732970482833568420304876634224346444566226120417146485097298985424170924010494257706341100641756826318603965028740204354502293516824025719465708610982566679646216250723830385566018142025346357604173639896478896250736131921873401611255411654543062533083764569245007741665544292374728011435989460687187588591758294868305724030921522621735036104833557309596751502087321041566792320981908417557246052244979637205250309639221914021469202962023662153793603119991182167733497271428522673357012291359423857800225792234136361950789186565755115262735238930863899199494172984194852243588227365361207487950654417642959962375297964516768554569156746286637602920187548026930465682759538904836172125432259951673133244506531769109834974870647757925583477495978010168512459243947256641867110539265356788420291451683025835884620484001207099759678928076597178608419380462310020242362278523373152800286062906302044773360614594279153042945084785358280741577746792069162262139472189577225762416764602250780519156114062304188606847536897709337866781091820983475183503673178240652195183406897638674533495062140444492319936527392629700814834118997391382393618672659780720899330779430305885309455411492525947484849748639042062179142540413237448630954431676429024378354779931923583069142901467643739371152739533989565550683766260848635522195604284661176340159008454249496900496183277183300679971726967607343459027404922763519338244321701481385543061779018218913013719029411425447374686737720096525564701989757402652986126970836044647528676155102246564378612129674491032208404099134074410358325178751097224336551677135382753101825715208124450223190770075445333847912290169365832202233337243794832859275031837200224459599996532747484125366937914856507050904451934120589827850519633749687064290539764173401578900818503214736686384756495746466913568009476217757614458056135576598521263000907097551574031579635140452467506549122654089058524743420614348209229817255356749201092181712071162717259558195289267551084550555288489427973539389701505449899405318883140495509415768309631377173754859523704097751846010840453812329281725727653452412362247408457450782048506406763388618873723738852207147795409261654139116663531404171190847538677912737200148870619373624545615399503671502672452770924182923464372571680452684720397312050377818017751865845579326501553369809295191295068659380445426297854972488504187736320726244352569715912282252410974799964161492181132385893633835561150356818062156987745494417321287355005809655759782924249914375526875108917626151979497520128077533321870901873801373007644482687433750272907155348509772486915870716113988618231308850298267890579691676758379196923081403352626208570595644851858931217092095738250410420933390636744805933979844573570474487557011027205357003064746629706152221855969422337441028127566284874890964222111867214079649576426026937235918213832580579960437638078954487880788035607017993782796066406206120318083757877058274359078057991012116156759909797985783543581486245128496211729275944960000, - -2012550119768515484042641469365783054741330964576287892024675533117836875491893943075642995742558993838992685140281853269575175617048130950021155052841861636718456229145975830655914620941104220121850737705947423308522774499067101703031757306406915237078059711335389664178462823474327673608785097791241371292421445210594916038357253775747796342925985987497680840868575248038736413128981855113097711572898076562606978955465956361291530333041039704708877170693108420675015571195841582516906060097173827443533669846343944695477000903012215377442148845871146518331400438875610426617863914261071320116645448750433733880367973243097642599650364704330114365934538707393356452324069864484834452225810971567862417771498529162088945734064827546988077986635182975231765775282158397492019430205412005757172453496453426476020857051567875798994319376417797177860795906075885487621514157400384969781117530462128186718605643254404276400502421060361721825987256521291595200165712973373712757750154275585128923116929173385344803125180377105390643299662812785208281046544433962776316669787983523500007047297573432783723987306565542242295609551852313018603618763503440070471526150068113660516755151137727985136117312343435418215748136733064217273593194459315107938246592418772322392752975474681820655720866054473031617366849989809822574024561618358707324710980707166052178815909484799423430492761160584150868646421817518223473973805027512746261732017995255283294814620585158778593884279327302629631073982957169482885317439657667790595914387000051102278283121659534067085843707535883076975705155095525227507649264618917755040102430554001397920521467279119679790885965662556015337557140518929209817360834317655138556255834000527250596148571755714298768319102674870174511305329140838950294707751240291027323242952680796180374308476864882585287543509460214750670067402395826574903809012464328434010865422356981673239214679435074590278787828330336576936069835288200814511270828518837596850620437169529645489682866704296677574348098000306196821718466841742914725786012775423440284220195916155439312219450187664437890912880019500175047110992880850329901861693276845754278181273452612594205482604855031145408462816175005579340851110546158042179551637779505842221108067146559906329761696032444371270247705645942923811642836893217660922894561991868820359922504095734455077329432687215370120191353858929209752208068953984261964222859624055458318401564153780587550460706479873434184508936866196038821044572725569286007664047373873932872634756598204170609907900377485411971572748635842712112912309996090830769081799183403707801211986480662169036832925036830221073046588783343234649686746316879743342827073093252261126940440313675046321743814991891883732667658683710371516712480841398702702024710981326421153069086278859306011999666280648314142308569484530504845051123530825750572841849508298102647818647115237878699060389134096617220040151369204882063037841089355435053139098530089047136640375710430239403712744654640137589166080050756116116665281151593996168199737189336657022026726588359340626544782503525139991844783766624760070417512837866246158704158528321508549729523460548762204984637678474923036027307046070769777810192049883721222454503585682220090084429833980024140659687907837047712862700977406250905669429686603132671699122988179626276045290985200580263018186884137078290331584921894319916637108625870978810464592385807605990602624448791444528882497318267325441755838833876731180946111547208925176387299327590650375469452539376389448956855653914325004256926258436427193446431087607635252257733071505100464707076296170018729560197489837127731088223978392775407980223154585485334232884865078616117555135644562863477750426751451560883004204950053981086244575303402896040685711683827553067605278858584404884475819497768442906521081885722429179157445551514357360686720005630862120028167822292134362581353530572866451238847254212851833846394893560332964868814266468732527434273668287917045112612833030235677647212106074810711813499143225935410386284558152850777983400743644904963420536647782003018358677257501169281590984354729556250024770393095000397239091122786893940281820196566482136238473849906611510110447788591823177773274939089045776847157596739702269314650941521677292609129304784379815531490348804224978344865268012956047499907464406104411961245847688980025598462004075573297918304830506394549043707197485152972072519393692024707764540803218409553799654441365272047792580544207436795155044550076783223897237761004568154256525542826453598430915426122373464697555412076730663305303119704155125810822745258980272273779050637839140119281108499275837458126419967091330772951135104429410284775261296506936193522861365503605897623400410149938708119092582808807325267397908810889130553225446922461962395906306827517549453772630723979231274016460860639189061027445577112708391013634527305214444315030675621236493283986307155156255139734456916027381140663088230600135579722996116095515631540316220491941064088126205731875063457556652220261378862075368033595904142162217323308197870961111445315933065532410818578331525136124386110845810924767393500686834692423400364017169936547824873820092387443608347394048535017553404841939400011449073523494391161324962292613468789910353867575603737937930644972342378816332475507486289482010119281590817293002414664178208992724356920001956062105016898400218726712945252167629975033884681952180658357691892539086209998806769698010259776571485058961448620921183009086165559934626475855082490992721273795926663391838452704493322338694113022350083210718753672538787190383844524446539801879804748847323612681309776139658332619599460854174109186694501941098265104650512380722330494351961728679909078173847193538616011434336450712449602272624802635357713261451989924680070800094278100516519708918979005797023728366253985670308259034916524866721127730189795436073589404963464299458612430569357692575815085472272361429085596374607651443408620537509264929444691072430182888612217670667396539508904457191394565731775881271578479586154140425084464672071670390496262423855844006207727204067803888696901615091483007513015818758090633617804694099635703197068739810810040316813002399301830615352479361891087669638757855999242421379423522876592027561636009674084530142217731544048436182417614575150795038408493391556176289687559197998072138546317133740790293131338509111634338236881293071899086551714136835888832098997176816797575540963501632662506441208559036034607904020810195511388443524923800703189007066386170652848378747994226318830242361630680391722828383552348246650088315131033445122664353261680114645403056644306191691884463173376003345774731408143478434038643981755891007672399606725908233024981611911648130395498718267791596279825148114158797378717544864629963615525314789017125459471179648102414959190531918607829381031007570804350200479246026001272920111829611309172793023380283383412747060876904424729482197548829610999701665459304061968854385033259337415612540907334549610041968329738468843168728406084815506063409538951796564590385062679253109859519368821714766798005970820713031278137740294643259690279533634813637007812819199122781515303966706107205495861463495740543533450308301406976806971239202615749201536358509127374271797148340735235773727632005038555634350500358649166176862069884293165834804644320429464626084527463778652489472150741583790361230941510487395970668789638359869181684323322350497555602560196311162140209414706177453066657851899986254714900168774899804596553661977636950238527882696902797553155291956670236198583163865917740137961353039421898038178940493906041094618491367933794994805950059777706099510011813115950310474860993142065454726653518831502205499177932902338056191460955723681396691257112834618371137835920213630072686562572267065475139477015479055882672747758312803503925683224093655040000, - -88145113476022790270081074810982232125882146493161521764992061385896810617811805902649754521645621284872270730078694366385857667914227525052451943986855617135794160079103110452767752868254838545561547945380045324926427546525567112263528785592292167403610510431298236354269981187021152901372148138564670944661853893140752025025821443171627082734024695074081023847711568288954225969764608413598823477341962522070565873984155547929614403744145981380981694436858248162283615125099294013340904924366312059855649674954786371190102667400007448899663636208509664444177677697322749009798294219837296532752133622978200630287358470457297200759965492486635436212503870002497882288622999944054809367871798063170683865666690778530918057078595642117957272847706249303844750910548309447035068014979153953697041715650666114061214840364443085145991166483776548618035523553971177830844852002094874104148500983658119348229198137156726367446860316411694375421587375572298662874372172862291709430912859240517500175154702571968677447117963916252761056478964307205860304614408208106783983071608597309435271889980150426973146203549534265818424438871242644618888072702386272503086245672773712887381827004771055568905558881338130870631108291560550097064633978353009973760824105313042296845342937444426227751424652329617673598525633737851727530965312344290666854691193969300042691820557545197660670981962386368454811614663906172555742650581932269445466388723826562093810173925454059394190084002116777185382110193104386005733882109038777372100328069430622204596256701146913226906578886334950253000947625081324741781252237895914763848635701434971012405846857334924660079035107840606210023231420801873231519146396645788952612276981365661205559218588423378206770778902504458561385584324354777475674007470928384006900629005701199212047260344046766681774898495536348072013617563051581316926266736657436320304199852719395385778904136166087229035407037708578714579791566297575765359735720531980934671214445659166831250523710550114389662040918562408997766324063683533144822558508464448616679886611488138697374617367580715385899764914889669321664229346070513702660412087874135115180970769703356047491350064090873183035179593515723511144612145349426679829988926275493878218461419725679267051112167328377701433471036892089419802124704787383132311681550117005149886201576027916338598964637433813430783858113000677019548478472341615296544144661471544062268091472410750817432299940673490448910811192535017068580302772831748584108857735464078070505126040394600858178979534200076456489501558950441504384036532480325014775684062035739068324141263893643278217468007173544887652018987614306107131361865646538979946402739956281006923613562236013298200841836747044134594701618534249767571917853104575963641662558077228855369470002306139934632636567988609284449848744731950445172848583733807549894308732869134619283733247274528739660389216150364681136787340947682933019300869930050969664517131544178596376910043386533148766325444179200787634818391909964267036014203303439352657051068483294143683594560542328940176480426807775545307063856418041867938304807813346958697281931187108369669031410645277996423160454961819682290690853213932704942519635639097704483076121491576612091012104353212068730915153491223815261526335183034385885950234309804454742077912618560203864970378113848444595088388857757688777583614655797943873795247835311111384757959876037830559753434421654201226002222285423250481765031890395428946355167517486490187706809376988966533646493188220507573460393378673399909026565383022413259642313024501266567665729628032970661920028566033980563250703213924275484896468285229338428574667264355172669914139113588159150547492810514906585761641637941956666993908993831429309115513901388019296431571420509770129127513185626485059996452843620649576460136555368020584741075231447210846088698107069479274578261752166054874254759635410715794488220932522047723691451450168787877775379520452316117630169222595139301783268394820135124727597963076858041513302100689586606958017452355638760431279943109329934895149247487857369815665086062622706153537603941048340828733116553578415615017298354128927296985722542222919237974839204969582954375735581205257087527526155324626980325679001242700348059764751660167043011612920925096454807675300071431287208361692862667209086164440018457234029690701511274358649191213766113105623639324365471349708053993350232311024558271376934206753716134204511813947023522080827433827480739825976115695516456882777040398745213825888188783643604507526859744659774946521979511110670147548830506475614605058802095461318644646078857235175626281721562457132587503018279109106035434572482392468319297150959293345478981315662315887309746212755527885982553454869183200778641097103538097550186361461180076872565728011904023909944995507660566879576979967027414142523278828281762997673962830983714614939836725886632811266262722948615451135619107220809421014562654716433707643709133137490807392956604630555520241179130318095912521426897662285590728287658898430959726406697233892639866183945609348383738163229503251903384536688914293351683879197051358040486759375058028635673394833738314617726456754251592986686795486997979359152531799860674303685689459888624244070287218296015196058773604985008087414751322202563181262828734102254027084385810278553987077258959369245887277870434023175369615149326000045243476052692185390126020814102032097539989246227621533819511839803031796915591766737620340360736827065757483171047146086239990162939328951795277348666252883499591928221116848623559577439010901432473925782336380229219789225910594420307193139826742248845678598893917493316010645981664063552131761424456508287692511754732125240784013918609792936290980250998026057870393575130658816626893370495802451249280507981840945463862213530961802071749689560782041288624330587548507828429945756526607695069548569397795744049783258978371538942387920842358068872058193940752658297246002812861177489543969973095294786876641652586386492792991799791801792377491301168694151534699182052659515664992549802266158407647425629691869351994546786573633931776484140155687307287514942236941950684322461183486571603212894318213389603121852703751894662083782232610609940399155365184175901897700710967241776335237136737737324773616497218242534632483441464336086629645781852694016835481963451776710115218621910844204102789123791965162094971591228945331073736168400836289822122420696479547650417269382634827710298159274156631781940687585573193986596844251438822417289257936101535654661111242013370672477985786619079408691185034274333257536826386691831089687245372430475648827790585116768988928660482520450597360197757848894535736125123991476561881767076585922225261349963555319601084720440574540567193588733499947356877790979009709964896759339687322952972948896148907747874512697030641218108427321913469934592854555328392263406974815807070904556409989136525924053688603174409777376885806991383301912521321163654693037317481874092481868877318516237738166837621033240719323995373033363435545519441430395717860336997845526253149685925531470369653678620069074203797485696621416000832662628320876250640529859312567847123143698208944969911883766299108445375693745305816266897852130656750553233132548995062296728467148883708692075641983813010249475480123065713341456556359276655604280200796729802957144521385416831275942230675230472452357392240676056653175223250317305669340664215116623834285177877533831912881039088832417430560660645831925187560354819161777112970835077127829371841277623632632625875276668033649262269088288512743685886282160885527045734100872485412064726024408040124218477484964861899167733192238277224282785351489109028318553285780735841161643883820145205958022256141898038951946593886463866528851104869763550388158069636479047326592605696438999434254887157760000, - -1552525022979641141230888606208796730589959947085391345219364765830858120670629127686138537390321650678143388821594680055346776926787782823291946994312720370353791539070599719496464690228958511723998789678543717675664820337201875842075143672236923351733583625034501610945928326082697996599142222983486367671813894601533160113637698693239203675671206395704679228272440630815445656769187471636015783664640974086523550372648345827315750633884289237353281387587343795952356344253636525536856430355162041824253598720476857412176151710119301544769103991485987870440672902220943523859479925098682126139854789562463393889856717702870588026963071143182039341890228918676138936127075098832171834721049727214813589247612441106237918370434637062435643819708674737515561070914534802289470120591072371728979508232896149381251362683444553922320075450155079947838019929906684067096433879332153830939013291088099877086650937898779617164862406952926853846479413977874566343552970953721986060075215957851164879778670187262383953094545841309545212647786090051898491849499751984355239223229609451966774331548662657691258633233923859022351803289656512164339001360466835258545720766324298604678260861672620756180853205944529735567375860912658502314288968321930496323161805894740471188054923344429455321395733767486514399587867534975305319593935143132663628081913158288508443245310268658655038541502779600949282543280251643461050224928322117069351396902373349801150691621982935490167591096974653674724080567974265861587496143711793520712840627900808375575248752338320604877100885155776565501736647166888609020678838267425367808444803047097473551565993639888251581861383790682655679461321713752281594930767583006750313538415768968223815170009119595697073897799523609836061416970427585048402563217955004284452799726486335466064279530584870328997335105066652424945442604110925069275885183500911048314882070310585490474244592392382777772100725872836748898714835000153224842509149794378332748380589641945918384464905163562051257284974527213961986772129513399063931579367333649692475188132631268506315919892653989060019703760951560327491558741368985772628235626330807436696322859821655501309057038181725568183369373420757123634895058004342156026878819284925760810789366814976030769512998541188694642979788160942809458461826090855944682886726019134999742782250054696814438548355989216346051413052934846124715864707444705912545445538872486629444408172535255011210264341141819220052284955517107886695897985473648694658714289094327066169037349590442549173682123486837872979484252206515583954865566255600712140958687447986692314863966199093607765048877658019714408272562344016283814650874077751052596070215192110529248470040895589625048109734998724735345132740098947488340438420914364287836783592843089881164137830792253365609126179945157442846858931699831109220718695330686996328625670128225758805421151421548043459702349415788244541268895356457024498747680822992152758188493056862029331045469431498258590580970457525089408585829681079008939112792795334502840409231280952952694734016146316398172151721490897181913644855408767471272429552981443196546358089067986281595608887600951741795946142467095400213692525195654270940821933028890643131078671717200551650021544001643742799875541246069272049763062454755791910738654817216275331858828593385520506717419043642794499680699835957665759384636709831840840429669730281674550098208032220968132749444508842684375863080994269499507382740976984582993457934635345205297166447753313195311877772010762011632690673429973505037646325074122523215834599179119775182363981501780977980218519997496790586937767551994443752605278832209981874185141829215067242021707811684419389561712151261987934293530951688168897379877952766651129514322905148702431443318680795740525949597515683265068561481701759905193662402767225881537193274449054549759707207732693590225576575253229245160743197763414031946815638821656546388449156609819007007127232832833931294922939880190411362520346641917027276252330759755864633317829046846807449350843078752170636728916269655150456139856748730051581105160081259374051980504745019836869582771365111920126941129451624729507814788233568224446499638669297343949474260963488904229194355370359881083184155869710491128916795090188504954863215072280131584296349402848257377116421070524895500906560341154601147894578475001132423886434884219199105704218567876377768476977525122346894318775190991683692708049225336665410812605474658581619763955429760025973506835186596985428113266664757070839046678892072325096261206575424250732185627384145094910072295989716518505040669935145177380174531881157187046807013331078768221836393733058784782227720411593652148091369973983720595926349651159204217983934343355726007246751551365525960314581441212873064866227850972196188377980170499569722332818653400807910766366957528763389905785739441786490791854246141495246108236492958519701096757551949437167224096699580738560552489129450727682310479461060240728291416944510251250575519535495698137007355283290248059910933008133641821113081366561463707994679198561636628452724100750161062401055328664953442296078732044561334764525165234177092688256160166040417557146442538730104962107795908332536007104432112208853732001769877997710601560006043141514481070608046344287009484583573503782966509036796515312885443205989331500779190953191786591621004001787053046448808562997817304018944563576206370184238210831321851689005231025265096046443899561953700463771853493591971914255852335212966538281763192993015537900025978098067962205569011441655290870313407463413946784708634332159072355769718107891090908175278955990947452198985181752340664363260244599375481814738810544202543942218279230186268641369727227663182796248070541910197357257003477423378578278754512093995977444757111275128568484742982776282388165765965996647031249598454029392598287106445505817783595293962730563752891789027677011789632110801391756943243188496143496662920437608832865440137692946659090619822002157619289199368647133240679839418473324636414435583459718306851993262500292688718177122489743217886780708690978507445699843248282500031345406625281595167292517598707874743370407105281537854808706278773897969698178297872396622343519251830079213364222301494965265220809697987885384690362052526165458622506088862967722976797020572043721363163625418657073537671841371456770703493675707840392990543409514898178102135977630990189369946297286637118787932751706048350851588736548091134968360185355812615084864674715887020121056271652884422968853790821550838806304065344254777290780889807407864653909767583405999596426462057889610651466811662907027258023390994251175647493151445214164942001473705292120933483351026937253637841010301143052978411004936439687316328428690422418220839886641455256602116103714741859175593296308750293429035009692221117334021034080335149368374670297616409263998866539532193211664804899225253021966315356130652102776193825051421554956522270079405394495536948564418149124342821545220572090314316547242547873716226292474166418937810564319116546498412073386057447363671945512165094693047437947977547135099862056316861763580616692454418432699609467090451245657851998397019525923486240420875832055749097388275437329994138584732047147697172081791907326683990572476237429125572942819984327666139594868878848989463449074822773836125980342207257945974757165844876925156606928727927699860673557453135687727615931315802495901209167767565076731455773860091269969091954565103695773210074098249925406925756032727707899259759078040957278007565353513228833418967924765258347436757700307048765836094441420801765279672642584472471501060144910635829881691776435834915324622081419645466200620606889562849107999887849000163456533426607034604273067990783948869957108675112180934597554981510340208928223929706512583229440000, - -6781900129748181911623132312580733766995919272898310868042035468101370212912747466763140103784628723599208051673382400643786002133775852378621057649944261837589802074757911036450468886277124722190970422448037259763563861680297363514387123743177408123414214701121991424532008986132243886408878898147202467535821589987189416697070422218184440684597164450031191115121561054731596768442218008140193874797042264884707128793199227522992244900693162464889417833869602663628659960664071514032263238840706993634861107777333151050668030555661870748763236637658765569166734251550197815647281854822939161620984071197071632602500982111604810673655557824729227421873657168593251365498983884736542774227163929204991089898063172265560853791729853622171073340584115184982220434792357086539406941009775993992908210944739015749523459907409547187803762271080017217778126411600336192462878814599137501555957989416495916955794444674867840825883775035639851037745373506227623345982309817580021652348077897956495155332291125076777539769647054729976223804644968200806598530671308496136175694994261245352947239901509077448950337213337885132444872820793707487630087247629509657170845187150264174832606904986041962622651316031308064391953725626855844704215264723650080910360351960259455749646603312056552242743915494421201848373687599790676481919526062470733336869883500570213782709486451187186894164602482333504061720444781988350133346643478551205255308942705412231087496231766307248411302535081808382098125159616193709063298460423449826159649260780369652177752170059570256238856010805424456957831305639622845690772199385256767611994320310901452257890465183626742443942766681971033031237135500017432159914051441221860386911084552058267494058045018588302008577549864724388106632710082907683722575251133783746604141661784989963017676111143728302934213250423397648731450107572684779588733696136039685696633792862272917361553089147920418971202055560942834494311178801428692194980310661984268864655544248596107534165588289819631836141190790767694615595507447484327289132948976704242276850477762071940125761331955931943834687133163152097189545560437796816814230433128609008091559098708623536717654642985289015498818914834438008444697761619687386521958280446604581205785930448561176720978439178036372914779373051429120215396718287375932858948259466840476181355935912940077371726478165552233859176194157888695523377438137127361566907372178098794928073456265173679160575941608115170199692359214707152334666048454544084346356475786993394036872950720548199446707676612068765311901107373380769651361909560984953129585784936527064508285794537104833103755379968620911806491451617322613288473988048794922548821086373723884969530662618076219816616809866757868978516930914800128170167285601954715720786185225552946544434785660949658562902043319558008962915390735093447088207132669686628252255749442445005302967051728274546811762297905038851528356215711996835463911205461841036006752002884495927409616931645433924852935760959833436678962885983569400194798771272552186287983473335203715616910121306760796034126621854907770287096079832696299977408483079379369682480574519326334565230592604521424971851865424435337093607338070486880865884168326764770306008239603813653115951241973034185564705660070155880808476420198091078903214590910313807427339035835021230728832684342796807023503072915358504239683268588479233536022817016620729955215779447794434503773064927861873429234463728606453782261995872096068107236698319271557054311522397153809582445721385996460220385066706953964191097373761982632575932217100329683219146786668993556583538533286589857620872438640305408732417920453014499073248542394058840544349829002469863259004997823554209273647038928417493289865727804161764076040805231710019194737010408581723260314847888547793621709970890717042292812518276160673274630679634696202087456076304563729960964762672569108498728808063977930828951774422226981255400135775039716459529005677603620195831123861378144741077198006033958149689450097800661126399948776059690730237299213573119026971792256713417376240149238400554517062083192891148944492294190658919425870373195852443811054114430695150792046667255060098436475439091378219738596612894257611569967389842839576827378167354467606835622203111240634148617002057068542410439186030311989191404983571026058406625399524044277247192002746762696706947244224052478473190399046007606074064273365497330833258169452785234390493213109978735987051276822700827894867681497360111792647205632288265206602381770493899035091691288733664754939502259038077095207687022942822632749056983842268128067496431116372818837159923153800326846666593201038429787647097205164857927222211127485308125323811781419162381202523829133115795736361834136614796793188013616256907487147834000222517903464318165851980526125325422145461351921340908480975891043931797833296571123837286051996114131993221694123516440441129077627996149826021930337180171965236077175447717907353899281712344907395488746148264304057470042062161594885939317822412963116868936688853533432195781418595211178808631022640806212001283866654354757072097992447753687716478127961579439275270667792437453951414011736168612069156171620802854501085717670297630173873422491340344215334275892238205828034001515747668173766337465669104562898941655247166277939218875620160198416976679694021998547622783699885878477209040328255814299573125638434906350955428088761626284110968853247270984610535337899569192653499644928536120077755519354628900447748218136796303051498326325919963733328099186495159920669753001418611167902768342272810286579549940175236435479374240156114982225427040549606265064982182782787265341867425114159938811839545482894830732802368781014918470689937299838623990189453995483533129583705617069067749457647393843301955595209576243499684988689785934430514688194732791362129547135539701762757350128653601101404483521849082178946300058767764124399430139509418432350172500055527426273649473035419612670392349204358185877047730184456054200272893762137647228825338309444233092842417377115384758542148915845377233965389236398163983441666518654428454618540041431563529854457886123616496278024509368758669418126032105315724756292393773590306291396798966595268451809357306084737115039063725825826777313029274352806226784958694592881412124547021768071146929230460850227220070866447882503075418728603551372060312936884700083616716746900066447384798706593096692193644291838970025922877602792265731077051485089418191924200529955595238129082994021929950173500801195560687419537664976164072112100573592895627202172527022856318573778081647288862899703757365129470706389179981907807880582724858333372452063699454915203374481899850369353551733621152491482863054130011154882652683431853291005534004696173690472631753527630185776084395544122000101546690329858575391465553573235947804690707337381675302439002661997518902006996084968898146898127779828784965691152469555836640534476404866047751338305160824681749993976376952482862924617789634468399566424218201124091993441168600674103664482982469415226777711556810229646484589253007008718996767589612746756715075943875973573301315124370225791361214583944398751864839697078248565049724527435151610512544311577115773113835597015592265793984639021958937422356651871845840091198527581203031894526011324398362610430621417615896234240273797916547831134841130594171724971226419600548575934281176262094292079485775020875554543569143821976895263177504109202488855879638470076956010874613764982121774912940649015567245785141281448627585132285258780444914911821059901503771503746993826254353448308065587364411672459763682719523811085694888364221481512832475505535778935897467827401610573305748699450532172697462775840441286997683455060484496371968288319043480416807408965869852475522736455680000, - 400512327049073917887423969103751772441175078238070076149332142983321417321394430778335230369900756872936223978856941761681453401506698658850113357260201221981475112049157061166031859874248013084949991212825669207740023510009763767346711409177908127492101644602011256287244110640671131536421352820834628940165663416169917437175002615682326574538025879730370769443434211161313770356739029846497912829074738936342479450078181867861333133976490944145465344230328494966277928362519181857201925442827029517938683197710205397530892563826883351161317452117403004248984225773654951661354638431264611188514999616973527510542096872609545408791868220923493804138397972083940775149132305573432399821346327742627866879188038745875453035817703213203180732983593473821857460486428063473331123410712387200592523479504263297248090570799251608713517883879768641059134306516893218682584225583707159510535346607682102736312703802019076166520226618099820950988245601464208226791126968929218610144371733493708138676422072053146991361787737431224912394633004219295553952069043377181087881640037731838869006393118214520462020403410711192121818717321003346577650376163452627740487889403025736370431189770404491793361066000510938799650752292579685511479124889860711456993705240425388472580725727815515343600109472421726905296337733183718021957045535348939871631954483812114498790138319235795143344723784582958292791477544619421985701894929050902125408286026994512245482512510698453842172201585168506323151844618826079396331207549475803794424147444072363448069322554617638383379726360099260573352279554610183730573199257688673545443659989167592373978308958271327968164540581364057618457165104772111329204231609482205163500590268920583834175486099374522225239407131169934782975656794660272130338380815687087413391525654613015312168873906715041554149345904718869466722371578400003411110205113342058583837711436774936121552316590543212834659586452334201832481925705122158318261647689798336532091277306902686255729085666470312471633361681416909193791811319403532874207448957943573621561570361420142021335369986897890096676145182038963880261441061732050417915303630256848507936203920286252031119485944427869662789240193293256906568422117890718148236456663625414087284263208862223330832873400786741296920090835669266848590355220163288571504038986951284822092371831699866214144561643268892341683560196843556473756242792918996776440541828325251205159541356044574100090915177294594322159346130242173404539855501213962357113833510792566361971152965895680317218436013960373007076476022631744007865475931271695185986240748628471363299931697921057839151049324797346058516346085455789287455352049881203958337415771170592769045982606693019099091278349632244057795350467001827227146263466136538639444478320490667114063406630313778352320181470159320938699972993608036379390495053665979043381306437017596335445308307450796477898537807884325768295485873158555238551071709097204739033149496921183384588061397067534720922312700770309495901059882308473248851104630471587698594942878166908179547241541714311373119298683524430321819414700967611691148909116772942975569793956680175604978748614931754235836986109460498443346916901466040779528436086609232350395911184233347701314302257256900389976137790804106393825581228498790151868516875948668469894030679508412001620846748009981388517197837451018562400562596778801937232486471110511289371788099638631250838841850090609849485127609000025979935841816973296037617292736830127009856329725563323021234096920629015740236201967235687053850008672701952747195231159037697992227434648383447519023340109165071772790302232779576774055472409694968720889474112050662211169560998147621200092882891306423891376193036773429930632973824074073762445925508156032613021009192756202792434119066623304977955065621816223871548962817780837015946980916668891341700945619651200897804832745482693095390815688505182121021960178419841768262660242077509146019381002771042805290103615880497756460478061180740302154439549819288144916413772957624904589810677747070038546397767979506630526692348035562590096852621538300897947177912714650362826463702353603977081903215581482132183127769489922704332116791426051505467122790721579838603453735714020632096607907484182278936865251314976906370384453138681261661401346754604262603028166386737284661625973545119055871319530016351868675207728576530137693149340937068042358715063331566680691489768259300594180750277831272901774044261099428386880022893019907150180913199663274637907422017304398594543431571125739027632918475280178789995927821050726356465528956873561899676084274623805226197726485040988257406658375843862168482920225479248649000696784022948441385703563181641687588042960052153549280241078830255012406693351468127759074614836279911632013640929085588700099558299403141651806953985407539113036080494535180787132786721745726420880521267774205334004243521674354365596626340322514736730277154746947975586419242077069111314225461354828641863406883386353082049351445888722660923473353555102903918524334943916213852205710403848526373449009855696006613162061306797914446576050244536195035963478421990112549704329765393361721691095177166728159276845241405734494382167071415793549500054058739583704360833316750818576647995921871537629807164469942103284098030889529247570402515786371137667458595111439840443493382554462615438146949017470549880539683564108491420021861887054309080375717244384210190235836550643091897274193701241446238353870549080439076686446742524978809783842285926678216099377250120855930756505757183099011510774283412112660175208223296441002665441202101068768097716251470168063599879252657973713173532475375285492761613463949744838603461409821684991072239790549973678104513304973489665181423944195898479656584083945140606506703665965947205895216696838871939074814076148549538223328023556598737551786801655158656596941189350270785572738000046388308165721536356019667568532999683730326052807487123480047362063027773108806488068824102664182194246726187252665107154734525802598140283107726218767757044695047900295314226878960690731616618190948125230096256403848986148312593893529934316611530344222329183508938024533159467266911439900419497460490242108217698476582595982761573009082455972549199065461876490030184886245197629744214373556873777376753819562483045902119779673658338493737645608665613018938354732423602284479791425173343405804834212381924519699411459752444777990382309914315791018010939804396212742180832086492235281302216897277779215387727734663082831993798738070049371107709419923426450096106827106291199126919530940758869182251750433702566861643236672125431763515477879867746757602425850711574603608013256459519652681427709707125875214025272912600011087521159888116798932287759513887406299110712598896131136581724568630618550899439047337575807886257446627498909492836293108046021017452886434370859955937990373417164773405743462879429439514274977161018604215454436420118297736018576301365300657791587017979396061047876961757361827777254111699061816473710492144774660731725348204791847843488765131670019217449346495464913458272789115904701360372952856213853415807989036840772391449116677951983000562144625141374604673787383987566875698945984243331463294713261127962643489108727907026746220408252476979537417404987435599809459143506750400457278147517782893213429606904467950929347575322481148412919113805142327315984204237783760694063075265568904775579651943365648212512733536920445000544087373106414507357919581315598254636108074530032861051365434730104252215078609094363760008520298974198527297807146510483002974733248317151858803943483354796392902917094173218400508740059423997283874699215616332021342131691025061752355148174346938724642237988958037278003707019848802913453342720000, - 12493598371820417507792033322578873166753446932625693239832038350228259497372686452356599594216106360122946448062727177995529756178052945354891104775070532954558656214040852664914883364018959349941685877314840831889585270362373826672615909045034596923784068963106405223630392886339330301572276377028142018992295187190109074206019320191021174440182034647508447656598044393363368945257461578440383848618391000642519885816382984474501929496487861834879137311554712784027011547418407118988157000063456610507230488702148200817283211166209951361645527944274906854612346158348051651709605771639270572579472361785261611164359166703512184717139209631416105933694195482068617378015326803930986036457236105488677334060057039419407578092588170507283005326769380953565415739538726290639277365146462673826911659711999780445373535106795079487534972314120960992399019233008097499541948989693742121683036001977493400136652673615819634162843682935064693200249312637017002536051561988532389235011322155790045457483052445207809329889853150167679500777829322768528854641451123994637478047811402523050501373318625604136356310561697603392739085583508015872511127744402373335208388637535391092821545819040656230766715609350966571751819952643466523273680019390040137052707191713557973659902229776160368817731980312298567642530976230072923374857342434319426577601992832371651706583829700472170414730215704605765938578399561279769818707457722782903181703337568005471582261924644793372458344799229482050359371781798545130150426255445001178843291909704851576412166022077934486353696361471342892752194369770137858160114587838256560303595444279203149958504629824845379320563171524789193910427091229968513961904417073339855721473380208831756041346206357236980895306517806107223340008335804414670846719688278579226285357230215333436697920339493426107684912504545228477041065062231594539116625284931793371006605312973894476701031714729343671239422857354116890762524839792466204640431474742911132501104053876412272286892744425347928581042741653671856289366320793638966797244837405635290294738703271981413808871323841444492348227833688739986080324170450262967612347450904201801603760915995673249011607356922095724586375212887169947920212012992744298889953247070957088752086733069579677391723939677230481979558247678912923104234170259035802506201156264738873272528054862899778226606535838207489610065069963771156877333320455209165829207425003461087628404693640404823588987350787875644623410209356286563075811542850283569784743397908202089381157863963609288014669896838690356111329433820371480694972017837865232297509297113673202928105472655703817558104457834050612475152847180234749437426999206262515826188380880066423577911165903963981470142058849879876574043696365647952215552050432506285414636375755083123785220115117972206922878724743183867152440386566878460712949529751180487904956153861652049758851413742671306502357178469847898813947443927232547018573615232211324841350452956188492472338646737550721012081042806917307785978686793773147759252352477128895764303743581230721894388008966498782453072361551105495668374665518171757542049989912832406418305640132497818978341488093484858959962337766062147202662834610367276149953445953754372272418375375157309307049569138034576100799763743482624983395936032985030537717522025097040956883445085401141618492985593765663322825517844732045515564847937822971523245361586619485483382579214840670826405654777514120266410893569805659808886059867894436710181560907803253394940442871346515155953909745866481571280314756659234548969827675761748298064261745311969075352579715661720197694207314432929798493709098318340513068841657011890441972638474883242134388810947646441089046355384521796138289670910867460324689215895563441347687788748664041584692984994378967709631938787422674339353214429622415053061984176291825722143548918492343321331156399667516665359663620651848210638970297712871646179865525719457379094185365632237938521422977197796054823989993290599220448380804536203705289525477479531153750875740198214096029783239634798308472116695226024107730914425884661916472938790509496175113836320720705552463446384213397271232691993604237003498106053122806057325722679542014289550823539947770199361121053689971273516150055207458134941012682741375319852064276920358156719061480750842820881433264237120753677566715098741791110204933801195233384440414846705063371947980019563777915686294602145008311723170826518816738976553026514254277424425872635095459227673271654459624613221390754305520795401261541920782929536169756470320766402752856496043631671809439817936607972843444929043003931364302968850195114539980318262247561926561053810956920984927488035502216787628127210547321253226374181030116423380491344374319089067092434240508178892884058748384844726553587262086048455771556270185136215291652003946392842741583964179910498949644778372662015375246242066861222422645266188160456707233381263834789693621820932189492974333244644777702432200135125394247312060024798315559543879642500468541968290409190572656361293114940818104399668386942644866012788995307651447854033599356203301932856706671396169948309473680523618066873252434856866522141451936269117309466834533213002942427905149642011069977023608589004315946397769063239992790227289592124131652320049297930245086682194803998346213948319033577703777947994257277072804778416166739738677617386212287414104674780152105795701052766222439754813030789789275271911709708198741275750384116217357182731448043035165833311563637829676591606690609054018804014398355091891295666993193720783923255769617295201228874388007243710940886855825082665085419793364150239436449705702916289312215652133072660165630451522167461715829277506459109776855507419993141470711632668456465817270713780855397101848164426366689645319667921820328035449142754744541271691251237849485506917277782794457473761033998739538924320111668442373815896368022117588935487455922809869544424018426511054073046616411095936110797317244987905418582269878951069013811302035901725268687739091473645865922069458818074124652697192305784475279259686844831611671061072385151094248131831430401189863882683425720545802888591719180540960037477524153466331429357667997148511242836758140526138265768469676609486950367649543542669654139089032936154811238809742250497902465794801636854074665237524637064649942673251087513780035425326224499068046839771720987193627267937498455381277964962135498607351214536365975252559181625848737631775186923025619301603065021356815576534804978692699254842849628098878270862130036304904810510774778420676768932784687601005491197914115573802768511796972104907823919023821085101651321675777673473142843192039670574246464246023720531664270411016436735693712834531565597145306206369777186680545229508071293793725189163891726806216426245697786001619240388475361967882750544942101426836566495883038726034744886096395581341546241685150866680248047282917454966464774351353983612488655875310755342111208768847527129400545942160530041011625170708605753147130652373434165586164053121135196082516681929418967759587041209256413686295241593273352130487387241517570164868360055336554187638756756802505922477797767532050476229171838607633221040765291393756448746801187171631618811426177826346009422463139145743020735223238850266396354741268377328739521762892024986692540107596920765914189749264499555414705272796237030503910225218803108859260581356909166329036741585984814478177462089898650004273767196926762722774476914244977237249348707767802177032879447569685624238028091063610920420086255487084672180739848468082099877941648232531903627880556880926655014558013995984906325814245067899528433198342866710605994347013100187037442478513757454937015455900696168624859575511423962316800000, - 170728384974326605153850634894876875430649661476923354119756326273279940475609648172437085215274894834253825362519897608410085351015329628378754047205572534096336897979989147600202069382924402676090789784855231613645715573011817990967000150253203269827793967393992077520338671521023033376987976595916032693875674838808620790696431571635373050290362454447266177594130776279504270445192288885237306598647269014669035761468479529385471237052943291432601002906552316655056492596027554154823513634489197978445206005726578153765003888477911494502531394669317937543689625032682005959306596976196029177041788928945372364935106093874438587390841850591985581765136194795165539418147959103947666398337103111223776219785575627393916314927886516456588084114606091288689440830730664060912393256484400090149119886516421443946734433918330391107766099711209316322756318166344688763787083068363200355581053667275184772607037886795088997219431881461454415851749939018689713818805999658128996595259584004072724277638778497560095108387091940493145355958916007806241417584511733829084511095668385162431734829930385950294396213891357831623204178662581528165331850973716572651852098107601553527290030271291495989223534814995494708455510938667167435076669290462561241478436712805129703661197301444539326017238253758079141120826312503207810887517082828103012083012926913779576741423640033750924874160896516183004777349849075292738904581544599073306577436928187482705056861479198779342871593792088925165633012790204990870603548596946079298518219928611185857063354427680715637236703706741819411434785486932271031765299629816506279222120142409654427241638500584423591976874686229727318930036641472333160283195317093151217838862652950762280945518335019534538232317828859552680627338838230253354821655115515165469311852503917063475880251070674495118099786154303552064218533492823211735571309537805104230949489017359422021433427842948902638172335688057911752839342523921934583372435916774407047769450310082315456035426638526757688743305124166269377745809004188777633127119662435664630985003969154723525878821966502228378702455099010339664020565891564923899265429230860389356683048535599682959108638628624320808450330527939766810986191552435662851341009602138328749722040902918781775288066781700461496027333766200827474838076143999573563373801906441697857496604799518815579014377897187453364487512093405608790101462201762227890752385552216015560151224506713845855477648817693200080397775458806395468999257431673457488744822397193453747637454641284158404764958397657943881827920934982823457346623441607829047794191887305102098925293004390128795766208468843144580310097035908815961745255629656445515412681716883359503875908653041682944374199504756757734252184390148116121701680795965167778562741598414140125271099476716924667969217653905488723209638553407597281443968854835817310462882614800213666359720974940367588284498886300629475595537868846279299054679043414217154709391557714914914897034965769286208894443795354916966290645171691051912316734097557586990816944758287344096154464228777941409778182964192566576180256775183924157084310081472155736670116540791752869406999073061148879115054397504121231970207098183376475762311906979930836474002398506366399729941875742596892343901170954848843183280047721721784215654997622410772562871781334181450362898284717798561693109796097125515082696134135191485828729652130132193449876553213547387867901707714052248109015204007855416138123498989742446745238704696598677645245491179517525411413647942734172459239632234549943974431508932419923092464461058092437665159216484661570418892453402194443341894393341429331488372022266923083514835068840566427197700038592727567363595805704723849745935731264990051540441852606107401447576779059646270220895372330404243505073428222706509847485199647345810224123224166695031181438329329901709021948230442677360606607217390128997764508321606274909596871478542060501924381733677772844481034042751211144854838420090972159091302336805997604004600812336937665001127729999849460733538458949348499728462617022491706898334970566373486270121519789328390081831660529926422903888963821328794210324306451672263404542943673927398228348567438071708397766885516931813251006635764459063166959659047450326855979218131112709654512884451975489725876267134550214347648880238162290195108029507981017022466465555320215593940911924504200636492018105029689466099163359467159551651171551088092397739155631466337397850185519944575880156499503309555659085605763844666117266806554477729299376214462066857244791391230664506179975123962576655887113320956232863944068132682685481389229672708858627164425408627258575112061166788698055693820975480195388149343083832803159014148210504852552500350605184047361038227955268048468809093793958078669109844344820260052658481804157195527185995776711071862423633814278208234724024689203840081653628498020369569109687407716710612005853969471827445565601445129857075784750187392529115641414404209926523543674594038199404006194959737831289059722628527550717421036212498239280447064213135836330121635550087186872231238848933557450683359946797053658770077324920262643950228384171985384945319985015067727034925385287894650008621973095078373765525134478971736335855933870408829318549818093373627180037421692798738926608870147582268936880098640384024847728970091637154861710277891958075043392919034120241764578521346014081552290635370967057909286127049844131104291478140486664881792254158749671006693315725625486468466128163456918005179990185066347889883469791519773686449703609474026525084499783328208188715565691733752280906992047779775038401442373779006369078381139161404437737128515685058152121713491078817827678371401346033316940270308802194232118568922919361401520845002070328297555198259932910314161660658506329538375965293764299234751778025884013052503263550255002432678429659841313849876671520222509556943420610047926348698030969367736250065669931924350150236916081573919797035950079696012464646519687110520156253935505955995965689780139901296389988672743317791715553500873629578912981781984243835846963360702194573882519875803970356594876830999563262228196532391927876775302792555376729249487128247141436488373692314830962620064040844653149846811406135652708655736175356565389223529452903584595534360359332773100411667975712174766158125557456276807392685874735466820962213141971906037681177178699186506926693355576429968126017438418610975599796104181779384568155848254532859590524899627245738782925136810274013893731677588983465476267648415659832169436107764136727679197250579455136968422378212862673059680531210530421728693458109447026673194244317828090595532488127249044979733404964703590276802631177031922606700254652894789317880122620356959747882065412018170385425256138083170936928773011313049678463238358497117062497012134879335242812088785485039979149196617231626576931815682326133752001473182195154343799496549372120266538986888863463160953481178330803754060304203303328571963813072385603552836286656110498970242829835086179233495788140369168636029638221936411036743172303822210821936329141446075169918989423730354609846122310410867289363528561649126254741879640166259577921516700339966751772283639207208804843804745940457434927559173498486012582785759686866391495150676856474458302708371486970935512498611094529046628040665486682584076169411230539080913495816337161311180434597669501646798897864082377435072333371070954971400003268614796977656154601609550756995287985981682900433174026654158787384653291136753629391746915325698599135090099211327483589635784482504839557866687769795186567671563665630123125058296036213368575587768556728485130630174497733750206568631076882170987765557744789094400000, - 245804318461389574358703106927225082390111792193332775258347502517655212741210360201615899249267190958302195265377029093527924562244104731024904646034173698601333395213305394280111582753176188146583740041919593325125767060838595334987890596439940277438052007811840984091176694203682723445617353316650615133318071537231828413704822378771903216450249273665335831987047009579096801486332693646815701888727466615994931307940713457799292328069520902093773676416166948064511330227613787902129343708287043450101532834134358407922532493017035523108041553349679352010705124625513662393590820334422473112632873042177545631336894954722192913748705094873000630906800531260724811726311388799787665491804013432658370197525437685863493245282594266698357530746733881131136118267960942086399760524834685293480328303331890600638870177416586482093327038669695439406159413712308456958926977354846311719581255892716410466447136285829416940824191244844454058750370256100630162724014342799433214246157067934577045138837601641886879306934668278289440938433408854903676386320051955453054575396674628524136133982326729692578160970264409231548589792537329574076857609259927292286708246389221638192729303035354094617559152748231225385844058632585564027183998046847245781373703912474066396343887178483478175356604055777987040470615903676254609435679476522270808197414053150937493517053102393035075261267315058554034233032484078513343453682731749497729605228088037267068140562323563064904223315422606376152991313325142014514821262401697548052158892695813274848985878822223658162075440366013998609394282543434367570903971075600536461931845321399191456385646524229190305428202887335681450317184073381943028503123666401282098686662364495303843592825485123726541348685864459988243516191402885116328882318757045590026764159825882699556300759972687025134819832320205223994625814561662668087964503399973431769120973118429323525386479192647064615819336599270851209825929897364327679028897919164290983195951634720477470902780147409720570202047248224474316212591552919521568149968590253498992393086304072198768754660693318434883282117040771424159357103686960821685414974827368560763262793280039846035865027924721481240276346024883225901653585182459375642004656845408558766048237236973279589525629133827692970861634493211505652538794851867703162941153233570451773380867887262072063390040184256206827272309177172632851712452455238388509569353234164988861488702596882029680205780304536740352244004339391878515151063027150266954708923499247205299453305012378644318220588133022872818928000807320943072587554817423910274683469154028699339336826059024120683918742261168265572290524768799587738646435895312233305050456002564055746305069539577856803261299094149680322480870014169511239904998932524379296605503779489598551899785150776315636576290038657201954640273495080024920837363341229679991228771181988928363975841147483160248256768164032422224767123534300232231191035554150618501395563349288664883991877932937607835254062709211508686640908161520648676478092088179776591147990796097815492526616557206002786893533188730377432178594050864992478346447557239047720345293071121167256157049915983377557529757371404243487414059601479759184685245136905355147708319843957099378749604084952473394576222089235698415498692117658311412712888657162510406964164107637301631314411452190657377554565896336985744986206200376953674857501914719002106752904934371338071343051321741551205717447379898364714899936779744774927978116169070749166738887982833524366270409696608448144513374034273351554433490192190752110796988796012701036203342422202400480467013241232655805848687595878594654164477024254578639117635360752473747196165554804743206324401604847238376302405877542794774331773541084245400608169561676141997255213739411147502372091338713524079076213209401107661040969457618501877832158960177019085835456989979894285455159551083000519961182466026932310127279782269776878286515983182180277682063816657891455135998074976993176686537380370783919931339830143263724966134365744884085621957560866659039891896812647680624864641889351348125873745429748560826588850070060124030168118631199982474678555939874735635581773871521232626720859754358271826569914452654459168698180884227187215172157981675139358735911052784812351339554827103212508971002302947586001979426215275308971563793998431786870227522958380662328979828711324059279297517956018641831322422591832526095675071512106362611091503531728917065678460744974033070265994849547459823339720311731807432102860784947087682921799484829997853842244854299717831981960286309377669539746508010554225207788442385507619510892838937123141323529141153644340806985518328583934462388249789601883104008173663152017443800507624726369471273417658154065940828943095850164675961216979292887812808286395290819770625610160082585174572265387841613116641409721696079458308241893523925994962045524667705196184743580121876915666055881747493786719206173885053604860596167595623999250166524464866847423736930367627711354975983604094264398993303418476813355871834440919740193231951519047430273810341938773123947316044812420649948372989339224119751053897143706748660526891468335325377962022794588785052017077353225719760996970831246153251927533459924256929633955006398068618887913748367041042507616718063211773273917567396350291725522839783878725646154622259057034916298892039965950647564182674533533170539618498842163735189986999031174887433198591843264716922571979080620607823845231869577175582396821109110808087003156277203388644510298421289337856091371254119150220511585754870226371080732224688356025503094525643330109060244288570200961176913809930224591478449774749575570679122550579797794860279829118800137999386535465071473134188422041550329558004852273988888245233598633629448643612139493132610410402762100188128373192315861026695052410893687298901529121073060530744442998821024275330345354132409090811226280303747710493781567141466488835885359277320792076000380019630411236985108028406903828518330062047084571048985281982540354842896329339270262187300838620655365497310810027417274985796286075938967690790601303677591587509834518136871209990762168377629348151098543590940511890213333049072304202093060931764472185421953480766263278096096768647640877600249435212401399304453273354312385528047768660462912179947909880449783723085028777605494993719574785230166969748114250887904831155579814596490607713465563000148193033975216752811199923016548677692642812876620910528165660142094074896118460222848813457741086163244511675149014272742090247608215189258690612506917297432860683830358601575041016586275000884663563472062061130433760653714137207870414156470322630010424470187437961805459093660231531356510263887264662074282211992919084483504510224420470313552206254904550717448954167307317006816302595863974108337499817955688209629390628599366466038178042719237524130174032891787759474208365431108480041132869389605495429468774841942568612425153037371649493631769720954606725645414129142113817206701450035355848225425013983165163481368554925419629496723502754983156189001406964871093917944055157134786215833469812891337010271020720138302394257861577814625208431888442272356360506813802964188510510977299824927549760281491148371312022974818222373763837457841516355097288194981415160363076926539972652493622530688752685060807288944484369615780816186470794582841023669848762034489234118731900906926862291010030362540146768741905782265698807998135691191204350244713286315038595052408125847794207140586482319757421059297644728144718164870529112780555990910437310561008974210592356331637775337321441023320348002814802721898969588738373239405609370316726116614961889280000, - -54397201812031640321041645623499064695763261585233406680950966634099141816450485431306636156949194422317481142027994187606420997705580866261885132993315132792668508673052443314609071638751299484929875602108281763484824883088356604934733645615523722916333562034004836974776600820063639882268427612864596798801177091326890736372210019214425898400651589397251646081717209248451446585988065914745386818768396146986480711169110170350090736935669669175481240732414154771161314842715993573205741493163484166189931432942899547025677947119293572174143716402731378827250483586802797549977350845490064033835087444921935710889127033834060085621253780852210385126352726656091004793626649355767535003675686374249060819668751600240578135863730174388686102830865763826118616447752997480697704285167639420086976204092544773139740198995962067865985106798490343857776022909933915814887422608040886211012244654192036253182800065838712689159645986417438674201049920421819053943312609189231813858269618009667414300226729888142506850516089568341041950102852406835133450217543889879773566792464193706264989840058968978401832099467298416600684698617729990518308912767978421586513035115969240710457226897998565749756014139072993588620133583665475599745984178230198725657849959751942222929413020149819898276490608807192630045818591653809699214214579669272446479201221513808189642668980093585884553198095037330346378565571873471148339130990363531009830208289156572391681112801473089818642361189768373728026627344255408621300103694613155689922492552400187065705197424609942926072622979014677219577747218412418501012834708159855275559681804050700043454053384904343047578324504855140685476032726358729271612448217656128344671669870562697808881974976017114609726627757456776795183717703299210697632016278664612994580213028179755115296143427352011893581157376550300740969582131753348032659024440666427591513661375949008522435190981823788584893061801187497179772791209580960209174301794817197409848430035423923627906491475745396745033022816186215606261210691047820325586029680374157664829439580791074306505318544342587625290656823334867255013131670436472727009277529741330362474498957335533187979218096012035362014165276455925006108778448624195870590982148559132764318275818973896697385038282494943524114493379106495514160300665339427733076382716911038850842868649368633812739877883208265321887733665023851874851087286176563542138376752079170153831356816450711038042784123421147332850251406836497270776125101764432388824835702120821305389111013473687430908201929135524894513846705366429375753365559656615544020622980112212399968905163792502126025442834765950030681034040825847721425529399775404283372235626364166220228583147339392760054287814826384970954562949814276185544752128195012842363907270986214785799521012966499681231410047083858259872385238381449729683276215278339952561717698005122524798671296019711456863875563622791655910478121631891368887992830842125681174352591413116354088968719813424059258288988302818504865978900599631530500684322631002239786788592531570528431808663700922956130851544034309064823973218633355473877589458270370202096365981032767678017417190195912649564186003790930535589960799699652480355070787939078881436852343938112746921469635627065716441497960310779749508455704388691615760932198562437286828158845899342310171203690567572622843867042775417484855809483521198728921324691959859639656860123893428047941466678898422086489114051207950914764257463240613182764799091446849015902774510007681437396478993350124889847082182402000533170714683440757838588815200468185634119249356889921738628795810948611660439410527556160756050096437038785787680831160249428157465303648545046709117193212069180433120966145178618343150348338285829328172002597411019191137428590961840223503219858191571296422109510575889517309067891602600927676646135546193859033450173053965623111556009344552074535145796244344708035598052761633141908894450512321430388571345397439313366334118652276821596671655887546494203314799515422942982660737023049764604830486019750151635556584008263800091824327961784023946889382418671176885006663783465554343781629949510629086754350733213851956374028446576351613529544222756530796442748246155882177421405042238338365687782843887523828592529639938925470470112442541315267637286097304642305860760964322238156147154989903232876615478748487007916979214491285732550386210567381599973077828967021578895256456082116542208360900553889663612732597880713081454072080707631759694625924064015455589024627080227553222211015275258417307700817901850409369539072119351022885661659376674572642270782955684482759884449966043389584173626876714642749989649013512478552229108340240101333140862838669895496487619407870684150115395894912972236960522591204504627705696759507626337986793002409742607291093879226150907841549333122237231055841349008468701834410330227312766886446133009768412283686269800581875166846488810959596010990777618573000324588553793394968722507658700842290117005904268629943041811494941849192474219477584289942892023464935568724697238380601515704680902261301546967602352242730267228050004993446322373737381955708920920763917039899460020826232220470142981432749542534505150709820105084450272113613657452853317659226618664198775618669225513830816003117513047594675039674272379724920823180201262859661064014685852524605900923403613973756791514726929056115291508955284586109042566593929556506070184844520311477825449471062454809415934507614462016623659993745067876297670119709407659597581336802334942307505079042590467276839087859547663230844301122819998102235349070879577566292007872177903024267409229340833713373291274784897341075463433031700039225306019940895722341493759531947528667213696640710664885074406473283871449169868099796496453990014226550963611674699670259303654724812655673346677963045103828627513643374985731041447681505644427886149303681088580400294765013120922404743944215315101712019245483608239245499144175852594808174962441320543231205104884673865847586286075893690293881472952867484193712494374872975867448394838432479685695034782768878737022187105284504859251545466285196221248078095273965861309231821455766363849090030202456376298259389856127830154329658487834270540720476106771047813172237230367988007712961125274411009045642935511217522192651942641403519388726896883216841878714438647328482801499125631810042449292352917123417766212731790560999401584720484308829225773235307805875641848414285005067647246219345865070425168724648698598568738417704393137423627643422433500120741591544139955808091333510137208764270676454948317725465269826697562139696197182670554310294244787447589194674772300712239664976606039102230861305489546310402963177857235126170363988539611945111010909602893560164073546426625302371240435050108363630979802509683206468895219700791784144364332000692170444470902794620625505284991628851140076204679892228611509684163601540253716648098959193574755264596039326634561204252339354084217076153444579323437023142241465239577778814178554333287628360884203415930664498588213879054692873404958806632807492061290390845083766793847545701345362741063529001716919216826505347799042180432303773129247181975330426167233700970278303715370375173833856762598604015183187846779526579307138072611216801334986137249474851869260937546892891375257329623889259798802551771110788374295238733594996241727797016252254697746632058227708650471392444172788960215064010405266849786246787675251886830344928559322853328332550036709940622418884511546687233611730137203873591142446472241333220531274568226733065985434183978961467860061479727054644393703607532241020238226303997895927445376204800000, - -1268321040114514768643798399642725168576089344227626794525051822352895105781765205071901011462152085596554756614802535253543799705980063481030339743589501434629216890913749449148880499582861979909501331868892290013442175259939995097401373855435347633055628870019830851491122343097354479075875546345132868192361552804303851462044385558619386719662006385047066495960065565391923671510451155238263572645453403131483879429295062952991881633995252036308274511212092229448441657653860485385635926798461645917267971465977874563250416915845881091792839669036931930683232027982284852002644083286869266132663776796055025071819652480938490004086244020549009623057616369430642764713901535791710560599818537678314876921051020782588018551022365027800137969013604445849622123175081257251175147027323118188219784481124676649479867618143009113244403550480849667283880087445682860435948275272048251152604522696436332922995066293485977540480310204611326496387497913763223677347040489698944424282654350566770921974078050303613233853580203608218765126400674455218792332826261897894516503594131991548204161582433503198268225863637649800101077039068620305834302872699343346116998589248833578370341843777971658067469474731568490942895676097646954278244640184720030024479806377209568493431225616078423696305964469762340859029163985559170896781331338029318786319367132417411967656027024364198749382931718427704453330953806440952671806615090457865338897242720116853986731093707061807106932773613134503156852344954926023782103609284425662066830890494791203609485570944751028114246887677534797225032308600466576899012012023791377321164444109353686574000046985629320141608655218132963542001446500361668847675272188905044297434213135657693778802309032748728043074847985843546962854038112383248883557693605377979376157788138041495101266439073410783159982508718055973904315290034617413043586949266586919218024931457088488353125334457836894007961607426197530924770351789388550442013251827815084764168424936825873377583112991089255086901800330581298951937540314440777418496142113248783298068924085116480982612280194902603730441896735010028122832910714009840351368597912922903063934602300165925527937908732541712665720364927433009148141844724295260231706299684596615677854449194347303508102646327962418827020355425292347959549796333400470654448570941860007182147739451418525073259545450945785623093071285026068846891415930821674815815545047439930277905229812910695002986897069383687183864798873747336036823601213856233466670194275762526262678308102998641064524349759798238217110013847486748232608724499854999135432511982602446318777759332935393908662911224642289897795429949541026532084507326194419596846510446870994178124108834817874355902910828794468451214843239311936298688616525037707377093710992603028445093568078422196689885923489399034663330705830165590142183782391829277360234403651916264367139751081542280928377362423847780512936314927618775861610844901814161806655887089517702318474245100218166320296703656198304234038850591932487298021644947780745548360907980958231392263834970207788996416239397030595205206113497172090122328438100806953951093597348413772155340282805876182018860478828860058978692733780487590397130366709414411329923692260900159748652296013171759762831636352710813632542339773881963925029609346381355893838934100628537670017256840524362535460825727741427446296952823477589896759510900064311508414692917414322051989793946371705911596334754522199447010272364448476701155307559755494146547502783060909371982688063495335504521644307235992001591342209164134648549111498122614310225856307792308953198276611908467697434058701116186758654823429650142184853661760935045915235520722022342139690718884393789122241267306910349355734063573786809851762171919299205364369517147561893580190205922272418341119547101612711159627693696354956284961748808163108529825487093313014191566844185110757542894442366991002740321031574640977782505029648057555254756292722303700946414117724997132379031977439512502090940362702253179020893771923033134388366886347744386907156019887134307350263803233653519281726831328427373541990856787770368822174363646628537574745330456590668630214395444515619033655349170500853852652099494057415234787798351011574491193752054676256505023716324727082025252059556114371776984555400665345471764909304829410102645104754175736266553200787397718251854323487623436985479714808057295027909566317213973088990060702647572218910639973174074130717685909640017276345040932450979834147544235899029857178628650568648292360433141660214772458374994025911220847652624153353994331067555148570766724669779603746817018594866320023313742156587402421203971995082426680323824651670722071120164103991841804634278736705496232862130129914627439686807756388161924494842760594183079305453476881667324873079260819058324346640062494047167414542677326816584850980249661891258158738631075141419442459951852546410237516172359646084082658511871653513690873472541221942165903081182750189262085133249938058494880830011955719759821900875082888089015005379615901326022484564522474738558734298678050759064717516374850302933449409269833530427540188055457104469758569318281088885516240891065063748204143504568173757438252677914228002540714772655288776089270845104207029274119280333248000050238463949588851580351826982749573834625171792528485194689548526223654081683866464522803860544473579875374598102556649109741280876545526917141418717608980504773140024258991909580980253094322309527762812360952674562754894572524352771735243135042925566074468907828595422705853786839289359895634516390196187361894235581375342268534103231033880496130781060352541535517790555222748751067621778885948346981403987407768328608270836116856658716991361523746733961072985083775885179218491755934496051415587599675593219053775860122354889318044420936772885484181498804854516514197964102245461081092225435226680900950772775633716734782953417406994942298027402033092422900579483638556594261077362720962550429544797793055720714945622565856580438096213240956465657137994169021041485804799555804186390422679657519260960504033467424985434978013929215216748434840884289007928169177660720750083598885728098449118215543658040679215740133629949087016613123700276270058437038345940445805297303407979691285988756248651254937187321529960875462714276941666109942907945856885698080683034963541793766828789463588250823937740532405646588180998704217782219056331571308421783861836070348562609326448518333322196301558529019349602990511968171441588804128122369498504948800057702500141969657572146176309512207066515331211953126147641836219744547649331635624093689101194862573397176502097370722829236031072011591497570913570831261667199194909287849914290558699504419199850897714291376381339188442755255815611610759491156707578126857202962070353175780433345820264310869983621628294920759700671722322851074966769554391991631528499843218820771367238989737126295304365481735179393652272901919764910802895979431373490558420254890190731643193323238067004266527400501776191152578433521377360864215422833302946777388058660623950888697652714589726117595159096086493808303241939880355641723846959455560457419899597446685416921877689740436508135523106399582979118953730996457016688084698229212396013720493117583875992428948803495141331706524746100487865800687841921102151452160848086341018744386162010391560137080977319268572237929649969512570433423099607450130212497361042367083493372013534799271498972461594729608885677249299242782711626396686027806005497865482607071007758933487051266064058216164281128247320014255224632847554560811085596854039231287076653874722897920000, - -12954730177756497146706439121322937309927594757986461751902791509733828576601563339721188308907418095816101283621626677098323810471916620091525610605728595192643038946491385919862447031980941442500325363435856376559838982973981596998597695120269010463048218925823835413548759563982528018217191656038398760886997730522746280935181954150726945538486484535739734442122620094552957432109740491469660042551752906486212212524089731221064497801777970530913255505448531316083141820727055483345820211926173543913112069295170658246152878561755061407264253485390773849092763520203042720879068278737104019998329622397072905309137687912446047352994476592121966235346285965559861391848956181968493258913344019925609009948151143350156104919467354724966896883714414387427730233178634931483352453099843388435993332179679281459009755823019695277915515936661956098896275932122975096736304178133603167590319024197623422243583982886433594113752860186636192858056119904638790387396288839739649375334006961292563407707281067260556272345474413669534811036088947086806067971011699558954488380312742038857010982179387707933253481832503441778749440835000477046769816938624494226573427348934108333939737985239098894424604711789358457568012703501595602465633353376059938401767095216905343948591608294252698267709482264335020006735664241006748233798802488972371797232921786804956739462975080854865426439304104758034963059165532908193584698220842106115848716737152488889253792760493467757748353517995351384381300060485258033172711413226066359740177748056794829271329005228587195064209862055203057268991509395601452736583529148976058543242278143724226076623532584092929006205924361081416801530285518914571622347498151045600850358792689946206213215020408368631208855773332213795877640786926503524753746017345785889228574200858549021846339647824296897021138294677151789746200485893187720075036774754647213956517109223177976042509756284861845438413351637477373631208052448897806261531702656067014396441640085868982924337442283142415488464280048994250992152859006417877829560595918248718825560007856929909586715165426598990178416611293777953645652965782025063117052780010033457699866689221982261427208225094745209525237726115633241658874595053506236826407745858424070964829414924465007835910034706035531402266474060963742820796873812771337603144780956601030987873956434946520409609377141516768966147791630083702148543879629709014589985052615215852350882537952683258110851350101544404792730839815352863579140608055409000583593568080160265379610310397248202576567082348165698403635736571940636166427312050844495442401406259723630536339414001701699356711492530408524335762001179872875932095995996194325560695170981747142036392091115271041820441896008262051942135797794538868141341017795313297562667835124078980448167571022152965366600059002875076249412909697744412409405109100695395820061676759855742965704579561730159897324856270990802866395107968368176871565681380756457538689537494961056030841312012954926441060518400761791943311984154750612229295636535830468666142976585651744081231135979111242718827173611317615060494555601343561635474770591427200625762997705953786871410507652586980243199160802673557503128960874237425488619349185610708181846348741697646244423449788398414823076969675554506532233056625709216564796142276064639024742596215210525650112668893622580555301382376308932215367074440242318673831973229476811964556055332433142507760440520163939993149930692317337657666830349076727214657299052444468649202642507862045222379278554890304684525624847291585229656081612933706159522041683816559430812756732704586450395550497334860188551409447829801546600626244623319270207450439754084597704566500369973015321230405285226332945388796062187858510669388026051299860939996940095474186825668835244452651545759570883418230221019617222782128840622683015570647102644748318953843103869672923015545588564955442863030697080133971319911656727386665840835772950881029276315661961022721836719283662298689134884417935446402300568312174824608113262330739278051213047933379176134979504086428433820530496531154593000796390946460397714971728335983849146955177727111543254111679169379918951618851502117125670634746076723810293834519354690296146599600810085494735440685407111565995663347667238394613502216905234384567011095414147596149857565523383065576362812656990263377845115770235894138608036420149393208302452524654323021920077421461689003752812302915997001232072597504778114619129125913831437536046563043934543363020330616459149646419979469211702618041499549557259240496865227794333030514906129314118086287172794466885755956935533216306215796870398588018701709932294288683047838736080225247220329727060894214973923106850803296331185988842473877643234937630287969658582646950352449835889581584122311732209991916640470513362237642611659518277305027862752870911599215521959059551356282583750003475627304630321599809158628454546726800035582350556269745898689662775666802433828992974418677823506230377988457268837744299309924417965371205664620375044606687573723119626070992754908645316513155589009805011246602007263560374362831208140851709077607883327229674656217565938590894638946250635431717385588928250004523076864812001240148314664042900691200201624206810748781896193005960866766085901812939987825406976475728234306785390872048051395054448972274760256327576581467592597721051217674960975715830274365815375804906704003436286257379572239563933674995963899785057129151056348570398453961579241399116122565192351927518008047091237653276416456498006577070647632517630613367078896229541796658728197495015128284284694943199316404164761044829639096550691859712130182583732575872038315757538457393439065074704977849022541642310303696835509386026165678815073431626503843208257232402298591137506662325119963260754547135318477327859250514905285222026799995474919763333540961204271530061173442930801347463454211135805887316645634757791476367917399842291080241338307610847436359295004355610196420140215411470395296401623178442704104978846094881848581127419440901832736357343686027618373317427767762598223067759807118203018974964366618029246469196044913212837763185725228195143499820184606820134657986317895935525372181037393943510046264072195899292915991575510111477333566273060032570483795176195778106390833520046420354894588500607083187295549893481813207483748672609184689758220694266403015211432206327429627426673884544283418840380731939151179554461132793722819669617810810182551078715616241748726554961724528345186068986114603132474563271849990182019516970315479168368740331169140345280224311680603739649938821499825543755472201544037152969600424120946970068152914936118240691014065227706423990198248998779430171161293055585887215725359682721087705350592028149898320950468732006777331351534495261781790723665278104072905280859123338149307695284010845933451362569412689261577534441146440439117848739662704426074581767796969499554501737126679756335944630783464718803070172031314785769227233123038471084361125780291675101551800476101594732214746959041609114842310518175592306331289205647016487633778220803516163147596744510310809106909412628445429756325556570277932275432859556990591123662223467235963313367741360628711569118777174608400115318221968421488500843942398820749466967700424858584706944729370821029624664893939934348597676251114674420178149613607395090927328466818271327679171435148219063897727055693969854787648037027619403978410450274335517567737989234892801467703217809197580659423151568418911151384131265643691198957090703456023781076464723585223793247516017384700126190170352283035893760000, - 69893164315207660917347460627830531776791795713179721199683025207155294650756049744137235622626213281989772383505060106409403060973053773026655671516085061573133769738204387013783530422857504444883315124362316832802573738898096369787650471918433472213419092248887010879114304699664479449785095683275699808426202135615967325745063549186737630004186744503691889569687699333284147772135102327326728983232788181016229784605905432992290857299083770591520485201497250961953786089523157868642895046327272427925883530544530338743748315345623861894937009234655933513564693205594308198089670232420196942511003188268680757197107371017611375438677761196057939579113726001950226157157982171496705489648297783027797743243566497144920593541983775108994336165575589721287571701432656338773023410249911372935044911934077593252497845718653012780460959375695790945719048867656669982204916243672287670857006856972769755964628933010036840868760723900506488681501492423539763627792993085580646983165242515285490417672840877971791503851405679305416636706562955869102367318999049035083215597883387661067715390311573155638466768634850739739944424866899730815438067538639003662981548202380884012572807027985324347477834426694075206225195438373182916756236570780301461158231044777695435173949761613673312259231301163568606282690953229372304041505390782707238343862081692062871234419970955804772556741825493676272698497192337613036520547080179335816809620284497326162008036578740618266894134706410966051935877042164767840003161375035049321913545621100841483491633888120226458171369245666690442733438475456783598688126628314791970412548438813670054554578703124923601482320748853646879832354228067947326630537835895598364149562253813788593607780858628344500729718748935693945187776619372849225479954330275771220644499581863741548366496885927588325298974177343404470033782822745385477030092906611650509236589651878117384606046479739981089949238309507475066370646330646970533608946328696820015663250316251710227583089927352672203018896678238665948477425948983620405931951523072452788047362016954884057310655961030096100633794079408553675168242764266379545518943260887397195283681756711145029286136072934360807798791656892695197769765098594223275958332741288708839751019432998220245269188748772965582171741711105430866998074084907183178624235094516653050580731009769838209096756441830125461223899666823900099227634872302176498343121743283834507151411081069932768589301353967532486510887574587024985442929898060390526267030572471485832893020960973790385456584837140641421833519734936611348394784706765976919584750651863547502012724317589479801681885653493837131653588545978235962335342744813991151101724920651582609793419934588046372822242257507218551904087822534659118403793914556573905824931109526423075598184095482599606934317005436639022442392696473576846798997670122715603095586736581234110373155204565569272001808958829528105398840808603900148504228876634423413486029227782127239339609209991905338687179989604752764655038154874351855767370787693323653542330801565354430967772149540222264105982710504622946674999488907290713326957071485032855232335989483156648672142443641577292832329369656944556168129643070349645811985254611736225369021870918008830769198236711485741524726153017988015750996736563119658134448219313454518991785565869188947686966097560795472042129896913357930646626417444103889323319295781424460972167466914841493049574906456646166215224998333734152057291512523282858085358096554524252233430204122133264449370014566992826754485889095333026657510526762704053605165664788347287015225626810114014003688491623750199351802046103877268105729935326310412905720764210878139546875808991081673101472136942166364321281660348659365704511990800258298749196293089598085029889732882175799424965075337572528063940635116244720419012886909169393210627099826450650915972528505024905753906883398355198021739087471735862040917789810149039890263549504287045083404986990497726358694718366788949773751643009061837153091145909604828000371709291360919995649869926353651673689615201730313298602790710221599076722242729468994010883304874196159478479442422744872328297148136670921925577380017980404615984352044521260316716772609676954181411610240091274532047156783808385078117814487129098100607556878658355139915289041543485006432465708262715762874014249683086034022968277865865014289270775728009323490600523453155632237627248862470812066330973994375213394267203364635817108731907089378883875174178654279898231571300262347196266513409195352986542851119256478449621369971644067748501971943875997975017043063110716330132669207701905373325788735652939531538412169564999666916615582134965191862314700659700178260977084599054515431501085006631295479817929867937839018220067360091987934581348067210614235493261096235249525306200342022116677656367681643421901119668914844838629920728374546892681344284797636293408853219534136923458271358506698253804180332216236056439708027564362157476424341046702379140229921792081301413367179628906697157497401944152118281203412248247799469152448129304497260807822658998278392336930050067493308554656797571892210742842874750661636356411447032061530539298176306575808057122299156810987240235596583293663615704363823662390057360973347321277800815702923304770663167504816265306014225863663772781486807822604184336901232273090980715162002761875297497745323636901323215729038375898557680857771714396580753238881911053560214692939806322159793231088754896630101075145214178404847765695277440538402326060968845761485632975435739275594195586582791249607623308526423190173925952363410637058490200861853953830025348755842245776960667176370435950726892535834622054199890434326084684135659694435061488442044607769409629750775534724270293837235591551447071066185815495128016124316919386971380934661111337129148053013957015762273397509121730320531999335383362930679171306193194475882673744311269765340418677440763161873653724663274856049706184107536759218822368405397318816133744531817019394331063752617547356582706097712516619228858094659279912840596197629610624377619846173750065053919517012948362800751225122276835459593119451215782624854513977720777080665287232838928893515956483863065023918490802674486657424129005831561573036243254985528219768152700157705632895011774287216235952807484763576078306086818990801356705317385016035258413641256990803670060250415855620554810006830563750423714133167225320096405887670226863930201349674684979405541373656196487555680962245044261219966383398228192397177697510031846693413513456686587993184898031137784658637932573479753836573345167403760092933374930186679843025364477915689020103709206420190125096695634401274571988219010921848889736552813113458891233144690653639050989385805475406479423398746197341535842722186648472387059012030286414466159783265970546477560911535883374902861758610577913507206496742530408504422895185652935924791786998219236984377595360749842942919586367488361192465520397813586433968341990664046084645200539269179894003672694244258897287849625664823739219617519652114476194644667513012219984574012280989228820198057950445142728273418061601654890026785568152729703730865310052457179118458890419682667868042505225445658959728454697378419639766242967233463957406131137360918621271702181701501064110676169732411299319089694247255546069182118129371042269740332906707466271512374603761456484894324193803425614672585100200346893865987561872715895091155899798432245654544511770413959089867423823373735677492753449840629666962229199560933785133487614545629095561072612497697013760000, - 5097916873920000649542119860841410281451383775350538520960241633920016741964987092423751375090313139167508672847970855264140395726192862637934673393477000804929770276964104468015008077222243345118804227669666677919448757022726802290483327163978054917194736934440899153124521100538387788401713859993151987554957104190604737255629006858738159549478168013421183309219241672547636303524750930563616336853399860216936299908811413606394529112524352534022593172523902503785621325634647957489255812326247472712985760518995248696780442703415797986443923405952716310577889755262976090103329074796187323413726017726234386608289668680783272203473171920879213720119984751790778290861145122783859558306618770505866479411127504689602934068746279088135601337256838264752045717134856076846195840739479035039082410230916586665083538542012978371700664408120251388519192866096606202466818243621579823427436825521321772866514010614026876287451307408171775264256828461310369329638638492300208115425505618515581154575081349861705319951269163418904079828829165043407596064619814174759816495115961568683212392091010378022208474281146129126511089862984800812044522981809694871738633567567453327767289248894498432766169456926358225013813597266762766996274539383905443279592499297606587131733415918143188558104208406542790153733603994148537845274845998041290684163803821461762619387003980578181283311432683407871234717250739945258897988907113829725351093437724158381799823876959085453243894352961492891466052664212639700827934990910636067017975780519775503855460411054591704648369349129983218127628777422612856078889391143751157832120128436409841476949667856819720522646441583645069255635152559279697220201817336526629127773680501484282809711460183551328785364284367903347157350299799722458788167112673581734252808411284117880195766297102520786403487246645374301971946324144812148852889723413417512261113430054078286826434516137268831895301266170864266328266624551404888907094945049463282549955269140404093350986519420839388747681107214543607740098367651961252717932969395532808391795535903641817333114201202236846452582052441985317569366780474116629599301314306729559307010879879730934941541976414452547007762369342266308703643965823202703937216203124047260104858657538080299495078993948296401762531584923113103887175022054992958486285094101636511479822998886392687941521567542409782045392368723390161270352326686473586935587243380069448269070579316026984350484496011439632921307680758880324719544159558110411736335300508652734894887745115992715004729492977361907809335071495290393907326864846669052098577692568260744577065404572249559137373504048664842385084169122326943817678835996413667197693076915350157130794912075182906714536952308604110493783873144523380038790250693151321913524860424776933614216169068692902585812612210269057177989935853544838480224701224708073573297455833055086158505663934528314971083454249921093209265140471651401668490912404103203096594088346834549678306117350394912836550875377926645664886311578770438924424768902059755444793467787695696334524035860385894212523135645347695082540344102434463874789101178142794939353894073266986391793280826753113202880747215686347284208384293002448499779076920045460678799361984796714650508552936114360436496158106596493729589823112291661154320407924816445371591303742992006159528939924587780499471085392319379531283634995118799831997364355283099610807603156084200948485546381042766719994134436953490615904393513625618029779886106193951706816218835565234154730855024191937980977940970142994417862025488569430399425633074456060206992198463340222474744817571896643242322455268606824117322780782300699548925728294829681230453705798574141016159769368957385459476426118430105626351082278218801780469901672566209279986048577745659708684374779966939917228922106891013326624659577925784189256109207454840146760734779061081108814998915160286323749916419641197708824273604732366081076832651400375864663323857216585632596656265115199358213061110049431754865235666115105540635447611173549453541761453386014596516365046710861169366172699046168586567282548716380330902650631094205770113334537393255192082205278634225388821123253797992267411700354130278111068529373141153028943756565110822171208811764140416718256309530508504965709619903570346957170942691691183941834442845181947355798628947030845309776040131588746693374135753960168967344953594205231323744286321851066394627419206238158804636145868384054743509190459622866107253126054283807827995707775885920705802415494788792891799386980088134452499010131238606806972523244328909481827916139626710693525967543489364351102247740435205567914024169136117795064749104842289974260509481561238035110869679905447107248000390995687079170318483966691296207383563891238456649530982433711913200419390031977357892323448343739485400415566016749630000888419313664136379463096385009038538952154567752160111183292293567635704106490046154341219535431991951153092897465742436127227787124881186369398099755573582228818977493940100320584309582405345131201138041626401323737640730129255236885913096839084482881517991532054647969612761537469688147166746773493708409407785860164024378257829625945495715270356533894525549408851884611323304097719166904025778326681794581906892270180110326196625016943548671461909006631804003567839392867600883774768114871303146919108516381728659670563253980183560466917199622139683691253325854416277285558498780210333666412085472119054931646127755441594543309637610054328707010656644585790208871882114483891300821667895903187745319664379043253123964669454524989996646706196641190542843058569991392533424834017716634440153398676944096172271860268479541460839697913318533542847765429781892980926942499953712416686619692621062297850977086953066756874854976811298926537138212677523557130146760289483554413650599653672355268593791871576883839109502207785048912346171418569765221151345284477794225736825832805891833876135310337639262989080111906579768415120194287905033251196596650245104423652577226776941011035487200659725811750541920445817190632095561449268425513091610991209565360141129084594327680079964020243700637048716046346986626720681568707132146433259995680724607793741434246303147450202599334438694713521893715593539636335236559961873234551301515401750712521366374665882469520782212837615051716256959101174494389475553033941345333148107036662506627092764596755546772532762516927183774421038855286766617039293773741588464623925548270229280559773196049677443086871097389813869797829897945925606729071915365150381245592284894315010478193131626391424705176758209488827944252992414594935895768045663399677314711779725774609801938771287249286767732526921862378447749365296170729239475502420284473572061717925917365004031032765116339935095772380611178570160476950887675115179062283914927120460946405833553044915991695911657134850754131245803914443174068310523500636060926466255928956339831323777666278436526876742968947593907907185947789323952570039032159283162107150296651491195202900891238603124691817436155714406382197121892836218112863695826275120751477823197093161237531557894604981917144208313661673001159424812678393713493276475049047291503843833025511325316887139711736999429910495089550064978233799006696319392699283053674853788795940596257616092855507670428333176322323710016358690576185645390133476127033837216936862797399674142250642751129201485175122034231037009778645924525454395890397274720862003607572897486040122397074741644168212171572538027195256983654443652919902645969126764062965760000, - 92219594941016412893674518336208988153941822284644129604040854742395015504832328748027561345050177526629234845228375782513475458198973445382207609875401740579965864745294572191295734014561034887098866587844407237883850092137078449452564459273129511490306516688908698759858412750302921111312509749299249968176077297048462653626360133794128344025621707566495566816617939385733997969365012975577294933402569234550241860771529438016096260605012585795199900734663257919771739102960873224906080916177170013485506024240227933909885867922337488777335926444851395649295867154255987676288153700920788141158100554096942892849906699611442897262629786062209851913689354742521521089357460424564417037921063599088752314604548839929501800478748078830295984892520283164291776493754685962621178908481859414890655838393251417178863769615506879894999937854964483725897756878416725533379163223893247671962754661709181085069073867491447391463077002344990133291873903758820991506699343787946269499996606945989985135222686047762832062234917823618661230581306522550907239410486205155708425975633834658540145503494580921732936689338107808788965005386396980908418462170455245311382930221600081973490255956828881624826844022251415403496419803514746025756915544718854890646917770791609143179735846795286936361845760017824124803460922588204091099360015087734284854508266157751323852139809957911391528001336316294651657967225839303931693611726570847791714863621555507615311203264652295423654756669098627964591871038791086244909834281751971780205065970042516722719840883567107013538807148200913070108339120399981163988676333835481339142922526493479018847152438339902306363697795481802410461066618118729654861236889580017633714410813396154652043926852251038752786346336885891063565001928730525114013877116473384908625519732331928575471020322328404315042290302048233473649563960264797076198118827087438814764716377553824650930195677456174116671980797848757734162219918646350539871916330320921685367363049527802451938837573882411788722046483689176601621157956348547144646785887179056567325707868019008879499131711111084454514186170018331357593153764885199462760074713964569809820760753283628739628649137025178518501467224141385699134045885712772430782771846726994319193425728357070551883189189639457663135565014628606953498588536894208509208066902499162947406500177330281313020784214613414249283157559192265171857030595406744150860144571668351002271524692517199966521017918888983232182657007435058814123718982056785365388182099416174648523578376335242253822632053423935861692797766882012238683417878266442122070364415728852036052335966735136489978610663474490379810371409435153947076354311827761484555421263233952076540209009897166846619224234578131154838867747050874508822283822265290942532550464736663171678498983882800006184642874396702346907686779045521051187299880516260850354081697850958145463502215765432322925201386773455463517710729364709176073732579130042128308898471523530885279455991781576633911714308605345832437046293031478596932879395064026667024248385940394306136407770033956532725573897505065604740764716042964721749880503691889708170367382442306071578123219212154559224832468634463064819948735537491641502741980808257249407547293056495597541985559471312720215915642863510941158328546172122279143602476237265748062850346063528921766907223642926517918184321192904027629641532312718201545362222338379713899566440581313658674993592847855502192774381255936646963306739955162517924573714946972991069453756583096474500795708622938956404915549462282014079333078380832384428808231182349594453327397319640913328941097080295535667625613040028520400497238482716211440391509556869375358085332343457086822908800091617852408580870644429398590408088809682739239202230684526608949432527892693259081292431410633236716254258077150872031512935189294025723896344593352532016206608967862599395990280382921262800090480089531429892016607172795443311292252643882483030132475720278285132939507336891024479820669840218333055258543442625335554968408084475385528743687405433641427537496114372583780100513757757576009791451638667960352330293491322625236724570280761696470032127834602751275379847417045592674794619120932885330008146966897762665356855877490171850629952063740521068278329280516522009770456269575162803437002850054490922125387054340559777830641771478007374759252389585169983052122955269152273409015614443761992246859391229920300780047216027015500346110851841543008342050684098800151142044871432688532268890520089962198535467998730623834942260467589779153209827474964881183303711316107539784600325648155500828833008877095336672953921843565497215543104913143298752634094791065879792142904972759952907927113485000317881620049018111866511366356865075371468717125758171897643563918350186816412971222184909522877280525239961908411813444622077193613697643689901811654038221210797220573815095436265733625640314152775731908914522327795877001562851679232413441218636514520435368313615880257319139339345989915344252426185889630893003887185104753770412295603722851309146991891593670200988298872411546772634472253073649995029672656272921952029836609483112775600153178996765095614527674249103236576453214424498582413199709038306926837636764081324643013660495083389201681219601888650087094753052001157169505866309785913710617615757710477577833718771370380028021282471230578398093443874498357357107939061722609639242808201872329456069756979312517633337632014524497552424600744960713543846409921746028153833505446580309415566269141069820365515886215842731954535075852644296865443401745205874842697772052912812620951590082749962002626239865437116367255984858020746442622823160581066236188751814858250927626644534221160787812964957164938629525883006935206962577291537569733558144155515792884953983939944268192869579711261121786781989588681063963358707665014461126623108229816999289599859246526110762543512722834739853922048439249858621283010181817893017588440779491927042522705786052324727347957103775694251677427735410465284519753143831867559943855316035890252763340193911666102667547717907176083742016434579600286816443992333346098562003798299780532995388869543689892398863237486017643926436416992184768730514284196029617180952473624881039500930791378920196093252760638426877604687052287601200999547338787159656767830515966088623295159318701615550704731482143773121011039430493896993605256817143896732727424686794419005557150097382797711570551918675893170703644154814770316876561989100597106927679407749507858027406026074037073412298543151135249812488239706436701707359502737232217978779875081907827709315451702476933670474010309143798795789327699517548810528830924679753567053797917616763675341007062307086744278812654005181721720378688277957614043975136091120949336363719535133614199679810342305024623196883617259726077931066453256126661568053395845709152103343784024110359768639332251907139781057907937123154722311202822968921687825126078431607894757695200958549074952584821942937379269261478320136591267004425210040799073483379273010135165133543456673012578824369476121664047669751293820504860583120159619781850298877150739243542197031688363089011807671802134570795676663688362310323863142257360419417789694966628560801431136644554236193126650936473804813003080566656659580635708928022140742864086977981704509699681148729339035473309774008807936924922017976170460383120329620619459347287497440254362451696063944131184722714120500679684611289175057458914845521838556928032679924160118960356342020177920000, - 670876380584140903168235538624257778757303131606541628223204465563501956814074195477633548598878534505996910723997524940881322193227552837751031041118722021993844129608169528148718063304747868431373517451537154294653266852243339784985233442271210473789957706126981726358760356714052983272870509830684371443316323594637507739620258431813385463958685309153443525039974490085215335720993547721694296679448136965776785399342158123297060112233430831632778106368274795105975940567893829106888507633336143754627913672544051329523349037458300473243456524285284952776895132974827114619857371140877426302846331030377856262102531226855390960747076355960282635147557987226107386189538121772826790361229156576675707321956551863437962728427634418053175495011598499709581418748887452711056714762197327164280841406824178131217724324970908800353908878865622877716269677244735706190192185063967070638097994077094918140517047564581931259214905845948671000534040490558468103241659321733814710688151011833878228727219577686752572332087641352046943313514188315615944583199681648234451724282859639481401507102301363255483043754378025039372284190945145515300241371239993834536709368107454169482843169388792242407523492422690915575707114945884140276707663221276277237160731490562777248864389665758732566099874850067746379579696623271861453285820390410009508139724054523872083627070831480178712212510868868281012754873478749303583299824415851540213717016854159489198038707097567726304417057903109670177092716686118445613197787804112174149999995212244407480634873817643106879116190362907821632952796417996009116804029312455218168189338118823140394808717622689784184767895615364173026791162783573012944978977396059858556694222482293868597140713060714805616444555913836446039039555105211517530544051236400799327684122377200840614953511518123396034605188270515828879322432766979220799153202304219105565648190328359577303154680948013912346780452102490723373245726586911780048476617329761822171263928111199014322660404235052475192818834928872482712256541202518169670446225540072113186516755127504535177672387200473935994107378217856322999338255934049566354293795681018719767011478412598368874420645444078976773253011803078778025526522258277570594458675692655438913617565242244435784549447469422831888919773173087116982472579464821492102282184305248952789842254114225978120571734188757796317472702287139393353194186148073964694908107752591994139653371137482359512682771187091905047923704869352020400326008644887679089737922925974497651992132816411483688327832667137499857199337260396324092004583268861539185979266818719114849988870691788972929751939824873499046919494934194471420150616368887040846665667973587159106384518442602464903119719374586022179683965891827256838094799486051784328092162184808285083745928205044363330815529567296038606705524311679550709627300589784654327507063810944718754730387406207633489562593294589153246347129911671873117034492182409039288735714942568787806453161058246772996442347854731024983787032925942820466560033582559138228529426297901314190576918626757910330304246996870946395101140586937769272575901142278708207230187936335139723603359113249225815296487123719974507237373185612872527009349921603248017076309585310213540472229644003141395824671347955607258499386016219081663392528053536995457305569811613659511558321105872488492296461360014437983641500115049941253783178352608272931513321988493752179172549310963104154160394173194279921187507288501644050187104819356722444404573639684062224678929734653473711843385362306519042351306410606948346524238688906259024199513704287110438838761362625052492013888027519396737462523571771539223173488461580496862423355263826613902371789916180353261053490492482239552202789477520251420019226734844195674421091507567023542280724906684120692113772608140625486330460325919609684463163240496983231413944455115187511590770696337667434049399699488722069008130006871708535786538886160368187599908778657796181934793094328755723456122313484230646059883757550482038153421070402497615661038112848596990481206388604995224330828282255721840839103157232724867360346448665541738278962208239914947911775172462882130127691878186466312287007054204962704612797058695297433909397202568922600361189459878503850827154500790300410682783942934244500806961586797124209194126445326106944153241413128139069645340424707542906632562983993384443018046638906005483667600309845069369955741561334369752863089737382757825410338624201556766085141315942011933655700262523304776980220319113203733037955069345983101113293962860765326999059557327806658224635179203487620948303460816658123488845284978610994621338284123743949514528887991054378086979563878434798790434670623408884254372500562320032199331433573492823771595563185996079930158783065809146262356717233380547531326758726001280842750182281463465171568226789928828452845660850170083223165654915272231528857641487155608302765418173731656723234159566740835632451189634780657922719713764947704146353338328897848218900452312719943151269223317974948337673304119344069018350764454226790643045564111653651349751894339396434284642905667962299998635330701267706765591101716124251413966193563827044170112359437018478939954075032506767872281358691091357632965442673139969704923679490735288030250571668614495032570819401493771604446385056116302642747512348338287560461771891907333838395076836758529854906232729496766083528638350367052504036833237392324216499330320270858599469737548602438089829056379589125386143516598933796010383712585840654929906642187735636005712539457137495848361653924985493176195700418800009736197357498807078567423974903939107805550140339084209291227473531980999907003615263139863931502145574023409271366607184022883633956462520950749009555733446166344352139336937228197601033610653496636589715189043372081365655218047154629886045141474864377623495713925090576119950184036107533736987989145014903714180934076918440652869043684104666276188577527816042601802439321071958914710127970010856350985129197268166515478343980618705874533919155520655379082604950894738243000010264915875967043732378839335373284571127853776252526581716217379792686474468472215705063610670652696611836468420250264266789119411583230708142312605062950572227929437697501151848922713412288356737826091454728038730832823838516094590510022139815581169469462446070163142997912770067541319763444121260318915983308348621306931708137341825068149536795201259548497770495961755171283626294700204478727572050072771059517346108506479036874590109274136719910898996601907678252420215670817701454286290323992580159221770937668140626821307238124281167059754303202868750417577387118919452619199537042026596359539075058660508102961352806876089439863181425208781544627075672164664825035509313030398105200068827120338729471478673504514629195020052266000288409114227668929491485032013797640737834776626456099187663333773259813960332553877575801819957646347808814680898199599825416964215515166741421018647521780904758545110525679855376602584456900683776059192522989115977069872390898814817825437949838532345256909136019104339794945790318149786876641896422471159191380493697406886947805814845693023391511544843470399199040278112745127542103628445864813684389984902526171380104948617314597259766236797305087593787633802892639378626549588841275573771748926037434011461097600906132886823211790308712150134515517898375655769930741669504853094621272894302562874647250252395625293237280984997256809138152045281280000, - -8526779427672780487464091491876430158236144482873220401331977507362876577820990995275094693379073279533684451955740766954429383433608923530086075117740391494206087946796139766375425135431024824166516384504180091353272510241464868037735295100426731755949650875869189127584430729574118345987229483599097433302482170757559216071315852856377076252443456398858851949483110388846940863936339885098502938621214711536227445422131286182486777913281246933971790871296658079870245856307709187634263365101491108484008976685669993701392426044986773784635899462507794758441109733041594459262137231006524282835440870525081931933174568622274667513894115048755334108390595306961628978642103315458166028107591890995050659637708167552635913763852629542580107401365277155436880262985617150621677317992892607008432102896330155444439678252913234128564270597238721388276247828664074892895093056491562023772720884011739300188054127276470612887127855772613249772227675294259988275166256489378263660928680595348767837006401067421573040867471367599316851593857912333611412524839113267480775044871109275867656278364004717523141165380271925008670529996111747108515202167246678506010657369922165723445872376812311651797667135384365318860491658777164461775297504701332160057173744462285734200723972437245752889315605530131057198410324835669905506120457156133234222627859720130700554045753974150421957665208054531146622870792665152276323197453715906412819469736007522190182730790662862537802191854249420877111491726978474226320190877092981364881084301606811714265039075490186013235158768240970067580517235844656286557208817238751842742674699130156985051182359910698425130564046384237935446786672501466548151669971391767441273602092502883035845338570507468444880679591153933323223643928191513414482399430342814836879449101712556152657716281794675517708106113479260285713163208982268135726206040435560827819459627474641892818548646415420710011371162318376681835087329429897332175316318214189778365199182485208214039128198081561036519571727686087586313521480147426553191397608259861817909208532432371567012093870650507291603988916099444295811724563717133006966546929474960323772405592915394552574998521851313759411260053508921142000957029917283413214597354626427607072009910477260340692283675376735654761422607267999689100516958149865848238083932678785803116409120907017244575883976303731611797094578476693150713285069697947273744292850558816502503890521510779458039131418021002819449297561575208602038897501090324995121716987994814648304256498646127392742997210493866611757521083249647789133684437832806119000651547547232708342879536524362893545386663620945959147525021924160216869887093515209747394529131611961804510819452913768599345973096687656085237725955444111514753121345618626114614529564307944778505940122875088761084369390608993886964650271904310368902368503730710520027361284781993489079583573714731503273254702272243106204467399412319107374197806563142168072349319965916066960182277995488201967416984483964281245073636081397358714306195907553130066347601583310474603722353072383015034823692919687246283727948901158296909960001791341713673948404918848779750826375919826296277400505372654234941452425602790484246316441795877822506862089804795238848586338840053926799386690938257106321874933663470235350362598961252056862673392498142870670936048169659373495057755562069614102133427514984047183669950944527768335507855419861978301076493390791412451619296370418684416882602577146744404631725192461187569149199112802991720524930570941275259759075287211994924808970869028506014686463036658477579034772042375994519383659193089906054173325874044984210752798851838659306662510028930096146008996152832310726853695211780548907221391856342220643198079465808188524913156441253625990369489210331051362645793802508254959229158512263420215907472996098474689760827058448533937603602951203619923304983120420817440327466628245228909381844715223308413929677590832852223975538117440438904207398499015370916308543202786439828687668701296232861699960712580409565792196093575461252360801292793266347532862180439115449061853893150626807116316032682531339266727215020180124305980477600266873651513505291987707805008117512823724661547681161346684289990880207942073307983456711250226628268199338931000303978599920346355364470176026770028288766564196462666815118461703825511208423950025838351264296188355660149867246853231789534368182802535222413205572174905073890223443669867137970001408290689963852088259914849932455402365580649784119157379463399711679068102930139241645201056969994323727298562082292427551011037011914851220433501898353573059457331982253558700679995063198983504771648993940846062244746510197966255162653177158048158324829577630699430345169433652097187106177513212889013453816253684896054712794475223499904810062161122398120650042425455990957948224265686161346707628988194881919698305371281095038815022857030187392630446078641142184207060029211532940508692292802401248200574524582209338964058481776684302123906744168167194993717910853306905811964401074658467379288701453619596905212143334884913178293276081088607280861893088112392828166714964973697465496323046533560333189173424211646824549171732596584187597829194826774488381994397763947885785743264765782371091322884524577938097094025802145898260666627208735750142396350113689420751130948778262697834406977660492166478439472389675030277413347422788906195290386994184450421116203164164111412765087121769040787879408293115973484784113546470659211844255935630918307898371080864312058529293796306784431931548096191082269536234022188956175504782048454248713359326699951086842770257197196902130844968751793154915471954033186486039292982093868148251899535655612214343742978126244431740793124001941292240996735597161924102880899072230529166902965051538324938065259846908693369193333960293997684891345027891384460175052701969801102537967882445431319075008895310789654964338318081513083575505585189067285691610594849028375441009303554729178017604890503239419587496032128433499915662940626628555469833022457422540074402946278597355300597472191040303387175808552711777361622492594199503891616592338610524978182102098619875544516834989934985255822615115721450539616343595720052666528274501399015117698949763263520532484096820901970527439116008473777806044733661862832735497451201207069813140514229855162345873412837698967848403867132338005001248616094569298946861152576125388987787493238942259836420447009541242108233963116648722363375054283089852922568581867261173595571392794031865701511586169136419697005918434124182878980599504266680801373728758885127634403292625090024291771042086941390504798044639256983194359402213806196755036267994137100309947929839425208774422501420890084428183249872104771115635756763940269480775228190317313509732228541501719399284138700661493668848916596825990406941859746644839861267437805567852949688163074285786247113083048252016055659179637945252901194734663540145264619775311959584204253687224707397456834339498435217466643729877819143153960619793740350925741332606701904247570373981736398645185551818464890350301901807200207124565645193720297131742480718556836222806729225223417179621946548634706222582876677742955707560536678504840234338361771425809239563563178529889089374426204225075550079555699939368860628553082477458939330188023854349469692527018553636759490166420086142257241528232919449339772037880365938470180494444392448775546603195460102599475200000, - -334454318261091009058275244233149062417109248677840015982842390061994921408972707524964626183589357420837469677710419173247196809088103174029645435091692892524027936836013013099539203429597757422147386696911409940853202514710957510641334587137475969838248464455305925354052223221400931603009827725383721607811149344532658666674448969657940212871665945271911964687633814677215762450729783432436962303966193901587469294783418651998609743834748455036068899518418377673975518840465910092566935893493419537576885744747755349532716973003427817450421841261654683255033976002976264261404286558428185173220064151355788711286976600604241240102745463766259917819298516540643640673114752793181337514692556457708520043134013866290512949235012410106472135662020128396994843652043112595145076127389734326817139161872068032561704125151336898375698661679610200840664705064967392382109180934270787709741106156610089280287625062484282229165560913848617132198366465154222588153754374272413382839440868734438070576701058127920230650393834379074049102970567342500231699859413072347312537952791500566525627548021046436440800559467128257063849379319003944658234211153558239867513410958589997796256839501290380502119917020151917250430279216374535617854387282397718438769921205700759155337211151421995631638887596718527051280422007584436294418540616656910082127868396097029356604108229189421594967316854200722666138487753837057872776711622617070568033268737083202029883643562997210555805980537654177277089344010771536883700077395023055805351406134004625885258822010753961619626981193316716541763004919894152848920624800735078448616060560475472132985178954390329915885965385806069230275463543177606677100811982055144467949394818842394421849761479182033023800021625618258757179396409837224290149692915036180368924960573813165187364190294648061561749297990366366286680758492502040107666206697088781480207797047153337961409010474422964154433976090760714017903351755659102889594385676558665217912633363147659902202778760117720130184559727241773238127319427579865872957177477640798112432778383665503035864542238074795763019559087473934884853825440807366012627572369384728711424409049343528453764273495548504151092189496493454060207396856053558137381853161904645485536421164478235138881846529787686970738097617806175222763768838576181288192066140000997273609693369650693212309403227644980924531986745607369624697010659089857152652497802380258580976313760223453716566797522849701198422547619913994109394071858387450704140493989017534768743141284178521196465575102641859868027040226743825483923933428019862889143225242683441078511618891567501992496237090948731860662913740171477525030893522300695359051581677670774695313825265844081149405614018727601080590213765616967050978585327015883764093562212883385810862804015301017240170668124848951052058605531325687045459078381258579111614805603734520223427598754063332680576536052146357691557680692399708170856238294282089029522201946341606842632801769145824222169198009670822717054841986404849235176470895988224589664290531851365000996394680814419090752422860805696930392788271238195338636817788643063328440927822168104458783228119909886801289629319948774987909726988328836260190802046999276094725717047675774662157535931865328100435599838800588547054929091353207758519071070521736308841306505597055995755841807520378454146842040808066644867552848870545532697717438975259746366673027982383662719995940207611717970948636239970161295159963585066527902195657078912601441723940484842071950767489765319352692530041146626897435093030367250113829538072518722580657564335436076409079393023049945243916831185176338304905165760110856477066724522346337947235303522293847624262444669564453049554395169578242112459248629776142387068931548648890793090661839920677888262709221817117934201594527584211598704452100185903758362756246844758567464052479558154976555120841267345187920319282026929075621870775169571901941144882652493943531314524741602338295200901930717448462444865776712762218887100414903197745731547509552647874043630987446188471627330896065971296470239639203085974103079796446559115782274948285242429176991825234646121274601892638547390771056308342645459310239450872315500416438033739709518884584135621261201707551724367404699153680847738071526076445899804133327876843678953058772088603499538550029829085048092097164504289335831827791847705651693205709541474033707974806307072235051721841083848364625934384745138071177841866879971036023446692816519297770401616696710260456990984090784723351436808561594270031471146556729806145314010345406059420686284717853327587581389744416782844524411111027842552551687668642371300087897246711665769439522163046175348691369987516121434292485776477977556929917125826778870092607983501357615773481804490294157977526262738113095898292377973926585907564149598107490396410871790624618816369398077929350937481896989902508840680213103548472040500263070300822423021692762467346298777071958240184139689549063424201017731907732144274678678179833697248052675793849829724491919470196391343568514797169210726334071469099250855402889040611161764040011535117635963781817528857520661879440349450027131408112697730883827728673084264985500369328621091488356281978652605031410973063528336892011877738004175820003767221253074714021585139948830881701463196338484672213010288528774980563632873348200101756546795074316150150493230757339497812309304848971583411319790860128931041954321808421313206258614114594381703802599665078080700947931662179222120332078662862844296725420690312087384026998793377015623062643817023427788451038571524144260803559188230087282820484532362019027838337793484000544606012757313550013712364511005923911508286154997215811011429858420023326633087503416803917400701040942115867558334252520923898305112337289600074703707361149160972865807253012950939345660721116312676891939878145047708680330121833292289901782832557417744500448994437963050258820799753739146402665809331321902279951106302292960774082656508058846931983466891644054843401173570043772256349929836902707144929961784890637372334829704859268837966459425774156136564896989799767138774632355413363887069574255948025835732426749230509148167331575022654829495191344758335565962494264620619553656822432143316016353207593266074180747941301691199992715996450600706061085637461066508834041943283004313340921092097254503420899719535930852150528607826120181537585915647528004353322613121386842012539148830120612611545213311982761667545705492775965374267880727261692041675130782592228679754791440750094085225687538506725765157437892094953971902326754440265552983368331030161806373391926387351880949314414593366637743078783583025557738898482111399822696060434855495269744345515991458583398411562217606652596817387205527154265189767844409023857432428946200625365185703900147516546451642377981808319826130077211728529080256280029378161930382712080798809585934909256862971287091507010165779538641672955847665195435214435234008263845716650705010341596611708590414157532417794500228655656431384551498807110594393022195993889751149650255863694785136687539887580479697423503987371624216549933989684203376638559383084278129725179892626226251481852117328284769726827713658505247160950045368807821121260444216944106803918726351410485137035710275088493797897642443645784428122845638933184154474908746641433111614933531266848005232115450237187590813261352029442924172491422045929650257920000, - -4854852664502804166670701890730040856387473152670876588027564616836879620570773048551659710715354306065038808638767953868560004413461726259057251508775106794326328957410450224415347565576528656623573435157665617682757984369400361401285704279936193649397404486156067506067983116069286590434436200649286485970635726744241399393555223279867101712210619248115291698102030335813651488701056942976304367126924209727891574204815234438599408367958849508365646717624796713906077042454933856543338466445268636364970249269134660850994063644272639964795067197798533557946233188366420694231578304778541608999154251064758701147537422351025908628849558144308731690120993892879260097076106003662434068223417189689018648119583733032050016179772291881320696128853861774854543985829414493310203259631273329819513141515469428132804712588306133668265523943453442979844225578575508895695869284668063481411873247697566285205713576380932327362037135161191945463775245139944961070364031504876929100474748894697134551554453691964557168852156494400931918635069027777614602052104412951754993918856573888097583222486674073852181450343843846300267556967313100061329758340671587599215617328227796177492077562546385216337102386535624816276467383092427000268206137501182964104404849046544949756950399797207108078159155124140920069102521749883572649348804362879357621631789658541966258469908960982695013827176460520498537614770293077031265970415982057375438687801466853086485408046477753087536451447411534590141347295234873555250583323882592913862138873632205222427710339931097485580292939010741170504985196111871744343303355658187258129925956039309399545486654970603800581425759964602429193714197706295827206211190186175869077540372990312615627656608922842775765512547432354908724845103724958042556802172213005605421787756869646559355438528353381803996433384969421846070117341431292286833936032970275693119200200884068514583971865645712947015571914647572810900750196613328130219095766747106184850160099139713946271603502657038074950124099944241819995295497706822240813022775713861076054396709217800285176179361732407413728641614495016515626304422344377839403169960226776713472534435997701242552605137698275697292741966887774585058471176680251848082706020196300454236601562758992516780799725702221241531927878827339498369537550228119713119764847738933058053354427519106741182995530539625838435118313228534635096752760054088798889050551836936121297441097150659445172840319025173954154749331855390982528352371915515561811827391174489801108869333196631061097627219564213154254431010377368248237685529361906149247067847213290981373014033993434052405610769378354618654149053729695172588968309527384945923098398167717598797730694743003981679495066283656049894539391131010851087524142430488449489534774760398087522286554719378059201845941426114299232501155588156806083223110774223577251101613865356628369396711602170827305479829629856564345377507834994257760847034183873000004586445267456395902623983936486283669603126386258996298872743241070049519396840974020904369789878331194511861114509908807950091417837735826788900006707768468668019694879021988231208668217936051017959830928588120699598024525624588809876203968160468278804169312345955261209435882551852518419193559478816019696173789933344393837145353528944801907373264405452084201581479924832904926130320286456375645210780765620986165593113319375686823336027275247166059656855997075956376761565326864865884729003970079596136654353095679336643277571296568695106734957267310143766660971591394291355486104302397738074931468753316449446928692571416983100756952102255946314763445207576695560721026579672036503767159675009373273078106758929869865810314485086388725905839875545445637435891857831599801631440843442704416767847920166631023392497626822346125420617225742048995544306237199067162873233502938610063986147182149513877061005436629191658424374392433139257581371011509535321616169387706910632477557822589022248221430241901051152482278125955153065385119410907908214559953047077497174805488202132013390444480760273082823276150908102353663091471263108775218935319866184522550592214834357630472433737699727740745485242767992371971780384604845667275301176581853157903505629252796025328706850989690735814727612639381750915571386407504227426833201853636369799632366026005936686989177353739510654568079699835062009767937220068687657977940762306221928969298423062526170074101815121913681962186477804233922367826404286016454176871068200862291710559826448235376550489500648547206549497132958285389927841993673217139300576038773201555291976773477306330331870784423251616776127281829972386109337225628937690780136862943376012650209606261735448829823165337536365105575973057886536769035680028459698741340322989964556037555364213213143263409549582092474496046009908690785994544764069106002501877444455904401426627793817873381510478023822513577746013919636546627188015853752631907276201018273352709303488000067636401468002103198945990746014690186178524342561344223631836955986648674563123522042416455357969076232589232684382005081913929830748514004138097322526815641626693137689908484710329877007968900072421432597596485385423817505593224088416139924322995402839090635419741337394124247782473194486865762160375130216252596717000180926935880422769764814295246286926770366449184331852287541279419750629697455373873701816614003747848916425366722280822558834882201896664963492837261206285321146011549605868433075934709039551478377169274749877309474881297330322262547355603855853749847027450631327341798654001937577365644348927978332394141235542566873697575813507012060480374644477775370399078964822100834872756625882486660587110179951597335451703669065240909303699106122810532455377833372229039404469275804054920249429562557162426945805217203898230664490371502253564329823845549631288775578186958077006618919044820048176256194791665535964200975595624562575584438629506209442971644224272834118622028377448546710512922476271779929450012102865955695710421693287806816671766275393110456137841045651621048410469339505573073556305048887081107942669791583578727040253623121642328160434737318702603425542497814838247930606517967953297983004413749287176263877509813963777733531746145052474832174431483900380764687684297151671324056062371763901944071162088376528860749372990154295281231260226219795845238198395869966114154497012277790665346494009970400269825629791547502322756835350239817392406123665560771258704478974355654836504214357149606862028163790539923373203985091148184833182546334536933692420552631916189712618186318670858965385962465713475465407276256099580407146054275574036824540672833905539926594992388781265647026317168010357214894500037626814463884490757130125548035186901243632636055515373311731493489536988123565465798296882178400715338097986051996297219554489124883409390880542628001146236597086883539542429896712072206675885131757897671270170589470170477770045008760246547308610305078534300776417040451485391523202371430335198701226089642967626621366301579944213298802148428254297320112169596696135619076389063100189146520128557157131532554034498875819886938412492306728964044367801286429411669763364928019585499830815663304423629216724467816617149663051308007214439400417575601866900487499752102030706061846732801364863861906437138791034540267385506391828293941988191369733410889257897515297585499385086801690166231452872468122828800000, - -23805367539424237311662586892126932567580657318191345200268311361252809425565962741975523522252495193689100543659146276365062599880887843761458154845733456760709164625792247710732265291278386206385042123057326308975639734494262878839300319527046621280611257604851869518875664846927950592778553053647234470355959915325721609606301034988687552067377058612526217909160706090975672893538379502928337645969778318048323437201007366035011063561612468265566014077427108978481696334109265745614257792638489410542294487012256511439205557704356213889157468703740467518397760185416895346610294350882294932977589456399726996100347117038973177278808814835491426593063856245185365840579490351034243474158088721028598167380239292436166449863451125984221465103085896744428386830261364434386125043226686720734393386282693093826880966003381929527157101042768555802696604118039276212655814713733206499971228402828414858644937947802961043501564692843920687855036056840015806460816665698695538737930112736272244773119942452699482885310921107527050218770409145002184516626528495887000621498957661523311932297754597043799435963350107432512716906420764990931304992315586950253286463822277963636840757706504271154030640914343791889989212770969853648202152128982251770565844559107145454285207503476070313337030349846646189535902951212812597851972146435543041275473446393819932598710505654203650114317710205407620094459182800898177139391603136489030682582625788087886947373307256399658416658055878966712013084135297324352545125460885157235605153659762872705251545763656468348076700923239047251341399184219049202193036172212111861369684763257532993278026918236119385563726566906532741201636016682078075615343770887839850591399910654993699309483780472104964782380238052397006476426605032501341575430750255672920380071717807904417596285673758379762211686995678793278757725423356717980713412673664012210201836401042804380329547948363726635717669230006793979881607367118721083884361236234618421054413042352461780074254235009912325474324887676947389844808951849510827040840795663087293824421269183995820244781953070056993014114933068956047695357983336912855555848708934753482156448611149932042041706833969551088325056964623587111293849315173522330016964623620519295500594126724724996446496515624078665658279450996057295986222590471502975692444999117988211477273633382026406906081362222941757014988004437973751499975157936128505680757300589790077733886233280472280522204923708783862619506702322915592057812025072401692499222549250319035936456823652020148297783859579273174133031312497427033427924115781219037098103992543406819434785299870050948741445859756211546960778701896439707965536379249277072663575446649729457904518399165703536298839378145252583137063059249720266029989187913564607554144142068025924003202977403968861842096398191507858514219107836104630023368627480884145463800954047510658602785586371613899592576721349217891352015628298528027515492739434858826184578216914894967682072382402957519360660340699799842814048107785484013988732210804741222218439914086574425159450260064483315051993633905947092637405778241367032265407829315237741945875392333513583460609748152303237892908563984143584329721429995744522732414919192859249477555120573097306738022055296059313329941879065915628640849652769797741411424839031370023610206304430472474420074447915892723238142780086957718501092481297745111390253356066932988888486901307220007740578573888250149878302759500329414969062404338731594758384789102789465694588978734335860288777153999399409187742455163600674305271800310785119883455603796056396674201175950121751121507846851177789879846499339824262516395289446495318485639630805545634175841013740502599347217132369534472841639439046455747304265025969156215152536067331410191500132873389062380015830292868707306380543753092577567688366655031197220967615025379234474912242376698063971858690447663531067324979375652871997094358197549334965390958160790555147722322176336246925697443700853453301398817984680902179065150639660015567634750997101397452621936685178580991303964516581362540645986548504043473074602383965770673046779825553266911055698199573861822673773028586540828967584188304775240386812370617191292314176369874807122087884224008234614737127684778194434485864425849963745003324897665611658099685360035068059488478935327434175285296713689114248178263194434287296140860789741495457413354515093934247092957427643769881025337034844278719654241364879199830467825746775120157221188822643699475783213617703552933540381891053903053899215189566353221455627259050652081044671942610791748709545087339343802752432192702184414556188352388647556948635905445707553232672592584173868039846866433247355159274876615324477320003270751835129957180690414836442165442674538106300779311570170369295682444559959927340665746189820628911250990868322684411258336257760390877583845645864947108883287657374033863406503423087336020477445200071614575449254018757203034482344814165506990913248464831833873019599506407875867812019519126172668871503160587214211635273439786443382943251803593025570066961323358788452981564037704852137542825722785236720763651941569826462837990518351557084984392856568358338925540347815942094564212914581508036877740703814369355767988801558838339877237936551386703199660327479241174752521013586112794660267227329807114178575782962586942534180875718272865769239048462943402096823471028632098738583585719077433414342963185478726353009907217566943897736762896897934539612595160466261295180959028185677712612528719466576621821905481907985877305618332728656628124545168163135592880375818902361624874181660694724340494261814274030438731198809846135133157162138526992393197173455044303802756608189352990384493270255852378977231293695421690446401963488924232824394674658368440870141336095375385240062574848534873897920515406400039601635179594243045258345435842061894274903354291871852839703037783157666028068226984912889249959401017662921875821957555628386229186613313469665259717031020445488701736139221375871297211987663126259853706658360301265764497380659088077246281509701072861758147269164565004392328317530217898553016100749251754331104966792249077557905373580018509067750488754448850659582720159924185448138553005412842658117469559388917307755190895207756860061869146514192969979530041539017959451772062877097981033620127745628516536432655124906899210692842903816827063949600926767842033901994117647572338361539410711770923063678745464462810912623910741102482322641078257588623190310183828095563124792374806278434872132231590384328873233648015277805796522046929487187218919358393115269264644730132036619567805765682795405197447686757889202672805516655515149388506862342405822307732204484026894477680063339524868411425600444346945483792521499984393939503944936455100570654203997708765813545312871513508812045840786825167580818811250939154489047469389488720932410043083050138508685947323967832650738216524363048601186702058503906513848632081254921221049515273334731755625012111554699260111239186898808942735781668959467397934452156856744787366767314828883634463787745609636386181749461501594280020211186656902426135139369642857006444441246211061764893089565474360542334378340974707793119182255233880567201585392889299029828936190574930399648756583961832472780691861309768952700435073310893745870137739041072920898513911633534467209617735680000, - 555558598392492358221159996963038377912408778496156022594585164169963999772747547587753838655532044757080630888394843595092544550489645086843739641381435499654272507379448262723588939715775746912816276445101514173046336955212763007543376852806245675027713702744908429451245799574329064529187385435745935622072866196855056939547642199204674005658945791612457561778071654170152086110822761388239664392136925248509829252892896931169521216503254518009381290066616381330785699682925761717477348152298047072304870980584482223999046467417213763141901845974590373498209451512829719502835145018405634546553359129767057524060812790733014542805212043255926963304098413468047524535822543086727985579321905331125932030056226134952647260461474054843338896244157096259327283785778469116172222281707316123036638328542423314421561227973270074000423320573370830494931608757792130930135745603189518732606067991297323647930513040781824390625380671564461135226194728261021915967576628556057878044580468592990547629044112587749595317020341780940524200733411375019915159420745491060459846136001392112032596846047947335777126396703195547656843072077155723178625163200699436060234349744009322492072591884458978838215585934113346638778309965692302673528540197859955035367346285614283376913566716422944482801294538072572653236808897954480026583562855914953814907978564131402732226247355470126130198533411800722121988377858107272865608966899556928084371645574498962385958870121406768183743733005769968543955839584419141908006102911957115393647382498085588654624386850801000952696919413117682603696718441212765870885502780930547730757334983904231851584676765080392032984728553833048429169624726421768744436603316094115905835756924799256105240461249831314815921637074562966267895689645587919677904454322299337173968011451443245900154532779601062541079408175316445620623721487884758678093372562290953395157359922720201105719984417358251346560324962172001789135176112845171273885182927901986649891877326868268708355871932058147032623832416381763791717274745511530086782821628554137957045726964632051619326338491446701954353250508798434607325090216370579596947762503036781987161139441228154575098202329492774211729924721094244380022102518531563150622224758003037980444796635010139520212200062716833420297094799615964039805386504816080207263465542646192956087680319618500141914445736705730474688552947585158608849762387625109873149595786087026578898332737172774662348969040696066321389666321720362718605181605662708582849027347217816188843937528453035300440060853848206241989119943058093839798461428586129949077116087704082857824616635907197362000878228892458512313503808415147764486681328060080131564509757694088700650275525144433536829132866766980619959829445768862044959234890685638314083321397145359013952905811990466417112338912836526015924602701390293025815840558409898689970670408182390804155872043793718735360122915723619779729130042438826594327440560551848112467826786703151763642540053129587578470648350046254679743642931132040208925662400217107562646728837490056420938905196116085831223068458826143264875026630641290985195979246325988202365137555903725049886889746166088007100939637199411458111986000813661403164069072854806731410192322035207704123804532228602978570392614597725849954044795022565944462374699120733455894109978845211674118526900812235466762866160363692199823881265195081721176213575699797448508775355275122906489482124243130590785056097824674705079552069934028898950470017617132348629350734857192919139406203541554031435035455088180375052755328327343654176755619731004881877183170774471232669661856737537989314508204689058417497619183321886330318309678451053380672268828749354188375126463110783799622831533643753979483513565259727743549457813221523906361783355905175776673482906771366489178645629610017725241905650652756209575733002517068826268558974475578748347712761930562180041026854043977988134252086573283933083702659151458938235957718725982731858751819039183876710167646788384569819143935871941482858997906221655964617954787686360141963877053257599365491506685793373240379974247165349019762371398095183852316503958676788858285768507083600964746034604642717295752661266963103788045647585716082355946154035864388605210873891442101233495867914420847510069564098904514818848634078468528363129232582788047248970002921679331952719713747692623477623106409888628515370543753577092789503035893294163891848751487779821589826036051834963280829783454746756198725405527739370260292596157222282611794228578558637250219946330034118173529887811675446627577705178067133586820620899272814708051452311290564786053756230955767321285358942567719278213226639061487736771712263120004652645961894060796972145072560943543144470144291397123278781806672114434689735194038788566613347542561561296426944442008797426277970609519836169539179165352438266040153905803940429228682202388552058882377299033537470997399054997142715666375320415846928251525444992840791599227405452554421349194508897518455627238972753856487637638569058608160766381833663078234896235537714362970365485705192125864706575517439210971061759617849245557421245039721959460241856643547052438554760141834964784478538228974474906218055119676779878440237317363449387299173517791618046556290432555844268736889799777866108412796611235327784159938400058036424804692914566417382233502232415528282825611103933408457858295559891186523543245096769424977028103659056881789891278949947296862145462340558812553898001590385262899096386729645011046892714313492592974761521932643242391733096251096111576348168950888157877868759123642934901573522462046874186739559978057794772456349613858782581337989711274446530141470886959038673815631544624892720590431033248501109231715773096922111798987834120236848947398603322594646424312461568410689914678640093573363974607780434039262890593247571242088341636706307649935878523839756006197292029822689464851600391852194059775524280724908442978483084941523524708701471335542648585306085750642743972748316124296770023729682687283727021388405923546343278171992231776673439409590559637134314116038700416594224567033829686329422140556961622272310362114676963582187347745216485774396310638289069182157097874322352758452718902255316406936805706705316278696527481015003339365221271253856964039549546114510208212374924420059661357508952403867064935528387085702699808555687535013671066386472541815486019765845225257450343637059658965735848686686339218633668136726758937528789323057750854716662765241445236617073861716891068900494694156735356229779057586615559160952323541394559715828320398077117806518847630429148274815292365059978546809159011641501612067354483478727324066769530690266410644446588444997007302827296263343530035363898909860994272293504334965686239693271547661746891606154751148278535514642189163728880807204111505615622515767378380475786941009342722518570142893366155702102576007151692179954234525096776848013785932254445617971510677012133811919713855588242319815219751986724316826047476712173838719261040576053813138034161422956244452543522468891529273911520670446098464308957775095937745445500695386741992002668037041857138264532389195448103867660555763434762784214899840253623439410765824737427545526911834493887499876827200917910939221647494226538337000947946467427529795499817396642190155945933723962723836887040000, - 15604008540105276001270760261399930032773668617952267372768008801539443291096926261620380250655314244786046930559590536787152405259668037178429405667133993387799144085245579825240508643230418406105569034636527160578114277106181859619081000614344786369540612618219046247615297702235282967331538457959451479243103076075917757092208388443158757351551783884415280094613071410917978387114070195434893955463096069991394099956832787418820255676430158799904053822286172085469604076420498753470520038685896703988919146256221240231840055088013575185390478984943340228188138190774058357270661286821096488802803845812537432709388481819045534849952962364550451743296123324513045348190725776759612039978297155021995934933338311875704430741313201777997527335528974126319501870913116471772434493241360605767277781929651966154498736481242792371972917563165740136313149009111086379618774954305638769121884023067606050211966468224958848580068783473744908630849856856602916621406012899212544459521009177789356587226591301212425321147675718788782144761182319916706305388506953400124789244575793368880281528235958101164373877746491724296451864758119818831206008525155933261086700469103963336162247318484276683394428070973856886449434008210438670777863413283356474727151105213374345667425505772718335243473922369806673341206728423191131258833666812819687752907234868641597506145321959293774177769848043380269021272867145535163305749984831394175126182131935304934912717472064001332965792792076502481884231859155695043493989507624835913650168782251746298791625795892415081122712308776430124807210507562466665911744756076164375569567829894431672874803262871697757480792094111004398210803435858336767662220460585759841935618193356862595460307852641047102841554497902014070688725476552440073271862783251578625325381735684706541961757981318758542475269075993193531668921596300907338679852803882646354564758049372742014722226102538219967544580656224589151765373558131744508499219257971791392439610591745207408599951894609927858052245471403299096816634963211758769713420581937707603848314000548401318288391330219032028682526443829668394430892966937948430169334744968521898605404081388693874841813197263349944599295144889481378101277975083615130060939048934777473003060248296807450147844844575446930597694628106514827434548160278198582293489376153720831379694740986727006761123512215450780254496633836738198339706275105730265107176431979691898614754328133759176015773719559637658071864218890063333815230955127307815187823172386167348481696750553082674395559055179750078196624550491963566862199674411748605737222889632548461824281587463922150659023185491595625552704230350831255947517229825007977057347038648500966110706797059351254166229543519483215579097759709758638352597711915716416162372403561862389077399567325353781879025234725054745694605210365826997420361213111339939249978020740898740746161201861683097393325888179718448508269880156545146991244116028630914291393104681249878153282945900087738566681852095558197961614048305221703054755458856052187896119740813680460754514936863199015545181647878069928949541733015685745997879110079438824729237740341246101109322578605080073837167005418584708717037558678249055191626011503832051222772169269013008564787905099818074107113608968072354142421552231219775096369485645788618501685623780871215503454945112037392822158723239283253877584714330310457951591263723293273597385305483560789741027505938469956602476379674460021201286117503406027233595038675762414972959864699301238362378699633776727386434295719996922789168334708942112430459733685984780716912527979292338227196843965479258344355988699825291581317108632709523266804480751645915139206524216385029043049389106973426774650956632305314900405969800159238512578504951453297955263428810431704474956537952847222573528705142266342393885223202563542543607220929362656893668302182568439598099191541251147921493936663959416529480708339010986575005338001276181947053501696212819221353242771310708752597081277526747535434052556293582003976526377758573863037151460027487592938378019138357701061024865172383794968588638288062870285034970911934735136283203220838985082326800342628496726711604883582409385357554373403509358690285915900868298865685110023284501424505407572224500146418755610500934541290753751103588878890319170425752706591160008484002707099369720737092396435970372970095369562913401248652622807451645104574164244796490056738354276249435273636255617615935716123215464388110744217617396186277272067659804178474697669052829727498644840369727479574900351111900562388681084966124166478330428095608745370127144937307007592890173826719579270816086301234166384649623867259866876591494646604958513948818258359396086221659448705010696033687580025074513145179704631102179452482417406475734189388887076692865343651679893532065546389048596913604484013298635743915264362206974999197033268235443569836434101711923865327119432472000885303848335814834350890690706988700047145466564139053248330765515643366306368270107843316131674161160207436979955767541517635370531278368546828667914508073276070071843366796891872910214019982992600031981331726735501929359477971377819020313674780545143599886322738965615446869484149871476596928146173681554914519313434699320297726694746542800541778879903006069667319963464754175556920207028995242621219962542396949120897284457885843622099759298950255743259896669834041805525503524995853656816911136916693601600848137806618167841506803627977534257160617522471251353817314533331753324965892426035079483611450129895456415228204116284111986278111009960466426501313359942855733275093544975581552770047932083739837606784109121350166072862726381339581237854825150684947957600329235624534863513760075639960457389309351361156681548965939709076195662867971526155096743610380163438925702027570610606582942583778014338364299717344693615325129768450512935472980491812563517127665585338587792991409501444527156911514784654416689168626238015697305879793641535664934794524752386211277666884649083842025428754166793293344082138135516342761917823452551459539831036884564276921534962550102002547492303139215984361192322586333203621383809248734274717171432976716226054826732573398018060843383928810649858228823550498753631138330323902418746524752021587920174936677972960277198201021187764542991589111409966822877351293573402933828678819780040754604012820024150442036571210042239301991641766900547457950439422683361998041672802290540328922874645657182127431245144799224644617057356471951557112945253514415949959738756950240489602800573848504956222005825186327090610046255369244507539670345111756611527200747915460752658587112394482310787850670919681524122924255053455731146893152435338808985774390962533275679618755888733126139348241922262612575160948747423399246460113872215189045522405558487752705308294199348424203192678395995812263345854068955919865100531458417347279170089352264393721461683153193269027564748937909192515865821799990756152489864932031777724430919963942871316013810712073788077823801558924841121520320933516338686979500344281663482909645098718156125056506936480252918255590062325068358993559806953915784832100535752331452544925705072075426127990117725724520412683904689724482815421060900094465114451569656136271597429318637772857265328807631619114048304616602337280000, - 189233615656964106842582698401426347706567435726001529482376299283921826175573079402750475706020465410899652696240419622516768335392444779373137241901091092362703663168519668622511438827972908413534903808340739255323897925355828150108508710159596445720234841706836605293311139338116251173815264648617357908764070086329630686058991546487827697830730638718470161374126520378579654226561613022840785003171217191576442046415384743826617297879743297474686611593830115599466019031600783293797646477300474404575626162511551847143109031162631967639295754449345546922598166620008555857296451512610803029366811717990193925703371085410154851152613097240435161397171987745495990442136261031616390678453094055664810035182256771160348810962900604122582873002489024935409007419167513934926700591309613646411436305345618984189402556876972768557788502780606519392479385743928066767019640714421480272431065904788586685543992670666682569944939438370377921488983802964940033118310007604375902506460096535160982380673013157643323928303131219384131942938021361626784184600425575419082969528910199925056253554867680824263934366678393534113837765655493432157147047224806913382029491777170094456194743128316266567671020698831740957318177804142049059663652354597947154665821551103637935699480033616943793276574285800265913011986585692906809710904953138407452734730381497950485089478429186936729577567457443644913238801704328731172241764995911700134738041683594082648203922549683220970879288038594440074659829837205691732339529431103019518405225510768865312759132990468594392045126514507014035481734190375699932839954018183528458935185486696573697537500448517899421152103630341148484832684406165833302488413368813734350008017700652510557544940076452178991340000256483753097581492557834149755171464281212135376659127292639368500192339800145946898737260045625977363139708393602834029951830682426104710684081753725933215060117415121090423931872567714539756677515714214819492471222485252551954584217388804698812723149313736961467821295251988461899167006175260525338236249900116340057534493762826473615411750747777442798445161715562400047174078054574524594122201220231261922151744734897726966829180387060742275174376215334290068884545762197494549374055663604734573113568022618470133848986282800767484146688770989887073759817198717476453593640510063683124856404455883438304099572160110267291489785383474015964905822233835638143956565239778385900067007673869143869604959421557045706167605568720370927726248570115326198039326632967445928352779780359057656524440704669064672773274189600847804636018644327146587111138080118752961565892198855239239191543533038245949698525593022185143376333102416067840662474151545526707262503611136340494711751070969410361035607882265889162379585136220551217548208435779770318308054979680129989697210035999188363914735033094447194021059082313289132202581806644328027107723349465919528543543488576966458366975345560828069648994217874076803331031715120524608210240156122345234899991037588273482239496911122027145042957304352474646056047917725233263927818786238992507016000756826920659311584737250676243062293914118778250645956150929448657941072657988114922554011036689996300538516468598518543696492272593413524275988594335188062036641764935670917325347106234230759357629542186652988712399534362535740591020013651949302455997153815903890505669078141924071407647145204186130354896693042716717549413608812005958283001605325245130348568001109857615399259584391842651774550988087299273879664746581438834123309821035301622037503008551880604148465117692479851826154153251084355216252277666641568059745556810943356102465197597589959511353551577508120160416838304788429692860171442892084452826472245142498601748217301015698009108800919881459751998679733627642331479627586461867467191143962524609569611253192463699272354014242534281210433045662353693461760193349928542159691346866360032537946273142629333237433750338367439183838822207821378935915204188177897179924300899717068489674711984694126837258375824095845690098087791623085188523785686198403199674322441107950628927417186492035670125091940705168357349056933182270700065766101602616804096568722539672494647585438281776086696797962718628144532568583625648024030261892490517279365119410245442387576780829206135545115912283532727228899518182181298947228615002302391710205083217376340844869902441220138260761782773503504176853693816017042141184472973970411146445938898203264076600788578174711369322293925717858777557625205495101768253848915871078078052492160763562331878547702105282463414386862907889454449552999820387256894452173235709835030532709362837633638220730843117695264673641208903474343724016393378751175645675834727761630770902211400231562894546576784642264955896962412527029597332509985025683112711404332537252035803513751024329049630815162982430215863184300137154652197625896841245074781294318051960660260511209127356035650539098495016261385849552559841201633623591228422851542466761289172030313723810628230291665375438700711984018837049133034852571769584659051396846380077705024797996139374316122636385585604628814136418602155014810872483147812543363000142924860760403969012572153266147914559382356920258944788475015087676621924105861866108914685863954474525786770439232670598127397669973213330781336047182063277398702117662964816127396407403519303897346662232077638319259277833880729910473768820655767326440472910521876141361527663332811394840004947476257238354755122721914253107186375303213354296709134960579350602592104436030743001437374653480973263980124890961478165420211356603461361489593874237926154765344718317419323668683887846777781493468700959035443720817094930627158478406901934263952065466971216104203725679251973234074546312522914711699474039364677657802921557058763663325501814646941134255194820416338336648249087018740130448801519354002627511401977261657255913119001929276003174772106254428842779316885854949961611251611275464301499927251137887692056021726197372220302598637410861487394881952835411164607899268988037409577357559327726971411763022712960680069629888138177281576617918897322451810244735058631800848820761525428577633815468155389082776939979749162609028553112596607594880107836556985765739074747151193628669699725943144467347367698435817869920867480315204117387051668314807308888534614083482784439673018571941852439594758547664988875551746802658178211247802595851748108524275430494765644344591085827523227553220066698012511822522737142483020217306173187138621885621382568658771106037706737276132910252604720803789294474461793894453295048345570769881611286910569649596706460979027667016781243216969669184679878545291419879557422915096753157319303108885998301102226656396568559206462231740573303628617908393734922684505223304191559432219943901153436760588572888287654882751002677569758752148259747002619410195101454553913043220999082848799731683799170326392381688998932933909275712195424567449150348035640870106775026604001296329309962366767879275042849641504233020504889976698191667864824944448999193342233543388717286915602206283825883975371029693265580839236194118809986809487565716096005701511758225850493860070279508815496564642037995738226752802414598138612263987419438194951032266983222615542213369071372730832897016593494071509089475624960000, - 620405388506378778251811554044101799744744065252793071898111919519471723232636805689496466033101592325052849332103788169622329818503269227986691886096205142735904039416378317923873856036422550081562354531196657673989398545266160915036328962412170305969730451557926728451520987748457637217515016023243581315278971349440643060743158075843313825423438662610735824673299306404490156483514415693890078189242946320839606635205464071679695005681010532771596773375256931856812033361922641168645563102234125873091756961196987667762404634979218556546446067688336055337240394847736967977586516295440240449054037194651472998768221368291435636709566098597543069821676442753309387623124564690989838518752075537288433141604417341815786181248452447770836245936377062755690518566887216019289688253697274786491750896373306319256767588469209945071706859367763722530889895900405076611691237343792790793145785071060947668974255186701367636904534789096925556912348398728056520480214394333246083278227684437886443298505056253541020283655867306503406189276931286990161882195514115880114118320126900559938298088366047433059432549268647098719442556060930404347174728620282586596249291680932237190743097886396330801109470453370831180385598518770927584765419105047157301403980861344900266099117867921582760951716519205132912993768725529633757669639941479428366792422056798189715834654161412417144586428060345177415144953116566332332304482097218789936531776646174028396695675423465881089701186508494850302781786472881629677056830826556246730651846363356799672163262908200643284710119206845633038553719303499741302493784355427777943003689815733852872623098828237202949216649252780090124981791513454258685815175994773567905382429640850815408469566232431419205049821827085682529086823858584356860524726007438968667481267662911097305881365174203655737393373696811098705356145957027972784833374387718426410969060850272177838498776039538706777581453155200178347560952150002767876072668776869600833500537718064038892101680884858358180103905401566178562846413274114982450910089186204941001037404821329063354165642477616009893525457635344973309114839024371848432283984449368931139772723398960446613571243161936489029730695849362408760266196776064985548316754866021392588086686525249340787893125200223125250092983115372919061710024342852301734467841491067970724479864608904889782923811313669358621106624046993598932017887136185796969770826713990485737128126563056392433448389900047300693168970369253588517583090655106545986877278907679226517210951834180564883721667718196389967302654652928130276466588332307928879063368130015432147233801768972686231454385198854094541275535650817798500976260477064748987675220677553458525477015239429914997494752177804739697208390604187839573053305840823843298243415415789357673348809180677988475933660054834570753884362158703307599648021860364070230924215989045186731488692241994581521808621541559829693363700547773176785761663791184229951250017873298204433229758583583226047174917295682067898296314593366882591161703845852189648529353050820626554903941223684646415948031575869443526113403028448994008326413589969145317161304323092354537880435962690910586701200734306919925217063222634648344866288546742364853489137836452328820480826916344243821442619378123114840422320134863273346345976897283582884095385361674416256416472990616218763078281282585579559610009657684592505932644780004854118514378671574063665272909549042788317376842822980037857805651729028818529718361870626777643158072243660733187419356482793749924665820721841986766028147702019762115492234648390117902854410168452865366669159091508612274794093518816973931574650065552468696499955831034138308606443246706723509628744793784968576757747294078571322856818944671775561404281267004542530955516448680714435108475917575523947366180068841622078048547097529875542049581283090155613495321578278424599189460777862947948772398411397600408347401449822433577150697716741563112243332347074939842700835177998304492718908980416013493336778268228984253430882599288520165294891463757036041070902889032774237664548933593433633935466715014114462342783995049815563698066813709854355654964399227067318167395824196625734894643267219551706405852286941143483819003628372119565448581547389953609376571590829884729384962625856250266226139832749450509007716853621257774654890691531915529821801833983590275439510463135310498634213251653656297070720506283048447721518999105768692601866696643901262248641351987390741966957007554747304078414383833211101951274121548041429208694956730101991193808143788660921696816918955407838015466246669775943957476276222948481922306592977170405032212823958554652593574811518487015589139779510722514527576567233750484307284854423476875220845701199004589097960206161700613215856914926503686027804482838116347829663223544293875378009667105280651644932117273638615858601052437115160851732456040204179452724145965529953697793408662313373552048120641863806906361125069907816928902930670855169930778647021126110422094350936744384098357115793257488822798946540176480981382208227702447498138981786031177940562742403026586039095753819967571755939104530905466223935729154701017599180476884307043078844323411725363281991942667211807806300264485498847609182711422253531650529655886541886767693221369354583997148721597275185043615255321148837464033272434120134567622739567176345160595543205457627249067320436571573221303532766029505228344054691297297290614918908332881450699127817199965629987059925588149341090729909758041594446834078455281482102363240935635250354869688595258696655573495173969534220606427583549966013299137977065910012250011455598516059961686437810691507090953448095327321209601791278276354052967418238724066349248035182427242975312672257146257367719969662057096000045996285554729705250798481435929126445899334101418849160572211602070584511087121837986214765955769975109352476592782661791927645236002333161597430831607095880211000094782851620104453294871406151845177205020969156305560618592264337340327082837621949731319937566866068074300030277567634818734850373067936154857722651126211982129888199221850180935637142131266567546126078767053223310568526795887602082648210986265217330874910838244870836352884185362079573330790400511852411474376721029856150906650422568073032152611129576574560484632935396372301554459956341862468860890685742582252241439294276246723410097285977992580054289554272698010531861380217503996128055123749013228850961454865348551463649668005186075495724497486286635097486380031499981884497441768875753629769874772348655219171398862113770460289859074581732163307420442508589248858105451741062107352346181230492519762629866771037510458573979525889888241546847130742146413961004472971910982595840663446479196995958328374181570972487458706470759360839756704453801007414069518871935729780558326087337517183255372200510050423324361159743646789517142803900581068294697271380843545005989670288778695194854275414323742126186401180262950704529146676389635597871859452875025612409267026630646665592837994259063344853134306554365149579167266079723413933222354478902548897711219909042981832942973615583230281705150810007879768594793200053929206752089808666399753573228441805124814499310281904791922370376614585303040000, - -22820880197731361128094542039547002209740192022704170659276277761907841413287130127085788875054332693839187601502615001385026278854108848919848440768784926426153912710465718831968921672303102957461420269242508742213129679229395111826602608131722729520113460587908849981859767061363161482905736242463063694479288784080807282773693421678339317344066435081501903522952771195512453214058222680734063683489804406401938817882255900333002258366131975807905275200027394731966439150213251358666129936464504253092755253314738838219135312365982563688908657548721043369482587856728923966877258616814740656407903099724350227889041552945552831433201984156291371929206976980873280718691403742207434027577320822122157261864677359524669927932706956895338074951059672510989124386975681507081877237772050363035718247912612805113229320319519758487917102702456840163840965192584720962940200598763227582266194307555501979981327008397931048067002659364745137707334469819024581899457478883735566411735432056807253180378112296299326973920853092291793761881761841639863317494106087906476480783383754016744934019197026432597887169319225911749938824397780485526194804174373558361140163802521073257963489721467846826122606269681971656295137779401490599288072512144796318342764892199454013290508368393131133853980472475092570604819407672768232190237100758902746701987424442868503545911781622979343932659214641686762557954565822042995757860188734478804623890344170560799914341470297323243337688051765494416392689974770431861489089088686641014255883818138313154786386399115918901480196676525096652885537235300676310738983886190747234624618382361688445892914166136520131169287118555407529095277008316719777581167063656270030243139543003937489395970205179528059206375858227105075981863286100309551664332634516538017041271511121232039468334267915915364560275524652493191520212527313368755831994163198800477155569489468934061301420187191725228250107605076240515125069984078698119252091954244476205804887556409094731289629243897943395967965968247161552410864459042311790869922872640929284334303971421539354366273706335599204278072705813631020938543370469102493812390752938586615611018619692105177636231265098234427476157677890795817313940154489753390932560177915485091348289670497946083105918584046084569863335338327929383964214760805485690442008304732964964904290073326477020460808186248318861847505950319429078645700865907744246680905433684390016679932732290259384404162359191843301205594542338557124020760982276107508503963556774287222498985103301817072867891588927253257520580063435351838319603465957175880707399824562360991989470014764836704772759329456011132978763333767141400494791943039638618980626155533163656783925493807818011736307675768362324105295938078122228895876646959060305318088979563721278619456161323552164381695956943701413359480662847004311076284046718060550699534409407414105394155916211642583166514676246718197802389906550968506325281339824664935346176073718588079279444281752516015165153171130657350111105533970905448684375215536343292333536619455659609121888955194470350003819363262819962610406945698236822627898272918834932627431666194234178390755247080919667644957866881124297039745911428689033606969122470371801686313987307744198715094707562881701968646253325308185327064285754145657102305388083122808596243094282987192216866905001439934860385099207746796773224922803472718924439548797367877392128862365092921063447751287465164246028156237858850561328422255589727666064528435937825095675489843861052092838941757586329111491350873208880701422659263494181330813214383753189626843468235163185816969187265985566307566999558431333234415225433822801789983013578920999566809761095284565978338001227947478592603025214115430211807506056947542896814407746197572258744395507521138064908232062529339519534577413866454475681069052249083855912810298245111233838576072606472311787674264354828968697965388228346695980371720613665455515633746504050996219193570983625084319482001656781254259416050928662572591808384388486664063569076970333097831258136933009100966785809075007488370287803463608936910456076572057838652462903614204677834739990786893783155644687471428313976850521178411107270704502957594255652363304639063115804291540270086719061492611896649592030555550410388052874526444580476392892129678230206605410689579321209346240626839275140790305741711456723303830160115579071908133539310576397718399350734495040864428032752914816243413918238311621376309737073343219136118345341766913818088322296124849867079099256287350419524448046314147628042862500921032854460608388586597201906586538581172055703952393005395834414329574261665642119719343032079017952624804724862744880782927161863171624334254982363778322421802303302602009052005827061570797874617212940016972288403285677312043528098001447224351985596041842937328704346700592114890636970044741589295111324453265369001135263195090513708541828888317058775147064317463151301189452803909416522664008764957009223086364062660215088013436959942397278518389764285952474704152988952234296511773543380337295345193434239027813993711205460894981856096362430543504302292179185260080471822505898272571862902019157863649153047931241901434476951235800400693663774541501442275983643877835941293960819282436141209761720378104954110680675616960033322536728457757195239877504169477568277317033657732674581098936686253775270293901813436138690161597402118677851726352820979147531300535082712753069686944381584660583334110675920829058070645334783502710181830397274544873158203832092897782679398576090374656574278633008727838983420178885110223844900460015441875608636692275843108131923374068132929866794017378884605098666741845098855610303410081991134024700969486934165415171585324804463928359733744375814157017202191725668444783367779917555234685361967744974059783270321879522029074243749145648783643221888411871351199060712803145974582598861014937315392548771081005405359144962124836868410861619230172814928630581935144162006800678493866792830825413914494152087831118551570625213014664587838273495656814848321184838228758145315471212883792961277422267361733261986687956490626803363495342480047838234018779437277286637415106367264018046506916611962142695720349848627676699536504836948232824161772958866927401399029032618953241818961698560601798781553278249952052124102967159081008970396108118482317932287091052417814502446251231619338776123060700340871290345296267843415927067704686818952832148263385273164201281213429867666199628757555293079786995601562274919253621548911490059104719939066754516524990059494436810762199602468792773330937912541045391577642010344894090679103915153053538867912495240388158192113002217445547665765497412150787666029085815958392606578643814087920513882088871270223337350509811204823686340954990487047926423492677593948463179086973790114440112956760221609118251662695896231724105720235194460173739451165070366728931997496205504079789020798289861125207579317281889742780086121631603193233947539978733064527779756423296397619442762186650322132128628763458391269492615443416266450870747241083079415207128257150264317149114439939660348016873270304884377085257095503209791179250095120023942552773029749295107738002531389900907285053440000, - -525466709215566510677552507131177745173771245523212178793774085613169126956361613538828269094661774516276610131306905712692207891567357611650280006105587366434744526557644691762957270945202433561868943093116599391852030402998349050585195269885458283627282881311191810443599818664241238357535478883186384235255936512601455315424088093656874197409368741806220277698601718352543076261759075025581605316792012804082918129044962625831243840918070865237807192296973561206703709292588716369270791806329482769644933673795863979698142112869956330137897744577356704958830260362689726005600781190323176928314302825909672230527095104828068159318123786747215160894808105286694785925834796879326062856451451073571881403289031354661100466660092038967436547629213028016492674496176333407767714741638361716465872363719803829156407285360441514974387436682340595196811885197917043755821514862832977459538251452175060369368589334437562056484890767471719670767826413731521333916233813233472910974590784193602097310537690590568540587562586765137230276490044869248821787270624345180178659510563109234654450972466725198737018083212272590692586159501875521560018753388821267272187024862961096376101938877769316559795324354145071203902680399181983559495456060288479371048737702357535954326212913079865218929370098027529591241801849838170752711281222335487611583775753138070581847481286160638345939971875896992885662799715780395030723760000304047490321609909399183722864011838822798413660239285920213105473527550294765335248621301246138746362700585457515742055076358478782775629921916430909256849439511967697698549756930010090915936882823552849166707701597473451925538883483829105504361634505423257723654555693678371542776544689664068678749356665175628710202897688524112847293531019454914251078141953618790212083944925869457789251439727056787639107982272356080363430897316895593375761833482976536750470473372016613249050037610243881379339028382346583103538059943733985377335557033026500184629817783487305766855161932428971048575853625431623304807724782068156866773815192784895485236917412590039860554840732574112419355747559898775419520963054712575431037175034649137409092824918243996627992419399693008870798586066524392033359952689018813794104707954352897525344390791375366661613457521746978366159047187727702807517064927174314609219686894150980338736815039518240576367515322340137375671964132667517681398612683660099851768406174504579012843013127154755223995581905503331938777762120533679137060037111102859100818221871863399495728797961451871119332797308431048166673571308156507599371787374271579831970497136044148316067539573868486703327577721674002295643822770717292567422113673143282596917886637015888780527292098542375114401555318602753987941712673074365193232428060307992150899886677903277190890480971345976475493454942029776054472112815000719724414279565125451782854263802284888761478315425150014498829004239810316719305154825503376227184307248005805107745032485767085782278025852442207625209137534789221257798203301573018237577261172322754015589497351576077537792638994394745730861707679180830019608770112312406818447891781996427324804087975321226922237860201325242235912101742940709336612463555023371746362901618809282680862162087320056318242128756360581501478088516273344488048889328005071674407727125640902276669244770057636528928661224310556389556216539990218255464900171130137390821578929588600429739812485073491632731762871991481877777223011945721634972054106854775946080615410617364315759046414523786439069771746226941678912935755850162598121672117460020870848125086060500518380242623345052246291459192371972491437885298612837944770102211556833674498798244453733100284937821499401402369957885481706424253864788120050898207690450484910477368794485340393753128136716089511541135967326663379603815424334044794770443714439738318569507330781055863100194863369600576526374993338855624850127385008708021323475882313604758117882774522493045755753473330939034436459629521970994239062276707234317717979820628250556933200310843229088936373376423593895010626150778668294291535004362846371447464194791780788379354177230304691678968989203138842180887368536191358937995037930981770188430507907303513423873812506585298536470922275455179263894079432985255787228402108045203513098987926496330150412763486696572220202659458214055652776598354124356112616427794721406151698040570867787936853207684924589620736203931044116914928690894965855269386535036590568146086884082543939239068764652111503936517963092018146858401435377229358444730704036758203122196194672949092901440200448601073550364256047781433832883014062830353297413680465837718180244270886862917073938242786735333355774430116484568968786190973478570187788873591894078579984563984484242376868327661988882289706075502442034734119693117900386910298391001687734148419124729817971470507992340477699347615818241899724468943952832947848057061807298939139829533239773188268183153730371870122141927623884603398263082689995090940357414930195040093358694292971827766827374381512452268323555616047778896818073388003152380255000130670735588653269949413154028789862255578524226176224072157592032533400935323578860005795132309813055755729634107302045476810951380989277123956610944029432230082680998402103154451189743598183931707256388580742107928799542987102790184829374155856911659691431929640489806919743458357369406663399459530843913843890168300443840869126840265330213496849547569503113938483719262611896713537292571178848933913669456308048425294905049574703835782521032631505015722301300914975540591524968976186469981585379694517295042163590322557170805810164770792202411806593449115698688463862357843076314837132171648546946546306411588454318714045765087273404043933831554028023621223096099838513046012363169932793020383070873700913702762798102743627484767189598510415136297178813625349766970059935668288351734792909996056756395683523588596787118105217208349006795558160239276411788317818194385382453740265224854787595764351677815335666540441284627530141548401943850356349913878944202846016380891330390002127330295596203506918161771297995367255776318773947267258310453505007666989998002586968207828988690446501364058043530480310911217661561577357276239369924839031367905719923330539989841032885208789763657291281563722850387904287014489067981638699697466966658361824754395601209871232488138898205185429211333408288571167578758182455512948811657079865197508090771027834488290870633261363784341406798727591806336216271990571069562684061865638449375734288368737044678714066687121905091158016757889752472634471028267644124955406498629472837106711214698357006010142873641169343152575977064783445062024397884188855378904043382769232208812398929653351964712279283455406130748576087760714803902792304763726930886933656656427919630680050983877303995293737393282260385853469227335214742408670476127154288194320397295847993472268819668037480212067052905116546738676593890585959283982669742465109053530194807100160918411922851229068472134319845097283891632402250205921744463946274587916829985044489476610434053305355703127378135221379507476428622682181447991370013476742873772964476144990512864183913197901983554812981798764544000000, - -5634270289523595337610744918922374429563551338654857447306262989669898898551749994253819530097291353449216532659913199508971731414043900752559010447323828137393675180528680866311421451125596430309182887758722298829796184855634529962419752211928134625860889607708825731534043305857637184057213810698734599474086529461108519319341601176788200496462036874104434095318943947149069973444408347938434553753438998462177002540790693901118837907400941759162755584513624928571674875751821744291006691244444497292264155632829670334484616562268052748161998150475998523562355171523631236335662419781285280845174563289375160486988633401768063049112673117030408000165872908363629895267455287645516648658117818601280687863589995739952135696569577882426007716714594981552671729106449272350472640042561358067922885543278630458201731262630326461197916066493908728402266639572860141551396841953035854862151282270121156410008211662569952959572712384935122150895751584405091688498624571009918473501595348002357804636443999847399864394550935018294550633399509979332544327938339053558814437266112637548413026050456552390427889112172436158000954971809475570441606475597276320048051672073975644734739699108783183890517691962826564604352448584572095347058522542259987931350219946222672060746850213071512162719322014718740818612034423473218118642503649015328421494052587413711042473059382523088723672998859032398765114271997741629970537368773866715214234730479761551839200804403516465088693379401462135137568861385580134878220351040994217690825352454461117477715415453524858963774237298497922622948788109577310295120542176087866255683620248055182645381340819286450117617465216872970965850978642833151613804581684522327921570596207386412950668221832079966987399503538610060219570939974571394958317641490796661143850603413648551269228271157219670513909665220945302617631485831701570937963830629043799937835305792693890745012557055821255431136022729131029076265805145290206396520298549411575415500717761414483677313665158265079127136431669810899711063084742591568153901089771302435924772818486764507445908134721931703637397664636597065788723244364970062473291152291582647435669234064045601669393491969181380044463307733715954316682444410215490607434439486305760939284567766669809616181077107763574990667359867509093236864355311859666662288361680646658995125674133770838380892008791711493826484997091050128972235658785211260602291378760773020102438872537318282334351261548678810131556486878018016711471607840643740860206013919613739584457649122936301542831826273007154815383229000646870300529037024178742442826498272165275595274659377375108176801184608562235760886152354233553793874965518743887040622342704640257560291414841993569006400015357176290709244389752311343453900832516559686622720695633010591289100178103913244376220866244501601487271053243846215354037763425231416761813685564965499969054152612737649754941060673895503565803375462698146742710802229494678398072831026352279132840464197429162490221278494445531321291721163335722211476283012461310100126636029047637503651924450864581823070009506209505898578680474690135108439350765652723729704931398297747466645448449303603228701371371335828059018965450425001864292144142259594305571574932454548240379416279644966016092389480605450177587742226943478586819686340622525035667640338916111565226981111906613474344090841097025783486045819516211992563465102927967876001681464827049347053257999371789117078139863261622795418624991026499548339966380198306639203849159484378470985796146724771344167201039777837694649988474115278943878861788401018569133990854340853058792707614648992776823577904927044693513046206829798265368729289426351662991199052385718728886171834947604647619514206482266423583572648934329067974070625795178865855146813912480610331955703084779461252884690027426770738198765938104552901530443447743812476959615924807225449174900749152309046015676594469644662308564002244094913877503500568224494115026657213349368871988740274207868876841218557611435805772168339045277961092142929841967566841911355789754979835988232061245566000178514689650385231362709439969902499941687000172991071042733544638605828929897908102147529112751789133060670516978511232377689066037787422114276259549528636716181860219899543840143057763604330739123578079763129320566469602534755126656565479809328834603981055627021680568391292473465734627445930373741221988909458446035229903362394935568968609542020221121050492540902340036384549992447039144076951158956707336567506039139306103958597595752886672966979856119087158300788785077428949743704287114149811620089539484710795521677653044972870009087724736325912481407021097382752240895933884143924255411555060319622418663158606695858223070751155439188038485079620733275872438166110649912941303907919260373405891342918774451123592464251504202064916483234251609676876082249776048390172175392093319813214593574013522422134802564402228616920692265682365229229745117031924294265980459340727585700648016050118092531539918657872526628393428453731759791294238312179232608839723263547050695366489499054675494107522512402606105720242172865494450073299069130121139367337892640352512020542533282780098684148599259960895832730277576407221694470736069105785791408183256302441931523459746796473160921237199605448634060490564782223139822568254291846462424495462760553951395842487330349832576651416794202938516679470043512057984122794115234471437621247929703802068814210253951431325615338731620260333502822333516323639396983643652854055757274499299230839877572558970031506887827856133097620829208033744508299043489896094886617542238910781216196786631174479828777303163360707919664081834190155511300768735009826204161762222206102209627433787590334978384065854283352007764945577768606579071200486989953270351803685879472413313147567866192210449877889590636596811465839835473027285573005141408105638462791531107271201602871040800113374521437236862925318893143103795519513423137772641284195789497352180852523109064788574132277170637733303013615375211653331215028117323470099650105014066481367844311923021775293553025461466317110730960300472598050243183557398486996946243732214772175891844837563060346435885102669571275058148027461148838696644440932608276902016989832800926105303207712350143404403618808152113935417499787554162921144922530164877987895702035151962742897463224973509891968703287931377075689050458674442272177968385332676554888403418098845697053673987390795653959110331406026983186332578707982777423225741078448857387841416307260707377921436791556918181696098842809527678268985989617763264327869150938788076348786957944363080633082610457267052507373268927707422343496319221035008811815370803023870932787731281062012889475468895184058783300359614101511104409197379251383639937306673835494768727831923064225830468957832036206041291355278796831634445314055488872959966831494479752851549187235022169173719489213703147656199587234074018734244555882877281465303030293641812591815500974941781171608362607207057278335880763922767988811792452883871746791241808301216990130364605060209543049212873286150111151875740481202633583294830348712975176101498829987843688991702384640000, - -15120656841631127976220208888862895691902203995676433240086539809341160780722818106035727904841619798203833422384458931532785492920931228242124830950081136145493344878351157992124271140829117859217590484066757705781942421994520295313309152703827719811600485231844056499320906575320174079143986169072034175759534664892749295793394877790409406151470114153959649679843566048266147112321936462011433143531472599450362951644153087916248085606870285115010305044465234146528697340161601579605958822060300344412998508198526469158651777738209166488182221513176988546264763107216335440993881960225220730856180594185158764726849780898792561730570261349726996402951678161227218212595611060026389426434342588884064118550086327619651631915291603893786931703597790927420630646590215162043605953623470179680442172719760387243328977309216890004332302036398747432326093904399648498811222247051988719273622045761274429032476718496667403762190227579578825670552171145694270850817203901454896234849774795973420416913636423506027179033639758958690391622545386518569517356958498745534772034577704963016039331843207419839056507858381864659809304227627238766390192520079596561388392301570641119183537141027070628102365781505887104111885022825409229281336874676555055559860367435709626618951597952486598508874687385035664649766749903863377055997423383369498835832250814274566056386494844213741424710407807179197955253299454941632607776761272439847619469386146554219139854423597695521389375907723306919413348175209222688751223694975296278127336972126891327125999247026125631651469505126305730106404171035093999771676534156239188024218202567324462903638545814218052954806134580132333217587288852402749365413533269481251779165294209772275315024958914837049397310778017947428085655443084211816328437043293525891184946170027276418125428638039337674403001852289894430489656398982137823138735387938524021532719430796143291874675906837657926501057128975414407480018716456471941831370537304012230197151414532119034777513222626549585458162549849553903484388086012441336761858932056991885045396783891241281256544268020356135029132102446890143803193003612428338349884548918374543358583898750138699116912920466113684246542554512434477081544967997751127084935732882948548108731965567234295621292215050089393396704881680285722777208432802399395038309027396339137706791301782995660567415131791747642760672457087007489716264447254729378806750837913071238137250402929448834711821264667295014153348822649309539720725071222595800084962010920629316023721758088419688608832884875554506410138427112154536459300107683791475734310228029009999607878632007104511292817230958558954028134650203089006695997522638571012447845727132660729004942968768005901852089397224445710246243363586016595755352641191110695659335295013962200032439448294452436059251470495753242213747260292341754277095600450579563057420895617570767567968583394638048105668059688123756395174665787289611200802859688509629813780289385938156123721896654247910339964912133217618084128332952028051765249313793020104001019185376200058151866613709929881795752945675707990076510613334692797442613526931226916039071196639736752852195859489901316561191535433177444313535604807474032706790031216616600536663385758688183629428973309601573566892280139125094239763822465040455487830171862597841238334144015921237921539791613414663554373182823077637274295670709230910832557785568932329960719038030968698480138626465056426313710796243029886345460151102745563867072486791910366474175447631906151120861688038329871703545252417501102740054117796475383588498589897498403101529388025267462838319018906365000664889281239126032565754571174314195690468437204276028693651295965851151682226240364720965649279224236543470770248131126844496052162234282362372806381857142473609734000559732106291277499414039156393461288176068320043946118638822517566013595717001113880517006417872488777855760682624022518811538809758718850050895588348041573902207565544704837999544024394622770631129357026916387962435136135911491134907556220414980812959354369177695760228773159580269845758832508478006693414238444259351708359851822244892247797453338470499332354558547531028420559544582961815602607439529334745124452985748714546514582419204426994040048100193915428455950344666260639960323316581152842961687442291060963421508011814094155565344827379318128888337093532352489314033512414705232143079598309324783354271983582748530915471580933583496982003325127543428384801041358916547738460810773307197799729818118695597612957048334727104290604489653289812077095287849497636450489826051744786308583311592470726787206240770019492738324197836896215300152148698624851218664177277111760237636383199825280568848998315555737882229876658157586935062676008555347913903924694885889898082070145281934901593425137263363741320466883994828031964921011739232700534656769658693507560488350482237452798080067210049921567192284965762005830017888343320573943899460867584330600033687390922465798362531350980486231265877069594777439991244402664994727852248619495048603502429951058878998726332662924454772577573104289366935457881829281702533599836364769489133193467018549472736425799279625507755985467225713447688730847032916722120906941068858155190885429703384091603915571599241052503835687286751385616176974793590108104427987556641248865856094700104112860409326423338924263606872752054419459953585124646927819304184260972069260617808548993207095901401961378650101924540715203667938944130439062653057004925527411907911132739539792993957979401239653873858314968645324797496841373519318087824192911803310713076562684388713366994651448109926380943627592295340847423809429756523518411575635747245748484607857177218786864180485610845068083644752152855335613513724709491467911944881075322558461662034456388907660949959714987365333534749625089412711445451826756305819574757677246995226876725252972389052697205197927320703880935020815297341318260622821702526340694060078531668908892260881675246765593637576573352155275941829804550636553150537230479544197500322511233112098571391034614719233495115983044013300624098137459107777899489755120739160206432109776602654788762554271045562804979149427644746406879687050579088885288324089821511680873895544326102203317391186506612705103116501515862077315048508973791478533104067463482719756762715878494537313760577294000486760430592409319435219830704424163755344658037859836666918495922206897038698549112549235634311820388693078500042686216483620859126889807519186172708884296847366821880574551663415262310647088668284397605694655289088868491642436022278511139362899636484572118949816795980675286302932585934330977676250668089159487353466219291918909206571595097582264563261216176590211035978128811052279281055621470188050243337681843758746295626223384590242559664500702037868956601877108260210004157416106299811407454389301455241456312962030320201239024178070042588977179346683346441576934585461590747834574458666386989983164447736799212380334356233460191785688822376414052052147446367954589822059744907733328120786411231459649356604409764393269037216514232978845131403492482240792264567878065392818585600000, - 612614379724445031438313974345135898444047170147351823498330890923248784859326051339805762472358663842078032920297224955957041121563304933903457736147342392299333874336650171614393775538672523139382623398459866639090119722509296327688693479329126125758855909394181659961858428079421088585077223175705261478424491863109896249063754676306623908498221931039055975108251834832906839617729028581784056646607729702433579671602855086439519620228477341828842191544603842442036851506088877497940716521297230250889999206957383049764658055957461954237804061771579554776501736638823161208179900350728837240554678097462024987740418827303915274528004654004353357795207924831428946132355113335689532835126435690581649888111590218875552380908378439715350465107889572623829939377250606940859370630694966909197329514969175072474845857060711210776077866611555488461737109886498895187358137597096085915750151203196916602998992652054855147696141811314774092541179096624832974687907429557170031528833658391249650837138537537072411644561884993094272335157053947687420283098351980405142675665376632264581035723143180968485773665614929597202119931917004836404293432115823022183271735548806523656343302810103697780315989470257486437282851241005785863259855898327447984881713532410027458442473353920822911760606504149663653307078831754393006192938390641373963536427393027305795420512206934816614184668763855459081067287238269901385662830398865475795960590664875820268465487751932439673757373263490367061437100256124818752969733163710370783745217106276093731081110927610888310362309936640145887075506466998174870865415312174301178098252900402620189087863394150260667625815678421859190002554675197405537750400148446066576593304124092791918499492334084212325702881042442563965677738250740291830773007584613381686397861495628796747900846096169664716432317025295752931247231604824509581288795049285042429853162429429158655715102924438120834112266587359429009938233529785336667471277076019940199360864073111400196231692266299416664094868365720000664419232935540308107238142904957358544899442984693405032883619420938257707279436678088020332974901170495817464684530686342617933368120144127731977808271247692491647708979579479859315240500338291676152265526149734891011187081134864938735542482967219848133201819679771379939259920793221620507536103230362726868911116104546964899067253649417270669547262059946836720410595099849308241768889031135657309643502650864074815248674413916584526812784049305015843642032033908725862541488031106978349165797355445978880686620579428585306134305661478653648766078187500442675624632590561190801974812873835573598090361169186997064662695811535934997932376009645453861360742479628201603531479526843716894970102810392265224288197673849876774994780164794556431128965270691861755991958532806192489786158987887259086575218755532361299540369101107927531555319178960058605736797924210514449758771824494071575902098110825553032176716181086080224759635847557871879353578095491146338051011418415768810754260277218666335374928512004643311560227271993507263766071630081707938394709323610913746476382033908263521789771495019369004863311463248408732748802309800946176829804213432201230650894458540378996740538573627072252479337433603575467379513676481721401841869306458262572083843894673331364669000784479677725743912641472673898904230653557147152374853372393708332458424327022375055118649012622141558544346364043775995873772283458555974133372169479556542076255894349451602534194362958645781089054786905668108539273335574242150414117009046274094944545779313754810253422793824448285518233075482404461417757260142657933543105931069586848022886026236378217075113766706802821134082804493590221259499162650960655444247124818631186197095806793454165137868170850130031596882933439338249671245978183212716701363118212011138270087815598348614570560782832831438548207932473157555268473741822194660961889116905889769141229647844328010414665739389198777018787891725658913584743094362955553652651837027443702954691187390052413132064835439560579225047410391233310881903110021728770907501749637889463502216448803276483753724370582143609713649752908017457080686671653022220139331795930044838996907717799916068357434712936207957814829940155103189955103593609404221964740241301135236134897657306374189927913256090004565093670376072579328560129353626258752667362023234910424822444238338516704243832887126947527175081263210387588813893360856498867021579179900998672046840558277545985822138028985815591636267323889808280888763423206857716213550781747180641767569066164854609894288123012165986805075069152667516613274143162011231662022191695949221542826460361206729347706789778167247667741878062774287079532056892352868481861583141853631415640759274223467447049782200393348251602370184451232889697867593352844458154224897632095870713371398388044418573693848882717949331584904593852897670351072675144264152853881560729618019245876753701772000165441204323294463055202664306519173020699271577987997665299542144330212501256343777893557062926341452635816029516639680600542075572406737442840699828206319523152947263645777448902353007170524807524650001172822680853322826557697011906532487634103211630642542670505977879440332428110222338471493356694311704612682980813160262957403520645880725375745115293345820443862958568962767481416304773192696540746999813672662018981923725240506741207792709190288117630477882128448603454001619565025129161068696968122354237582607471639268739358810336634727677197354192410821187715617585544819256784427247085380507246442683508839852011379573407734647949775462431114073175376387652184339910844906669592064552675004197531947252639958706251224997548701450756241117119775969257847571769382572336060178220162515238679617316413093747802779862758836010083682525079213397023313177545934014165094441234889309102679770035162184543780532827176456266690835559894823619666273826123621603497510296530899194814633988474594326220343857575092497838060793046878343274447222271754305463103761449961228243391370361710738575979144678521033912738997545822387292593492501158720726824527550659517206081152857988102841824226223888796567259561321538824098374122239232275854628182224873861158653925929775774847813585636883418530707869573218279003469884483702816508258148971755979534315675050507106443171898192976489620599460717193533928245696379348386476163902527262548427844778155787858794892894066877865094042042515107247182312016419263409132061427719081535091610864455480898157702233358184954462464842042858294255944999450931683521893807903209134925763111339996192964382024265320493070734839886494928709658022960185550164486501939947609935489562320905332197036953389014538122241922937834013136322903197928139620530935073002090009988097115280751624056723618418134003465690743010775626831846012885156716403054575321367258172251503708533701321004990656005377265675687314944674673396940735239830686620036115468917331746827062019102267079785041664893362293162635431548235280099641130772683060425695828418242013166060429720684757673868640696042646308941890849341080691746801251890980768972800000, - 12873471043114815976699581179614251299721813914453440358597209896425283346680076081626873034883001348314012789888765590138442020089679412315247505995712105762384361990455264711880496259198732080716940932626841689265679929094415593983438703346765804860762638590913052838516829633866854552466207365124068187650976080359380077607093747980208585697044846993146825094952490454043875615217849813237970323954849145446232186708374925760292233193208141253578013551141172461247897243594596067172596103340294184710477343145457122540324329976143962568096176307798292075552115108428694481313249254898116898342900973690726882289652005731621444936952923954391158514791982909516746732071939358481731185950606245910428373425053733599375511594545781246461329514328874862252522250498566291737555464651131816157204060279419265412344246320873680912202607873891209991731248217372487330912450598583295838412097766558297193795798743574191631039690368095355683094159962152801971536372387709677578605962180104170466701978070617373780313735638911176266992230071369516571194164367264697364992937279734051775327295669781134098292261595449318047300918550116398944767817591197173909632280756877481319985435063981778689013075092952727922327152916036975460280421075250538831018655776666138445494673727341746959201290829251808601869602757886251655249161106677466276403263969149626764299970963477022995985766811193404161316693314394643682152195191924752347741981250095134702600320233916376571920870700825128960378539748422926700045307215911974896580284906185095935689550994480497506886774047199397474792357279302969369627189633930161951360742752408459153684203671810473558796130655378268785648001184593759569290823443549797429379559952619854089643622785229908093149694966637373152730411435327172038321217168102697581151082400369028205255550408531771967034179453126657857640809131668482650636020513468343807505310578863502519808900081592890327567397907328527798898092091184894109214939369121847014601239369948833901223765610503726617449298822568568601098979984703448846240886053260163325474110125896392736792365549361024173264360605401158435030133261799929461786299517624986186666518421679651216216361042407006624970608048753882861648303572714623845999311346719072292745769590567465677659498969956973932485424316167167771475087400551329665752750725224576546836333107434619741526455845247540893478558589908622855769190447675051734455113116598935374856937659580922393718532000646138747950096689846710866940338056208909876392637161794771099810408601802490161684626632501498584375024604241134423309162925734971729451430532146977744860233364703691122975777521019783825664650244652943364020752875678020567499555862978299365271542498153637568165191275463411479845490853808971846427018227985863252204682724598091466260365438960509006149355755004226086786967983853268118928549313295446255335776492876961105935880631584372451520085849347778510612733285842647591800172667592513516004894512266570230931842908316421661575104145630116192602616515851611340669797662125670262075148403049691713266479363250113118007761894306949605171653829397743407989820682039857306641909042799918112531773647588207986162907858290868105389184388788453308122850680311784233769638816813966588170363801678811796862182578348355645203740417175534007733463089039840678199096107364601401719691997061257161858233340693713129635572066907481388438264851054598298427882776196648811463736403285579693877734165835198655588174183991614511272386044197291192009355358063919264736567537411110624393119913529150126456290086245072456622911355939136276343671578122730266339316036278066925982349944012045815262949620346748631662542448540155325861887471807044924539242902307664853951428808537947504376108708636772659788434837536233224226291598755432496611011065030077288633509452448622233375921819986157546828408285734139445998617818972020581388642647359487208201778191046766516566141656576702785906740402676540695136584786367991158109289739443593146654685091305509862760926337941510512003706036527549354292546434804085058263869856893300328897706593774110021857232259026502021805062467112163997213324821797872225033478173415902955353983076541081998069968673541639817213483804883904187921495160909220169924016107958975179866652204042079681945487773722059413366809096264021173706094414876185882926210418519811574576746128377872100610663446759224431153115161669505037768026273221823775386122940531321611265465449042613517691316820991925978517007885354920742051985908915425139707420306032058820805294974886140514795714983368782296177792603732296922389558879694330259239460014289319379544232473105085529902827870445293402124904009472593917275027680660663429911648122395405595834743234231056320369222250223071749986051219474932070034222084693699878139831698119258645149790736013330676927251224176243434668146578294628219441854836789583110113414081158129321948267932411653124687209924276469570390547208670386289070064371501274445214063917210533562469563531279495959498399166254231422768322286101303360387013345538092221431606930037051699277328328981012431520081949650697119255640625590024905860372399741978452606915673912476599469899805640525074521474519482779652106603246790871753195442470381268823411222586416633298757345039522345781842451494956375761512334390221041275430249224427630212791677806749617079822493839870428390419337479032674162268677564674366223975742645946280324090469757301908773609247696919908086963120076932222043337118116144376268167548850958941251810801474405293824342507993730752752929135545043282715508309417576341248543033071438206601201668164311405766321431155664812363970844959393190162185598723865188616542508746861819628294409794066949085179560792132298305542709704060570367727160335853006855582776574121499294945931682927211948560365714986989140798944994799282897702366057448520243769311431242470181345766809951339361969311899145946697245446169909156414532499919705399054706903664055193517086578272805993825427452910494744877139381283411675322355538286559064608991194305651709019331140235798716207720406360301946990263021168138553824883625339148367608965861461346362911687798254065375992919554235932979225904953506645842511428839323493327842182274540561980988322527491356216077746938839966618469973487911266573490600320228909376392650300812651885446901196098576720866125810978394389130344553294230309736919844103667834358384593223205210575781020825612407998873535961950824684145277509246566054141252415847343750005372759897086578673882841550806825367546799006615373799243865038509752572687118607050491344500589078436792764849919202062040112524698289961741305719291299587267194509457237750263234690461196876080596845355223097220865988136144731242508747623104026715818550059253399813875943111317722279323161460009734497618953228416942519413772691938616580911368360737246462027262646075978450327148728964106786308862988683042732700690657465092030274047915232954089973748449427554331331609188020965069201653946313488743580185670507874187784068708834037057814656940068052556162494598792599306240000, - 131591654060136570651067628390250869676743766999732425591396096865643099426966817525988783149896312099359638700125900267826905873808575905185199879620827978461921961314423339953647304151496900636144843355050851665049386027172498195604301375041234012428399430325254320792356251970204508384283265008038784850390867721325945213040760423915420146698778919759688794015270953126774449955183541209136719425124606957018034980142454378904394765349155099684722416571062453622381647446640262866929346016128468332085895142872701111282360854608033163212329022559572361399621509890649199259231705260786748449558860843245340990996140346979350056415652306412368658365696601460074687870568069830033850569242891395068553096178532527682151756611313964321045501691319063924061701826218801022449039963305764901088440228483699801200386199418396735140437793508189969078390809821067849659128325192601212702525839678693658925372683211677581806023712476046507360390030567298179597032795143338018398411137684488126962509095671638035438992323844101933346851226338338333953034851729036720438334636304694206219841662413667460180644064776913019690568836824607179661598054012568326070314939377279262364909395264316735923738765790004061271014131972492017869619589758865015057872594916772041038706932053427083311115288580259311495678419570699714842097816076124097077653278799790019339242871542380706004525085284106058197903577178932402372207463981407008787302889358265253101737819287999345102992000481132580161505476871187222340642572663705703361985568634403743358168075037902668889875467424530728664291666161593094193212804919530878560213080411058265627049802929855360343388334993045462776866281273569689378815480819321437361468583238756217352715394783935962980752542995612767011807039389391335839543325265144189315752008862338644377528779221456371445057525888229467342091123318923471408751626475924373059763650734004210145252846188620502646663989211714570044169462476564971800791170377661765162754046665868759319026321881624592167059683228480017250714235802322271645994176846127682023092976688026846022147450786832722712569454537448685550507932945392421035434102793030823635794488247993686830049631068287831243669335886028692729483576299286029679132378410844458220027350966093290976429652213369507376397834676767867972049623684471497798427630866979133791726585109488299183612386105166867680039119828269812548492141407488267447152955086755217386718896871734411914912621933945292716970998987004018582759886740698574831822520694623648383023776485397281780219068308782846857537546567442316282791813372995375493189995417649857022974603684167054793256783661789991592595322186253957532130961957294570328769946980592665542689142078087577835962066077644398565798438790095192518876952754834259964658158356351775031284324407972995302928366145579294837471412433883818089669785717297448700731283179173868309094223338852156692822954090268898937491413145150380700155659473423372187293917078019852777315292331265620291262754686252382654097337015435031474270638182517939646726064284324564747660443714146953748733167776212351538516522409372986413620879857799958893987091957359988586906734653066119552717593667511855086943934996188695709575713240467069135501956271985851590199111862800983670638414151248211543622008183441022111641666273056129954815328455147274969763107912194028168084917441059941592592321137442304700857866954027489163867550467860877988127552099584855221997315388796820917025139638098771915392922249504369083823645672963797871345534698178621909464986379722165567329413613714043532362970801377682461280807947383417849383592334593307560005706164288423367269647207311607059222766250180212652814953080496515107707120654170900039254351646634553424796905520957532779257301367001536348272019523252288646019503888054778879234164465487258564479197867839299083357127120266301537282586909018633997474956769567836535273513764804096203292503919007000273025513332973895056900377089300907750284383536657547025937929098471441767458505708319459353559093671660169423584341088347055856549853925853371154393120192883747172384938251141571521268072165322543166075740937670280822872800966460548366223746181640570277291462599664632570038782553372192928855390853890071150109596808788714447780490780753008080029203379813281362784441487763590341267100505773860814399817553546119146341749202289681815908288386047977071183102818203538763743562740935130611157297997112242853705208430998155853628000230872208579227649532658275640612409645783478567576326333735618735338932116689807544804858725401548696885003214361149149278769215438988845696636333106842419126629451719650569685893843116784756276232055355890223706405621210957051994122946935240436249344286420315352579976698033397046011607582502242279766110433486103296327530668528602483785204143372862806649473603752398125985053410944049850627091572421099680010625199926456688310960888915802876624292524710034761616797356760206007742950856333961911021361516234261499154855733098692775109181304240822078943764465187792848743295148126091033880697833282859047907277482232060718064168889873980270467614423606104409126382405890197122834274779775623192478663182708547657385175853444540634484483091505212739913479450298008676686219276782886925683634092521032705664599054191948025010894466785444266093479960020418830358277532235919364232167899987122307868172622469644242548530547748747527706678011461965668321948541165829416284765040041766758900053967882538042601807502770819029031791849938063061209083543924480555264133454656555640321217658822571099400671501644669739366999314963667359950011880838231729761043551550150179067583831007204152723638726518414600437269654513200236177331523412776355802604226600335782705576213650583335927640234858179124047038466014506310928201554393319914345677580931589185107446026482009083903202291577522659642781808560525641895718180498182286237195517098975466246183810356590141658526359873219954096795621338522961203466211655041100276385185699108054221273623828652195741954157227915177790708263889742380652634694901228241261944189648700406069958533750264286004084332162715422139569186675197484940088935738222982244400959242740569092739400306067643178539770195511789963632084542124087561020848730663006275314786134921272268245486946766458966224918841054548721294733893660503107052553305530774671617984297862646059018566598235722165796109214097278109771984695849996639762999697328785270350140270205632353008118713120998896000134252010283244530600140116593854826065334822932770613441992716026212488236614433967135827438187529190320058449195060565169111774858962283096291711227162885652030981707522414778132536665297418000329998084139772148079331242212488993615950280503393020072461644977842559047273345489630074688024060123245638710526865420592482197412299431715646734727200606569517533230310269021196028639235404393923359638162183633863594231026298684708156685486534154118307082502294731813297057629333988585190307221010978542508685692486975423996460134124972380924417485187809332428800000, - 432556501943696440485830093620812155653960685989424870569689115527999968024827253178095972113819515447764855307272729812145843891845572558551385016092524226117357975612470191593727263120626206755287715359636563505459499846260784537499039588083348191219387886988523491056063990471325377767690355925969463381597822145542660300485714728775434061185717731914067928681599653032073789039868511746147288030233103316483784545879007440716473917115501496795614468187511297802115497378770862439118767615291778330257763091854777246335978608177606980573556174870353238286626039368883630265246344723771151507407456167942959308644745475251116991150575405556210525707799366038730027531657878549978784852096736658057651900437797319143949045552991700533857302978131480614315470454684796664118907392841285509937660119558115651898092551150516215135934415865549523536693533991282981899201039683646536899419999016040112719762835225100515377641026381515242246808384097212436045470465281483974109440199520768991459826040968267592808418443207355564743881226730339421075706373288146864784261147555145582534801444334943165875561477016930296801481601567016750173845218144507111425616274026821171406533100849763972524446010687605035249868283791311608960203635679809597956504698781293494351949667023680104684192215554978576097552411583073273400265129723057421839140355749051488095782635127624876630099291330366520529823208037730692760027092105151142243616033937928521717620054862538440300191442088366637510844582286592043950759063586585168490617636603784005403537971420276267087108226536685971087620555739179468755561992549028814442911074505297492484125777716477557175452739649347330900030832739444994487361109782108202044231416891673651716746714339765773010060447917905721895839846051852636097045958341159765445594798970332978355351344654302718311071952921931050387680414167919012528732810130193028646635281494021038658815730636930266730117389323943333535624304778526813923227843053078256202905195677022020660551538901796490085714473336092944623677511191940329700557766880463100320540918465574829699550362057239641154574403246942998015474191923863990835103804495085347212432275928338947570376617468635363269795820469009600798400739186784217218558444074660079928154962980715187836121254983168728286530238168224302124869321888089969282492831900134307478142620833139773083329198820817327401311956261098436469935223539065095011744787285393128415260677034635664877557820868189888130853422549434070214793499034364086114433898679492616489270113921730203869956856971144776776136985018915488859920659104315235489681958832873699923245881283036816920968637214448457899292451674814506294083645152309514302553493527983850127085802654073241864582046523234400165398215089886454696325020016815752384173571430093228686042318533205102172123221865073997802015682208140512538447466495411474064757116850388445410977212918417698184621869889621076458256600209406955354527073594701985840258600466976409381459839911488790148078394741108005351598284115460690813832422116318876999357419866031924375005761543105014188465083940234929627373496447997902365925911757833372763693563911337579252608833267253041020470147666270234234180347721669717516577447205472799966147415451532744684075980946165175398459426191255014321560757830120190563302863749854754634492604678057064189983941215689344162388543513209484097401941160864622028004267698506261091596489959081079031895447234161188327005217487933034688420370645730791866262486328756884981731802172522396954660396582069158076144095297510787191485412974179131622831248774912875492785563182548075633072715857561785419123661355372453655598836572977505827637857547558716106344111793818819395720502974364341715175234614880452059327896896960502087668852595419158206151686272242556287615466340783592850276145890899454140384053562933647471998373234545320748928363432350912467989254097616261506791734298421851860791757171117719484434272088869513493761021977804524400878693302272852805431151171624396577893062421110394133487902087049706973845618419295771402461927216916877214997768679016025257264618590241517671768981706366447033945859617147420744841269784903759088265641184390799355145471871449209019066090958523387249963906284440756100392430808616893903832519583054544087905670562658149524013353796269047557158797423520282353877126700212358480112860645943307129212957273622206340835612829424675891937474305579664423892509954645887507021200353091579030048136649014510316858394412739504682510402585146847691781669385185745275306820323167656106738120393708474896195058657058792649453047542601263019527431185591790383638645575748964754978333290394525449320287216350274875631909221013440747172021400455885640323606201706680781055410761240655248005674192561539411958797626307426939698744985062041098195753586154049328615263866365329829184582075086460516038355840304995590184536076537842184695962171194383249074087011608212430744447920675579270003124876659342216099162303262511100331173066339500393314732045161327254304096395601083854255478006027632362724407446358267755612207317223202160953568228769596467419629287069885244175670265703392340591143096349181251441032745929820908424800851382794352123731653952550608269720506459244956131233357622963170999974253761324352253449452210704746338759144126908982786194797589066905234743507977061546825978773814602650349672093781558717368773364916958526898402800916180008908705730102933202437550598636678178719255499894651230158613737186546463894760236266177824132874439201569838595754799476587804129269207249680612216126848574244124422682110919602803653053662019300433664052568492593019728433364927438444951821608726462610372047957344839337785262000918963239871397004778103787074138022129838225100392391039603225052656314210079270236389291454496017014922173192801321109399198142068881504870749381196280640182554441483350908877509225807042865584035937411613202992242107007802466046485620330267561813657373826406746176948701325572566078801538626806715527140602153317810764064727911877624027799804698316153274397165994394771660112226117019705548774341628119198738237687887379188443865868703336378841832892093920343631766618650573737810268020596803200914285472234232588525183536046536798189944376271825552658393837368632851767976877078721392564433837027310436769180534939472886336326476769438009352782329163631406532283964074212396868028272822866388996379932387038956504256783354928136770630302551322454691781252423976400477009861364507139359249473816747509429824513659109939190017613729948124651594758171652727927096899948497400016875514109890961242516972675315124355048467410823004222465725429068385690740466492774788837087582164599833152391235861455026352790060540106972194577474268120551941728185459696520611804940328994380373688768557863610516702473668454029839624973153514167212604497039354172278628978531624258928242837163850175557710123191589586094857502738532102283944040550896486037094245475345489972674549075938542488516153942655605599591464960000, - -10379002264633030994817721919711208216003622425057419869131359398268136145902938999497199767739319211487609611491070368137079567564858544102733748124422579052777262148726549248446720430656541783848287409964138420505380586522219349078690898637891757036190119115181118415230737810883737456900339665364447935626017487405887361855477079864966439669912543306178353985433300956311256562670742396656222633510609860402445500284797988871849778253292527584418182196097470762259645435273325422987349940918149891225087096621614396101320387816165850586302681062880516992897677157033867563735033704265028935505855120781264256606119183579325417941911862102403498725174707111278997692304191655491426285675412555758557007271090338627943365679545161707856535124907835749563794857035431889419400127566858450186059498698219390556228963339137324380480510917353112072864748356898593403632645394907607772357052464879468971139903245360453017355292297698868934314080392216094083566205279676735013092844289168673284258060782952270389850359436171329406270465699526702504868603815407369100334366612695931673081926656220468444648469375917311839219362209273562623674222961412902134180572161443926666312903874841609512547889290146648037238296801697819752938820031928768650870083461751413843277323661964072580948775721612090686100437451742737968617093085935745805487047642435711247819034479825445433186885207019801211356733714639813173997191692460870289009639469393366409176854083594064942497686505815610291789146997111829116215638658659820607226935889656427115116974663084745122858852015746952508337213138410818400985587680379074303838956513213607541151914472196270721287224577728029206137462397125312122667507287050500584359930050857093917243084455857643731045299621850425413259149205039412970473196976402911742914889228659913766905974858297416040764493696776468009751038706560744419807905149253272414365448829597861779236959601216204998283993110500506548947609582573239449098854385646768345025780894549300047619324889576470016824549726793042380709460726989069559320762187697598508976127215126712163697393618950149547625616484765860927236784167142494084614959328913626274726325591382292888135286413441101454906509299636736740084905102903273141056106834883871641309757373606506240747052582624160938097061379426771468893814510584191859415596663036772642100255778386839748666418971398524507943182449710369851402349646567469536539345655257221878627772845812953960408890638226900420376678134093187978919381463052742906849931143588061240858483625064401837734010103049343348781032334743847873774230910872126540202577990517133811277961622078829243504169640612022500898138085903384474992947754238349318816714537659135783506294693636622884760314212163961132530958511479093369610194575588010128976839424650425628245831968979771108339656437887280999412208958161354608899282092041976785884923516521619374833525904437167071780374748272879733900900961313431942587556484720771995097403619498073449480929651522658312555486322535801571608418593507534054256552655545662402532116007257782460409380439141184214188660002898381978651084914701602120518015264392258284388455538323232862180991268339920286171451593402855753334608491730610888170342367277134688143043850757895258314049785034328825124766390758597407293358296741199842259707981523556897297922019180924742801054731466516760966131261134613457701334561071762190047557177419616826404270875438126052128135432473175168937154746463103441959995755601661776303114931630367633522165477848040389456439255175434186597125003394027852689336761758153016402608834204958177059572634104884453503218412690582908288902919636357450827338085216250367860848300681001695325324546198208188357441826140921047441535896608198826232319468910984926976586803471489195249342852850992856539649841242501666247649966516891471360487404391146170700060420233046261633194484534481579223668792066267575399661350443921661650838865657957095433357086824406117972146328411148012015348389697443859067825000008916889741773776438797513607765696773918431483297478210911291943941087206901744057646414989924866847915282695885428153002045951032553881622639375139056782854413959666071812152364625145293585237588242479654085277969607809645284706814023259570038933419814812593675317727710574195433708367945196117074321160336766675272715216443208173946027630488207492076458926291986686890315823374711491955780888412830197105803464497415023839568529580155456418353359198356488834247932419372796642810152807928228526672522618504595302179517925241425965463441607436388747903562071461125613029097532903660425304093110514120478415174667189881894067510077773244035319450421996074923033795694180923265149229148767588735584888027009057343808157721666357691137356569377026912190134774100788861931880647666238559725152695558895795421189460931470704671599329188010865062834937589246800361691245813826403442608698153512621453378579521128724703939634934782115729156003158449402251012135016882414379941077412311131571984511672171890606705719930603876309930519593948239236584900685914471791712156905051195983371242720556954049237087848349222289828444638027558229296856197079944831151434477236778410926375000593830693682798768456562200835166454980125034847312841865547080471664853740974203140309174517407450324636609615936962246594117000518416122829155703753934073355759453806945788650947810368098662116326119506447857820909799260102306409737498358692932231161659015632954353968166643628950822265309831619156615788774941923146432884669229407139655332572000358165979071303942752876714849167529771565747260186120345296901022989293763999031636219331432304763116608337509127389507211347351415044575158147236571239230046639960157997951736868754379328340568594635343143519908228793753806253853619601938462482352765487218328811271540282305535883321219426825007768984389422906581831509761275829064434154092966974748178180781537412698512558423801384076808352611267556036389122108711146421990236921466466681756479952735987382088072388423788647463048523979824701914278124179472778967890601213181357934968805683879488487850178471810065601671102355020696132082323116543952145031000077903818790937291355722536661737699888927943172530833760418718323733456819676776080210606381308730594187365309311324955544024398612778755667501818381805776797555735088127768182103141449756733031239915392864170550200335734734723012832921505837356687936226140281568343784300967743512981061296820446599516810648740668215233770988006626814277080157770684508077445125156835181667885210156824372549957609579920584194584761726058493292611493911141013997054819004737474549059095353768886297038612483568732678987362089579042070382379691076828782560909263638860878034149903092584096267074316677698102830429539319696595257973271569460824724432480908639254534575544230812813250838699030722493466061111685679545568897724729425159686535732429916474518744631597732514795568295445831154741247374382765935961746325327025504946059279280997369118720000, - -226553951319008380371439287280785246199802063361246701543311434308390980134622163510325546535022304832176776341430953701469576899692275892044689114387026122203448651183841127403143733062560893830482084261615024946147500731025884535063883662138507149805090949066941173341444220055613897780478814160041855119651179216735305015691306331607809057119839515891756816638916520231637628523765515797538734410202887537031807711933184405336154429857565485497321232412035089070386600040807152361302186317723279720609576421336557615306026219970948148331636739761387697542807987828209621645611418204237179961468849344529189728697993017002575022947070557847767909246834310555618795455389944065967551156346010334633605231693404461069593447049377717683964614653070911850979428693558004639203841162113758934930375799253059726591090568170970167658176370373707469702215975982380819159182570249449508811238475338567552459291111711088466211213511852759373093739741660174985146081835290398849812667412451565484461864970607935715831393557317595006546515160526275584263422235284239535609520575738852357497334667770508855320966288535248187516864800236160664464512440140802228128293155111652064336769256037401616611150608480621849528914957510604880294076275484410475033977790976964209013675605151110951272864531353192410662783593419109155756495225308444370997815822249379461833333637501502146116074834307859636957742613131841321297331771080434438964776791074702254754799809684015804429425268210576036822263206730697457411561457916463469480427348607604633469695731498030028703853970061485800149237397441271071708111436583306725724397509603267289833990004296626642859552007679864843107973919252142323038368706234469793022507067413968301275004256171519467450249963069707454101651483788273931622668903037532268282078834586680189471198133838727684070853982959724534423068812861912277676225603312778205091822981175977593346492391096308226856253140896082909173000815807471065222111540832405351328123261425754933011305477743449954465838613961295555087714521027057347206727129527712812703919075877605512233155670143088277735779752504933090933173380005467829659020303834163621913666863345518036005501559176128643822030630998684822446033874320658899833939641683268117855694529786467117253766102386720564988738534203109236522573202032751816472008461706275111941522661668290252037975045707114026568543551255087386739952925013038364178137061689071417111422012124816093866410124250120543747548816308655495496058325602811768229752823304512103713404005382427946918296080461817403596284975547791838017144624185122303375640581574018321918938981355901397060145324006282537653526606919880683224351443001552823093287963221764517636844596441006357080037007124079091756067780942330735666170115992061446178040719029050878836990769272504864978450879000345844150576698632416403254408665409386482276375007860498599690720948373687558320410627465117668177069195588974215135992064116768807518186629699741417066451217359808474129190894420121195690463066763823549471605307006579864187376536746371635464017591326356872953742824782241662499172882657560995944963512381710972362887824706817190026166581915266839842702329931571938430925610366642867074215787016919088406571508857127145617087007502591124706834426756573173831517451604443608676068137818379005773501732662311976852013210797493866260815790255077478302464311924579933013072750858587485964200373609636050033361784002076295010019289128054750521205623496482027660670651371957562187579261555722023891084662792590466316373707776788683511337852629688227011500398380280001054751564227953301496564490020423675202488890562711671075823760829912002646840799209956757964250005883772247983632519229585651667705366351287267640188489920363001091404908204333133967019150107647911882530072401369413233506716067264931208541672258066444319330795030764130941760658268566008197241842137170914332383588164335817394831701099123913214699027855339671691419476227248086595096865142838864914937272516530069649988103239274002805014271066621639617916834735393103211329855640131642095520282007477086951804580962082246437716433698036557222564096052712522641631457449360697672409251927763368974393277840426731331101566429017201802442658482096240443181396512278384331121456438577058279401833429938413505318799604235801482475259916889129867135806238043137171146583278301731801948319766922181367965530825153156878758761483608842077162661069988236499281875053306732594735595411511518439970606402595130785864432575725801613823398982741402293882504542218430099009834619553507602094061215223455124323025202626093629128990805390869624020554285995713947226074367127089643158944026169089779579619766809378718909922080745612275075423022646972848854904484235852371330967710677943568898893134480542220000633548934764917034955638654175203236789516380184728215728291937192715888818811064655511666345010282486096528234347831802156765137962929826933449067972154050393147431235611517828316117665936577949919546024198037424702233362886542918437846388241693256144681541881878220035940029559357543182103744068492900176930973738876965075196365772895944650986148526231541568881265822818267729660954964644398802255666025750719889865837456912732794952508602338128097487991875050863288063495289235391393795072843294732536512893928415863193621088827781770912762225024914883578224334953936577650521275175982307132300700107527378996934393590724324074435427987496452237114925736653801988722423810888149216249671414306736849169866479076882239952660618920067628465814580752064839121532084300480203633563428545426621339254076335935778136755739027089912580784713932767293720870283834980170968403811766502292085505025039490917803329440977086416462142205512493667854107433018044572937641701533024941816896962221992492247217091762281798494492268706142595074066560686599610362599890517117726447172106995294457560379700539871497741792800793364983689783388417741535627487501889196477868267049677935174843779847960803462570424834932225465510448398979105542863250871541483244972211262928724200052515863803781680392260809268106372455929152011409137766097738354558321933255480317125513360944544494409063899822460265544991510332162909221283219800341548866590005638950221151666751035159866957299253591796109252190780779932348236328017818507788516277740621646483678267556680920088264422979468887053006061547776918468667787842253780865383036087505594020439980130940858329595361403187832542143937151409231451696843292569588666663609350716383524694790886442802566006246933110857138538029385551008376288416045700168686445007596006246563789818847688422782133747470952962312944477308536812851231644066628611679945841554928392789598952267868782805649263182538474436763735314288190617436661088109024816277668638274502425091158894089181727365233744153185756954803702746691408800285111359080392611710570923752326450892405133568037607270994855354026754940276486105790987268846146730796139043901931520000, - -2402826528869195964654898794011277760722879553010936099372262094184558317322303111569148511828864168486562793348798221546171812956045301615976437959181305078282907181829860489328291207105508055290715417628118745220188312620260028975962955557810982072918902624138471892030186027353325589947511612432631635597923190888249023187445029704466896990205587977278701769830084015716302170517524391701132489866016036270798953784009396551470201551441121639309168088643652858789467443879701279225060565017943346304413150417003071455062998619948391617962173300242783570211333198062384594663758143945423766783978573067107198858014640422318804906005821469040231833062914207955385765449565702104147925989730755248147659427944999846233563964452431671463640928859717153906686996489705376732047983076284694665635584305016845394420857270965262249541365129753544969328070347503831893514972738827454056524137911877670426613853328018386686979917829301845848052823650468072476831865375434667405502094209667748613828782164363121688279958502204667576034642794980253831403042051310472303774334124863087024263401617195366951401536412931529654522316587604278212690623535784528895540830755860434646053998719400716355998624979435250889008017841931172702629359176000285338131401520254079258660529151999697405325685129173460741506883610883125841983330424362312805857373606035832127949662873226590384233918161089525486863728486091752027801938547330084151790517006987569684846036270235195785349702276156754417646855933751726938937064594828174709223319253260978528644431067428370992412088226085211113448513743919489613469966811184283044705971561139927312375704379920404132754172053036671201187108926506307466894672129785013445500079764379520902501968100269530559513756625543902620917664112132666755597933120447577515459421114102545290559757745486879480006705287882941859696772540845591659936352325723172282752424667724471366085537097264393621484629790950988819992604494892007786309123943798396578060596478087769343065921689620753853725762168236672745110136919117336186402091201124261216974909203675109798333367475291534817575696614412377579813708048757327760685191000422408807113503051971204303934506572387073810261195887248418411032187928437554596902421050829239682228539174026404942793183160688792812908688034151328427408902458642276855103714133001793003527459362422830466113689949466941167493913055927299805502843332720717559793711130326786575720417947095057343750138960892250253710612658203346428550622467299194438744778485283931558219608138186069623001744095507953782918626678967604586208893842456312177507524471990549520560306226060043321094639054911267596519334117264568755130397824952931245224814424332337181123141835196727650350730961730151135187518218888279486235122635223264990802995605405528463137406923400583583644604893247101113865648410740187714604338175886171973187847480404370221741331740187479620007774897241885211451600556875692951073193480642395147630214198102571993432569731263090865233842918691135941049387151505939166747450140002939557006986614790263608187530954878518891351692526273589398902308209422821593549233233401890496030576997197451804829403961977435390766300156007124470076773392463586228456022833723295217649315880686048534721912599553414719567634370898700964232870673073823088401316058300945851348310732050725001027718921370740674427222683669173899771150756342756760702657905024431330000745155591777542169895730388043109262898465219924261837370838719868283735318250760574242038840560482487015282552134509687057343921338921264914614660352560682799747392031745685478079851981027159275901431628732095452364618987503651127323183014849802310094578739500788834727996733874976176620966941288833800961636131807977705274188770326896840304345276470129479279500567630959223234733545772066083935652774839237829484557946235695323259603141812997683377964208207193848227852864068686229291891177543958828365930583535348565304791622379712454410824233994033976014407413560054129616801618659722961710303114501729088939661347272261122938540538233406116856142058298724931119042924435988534605999797986429143543346678542405249736527986189128071192514039285260742560477857561854093019516899767247918752083415530205731712200084560614724131154965968163569398529608832345474833148064196535187651168445068308652689577255512811767887750852509995473545133596457275402850335226591815100347618277694699452834122790256922618975923261018884549313217420621438896480905805280852483039106955048740034539524331339982177100590287082216024631648563591395923514949903237885266278759133338384536543070655505280238113494272439923475133973433686737594740379244770737573931516766950441268704392782465720894924269904631253895054199619697553997378680805937242797495298638720014817099051961163075858895078274299868815040003821269805653036856651794603977800046551390686073155960432784861727425311765974371534271798594765850766716207301374903011768721790440370409980032308037021302034665820766448099068095325073350686155162514379479084213579619449355281851014080044362968504357843542041466585787328547094325826750251503989137354346673222323250753033461780365579966520496682149647807153007735700752934816442622752373323679100862436385464054837211214455503336778489827770648319977778926890103804338605640690595870707589689229439905757960265521867018752095276672900615361037576700154841162349237007524647923759676276785678033344441029461824512532296054769473153904762637766392294119466358820605684626356207969076646017330965889394907468919997794050449275655212583112031133706550586784568152407103215778608988019538528075840973689729277548164621289769064113274765962530653680602435899041004331611251816613910652190623685299403908418838778362982755227015855638849344679064574636549336458100914236026268719981946324390036339500076028585482765183595086117238596504211489244687059125719107257608591850292476701327694435062707322731235155385162744619125012867112575474860471777190558690686285533626209523425503675490752336724127570808571317041957928276689741028231111125781533882910483321840197628167562147928277036068331584875488608022694820903352550474779595040159044695054933039458793976235573834850441530645760814759408966620797643400903875216266392102792998117705645747159246981241677429520122233017221953178916805305405941818467208370483629677783788378222963042475823113845610537560301060733495526713335999184574828901188669661744490428667152745083849058471923548279940425370745708158788727005745205916110545089053158586456435626536630334668408613666011177532472380472275976111509643480109588614678248792537326576198462861741288959953671155889236882390906418273687782667698726624696510283304398939539077665391700551197224566871715937855290512254078713928786123235476854955578359283479164095885292593783584206843288389342167241634255222792556038540870908557542423564430336656721967639273235979650820796211061222237698810821633638400000, - -11689057859597589827703466605552239830874756931755886619516799766300094185571531959372404256849384336820280340793180218914693617466429690440874643886239441850953396638443346586787659057504352546094588823135758379354196489700801277630296190501340951579426361330594736491242240576910419587925568953379392694464896037892910131612491389725729826458796544187718087102753859803564655410791421043902400743959906084715966455779335456870073724412944271208748326317202347799749970062388057865808201790685794608459912977790403411336574802387734445389395294462505074032343001722762184572371153252244022097985077422705167322502549991842513319949783094185051794520051335405891643402667496345632283509928192873650430891867635236797681508553099825157589542268644363927582486320549321625312482290425174994763916715781080806339095023140473735998165505396129961634019085352917158923817722908132911944917901342830101733499439554399827026909834778819935830831509728027850986960172369914728319262890243549186389388983501630706562004252662460531029047667901110839115179532269109186514445558978776922723776424463425290096870187423402111442719197988733683877281281430563154343702502594359934135172517694466434847678038271031762716770905681124003711450152585475953678682785590526421760422637934897879221628274352189168705980018343424436568760333864962109009429705358930583362440533105520520956911342402102790550205525809994027510823509760769218256954326232590499663799299467941378667481702920075612435521145746788433147344571625221205738633882464082176600910236449137815797704632454859110584738661318548353249755751741312820650049402134906224623057741902249235810938519119962619264595618373451735921062218544454897825466080876649894794570820426290715022702851593001825926740314547453314770544305709861063013474892705299847495732676463422977514723276496149873496455544740250612818221705231112236843950302820571361195121735652366328888002028625782305456516960345394799512970475730561841689495069421352312908259783471607645313752538484701227472092198648510517981948058156691415780992773980988737448802873536803327110630477729611103454213459794645789587324181106287131385145529887527207378008591868930953903607730940622748744195924312014826388683302169977238494521238415433881000413725388968665551082652436141885009638129638838750190811314805382490915557329134211081842167636982764305027101548711036796868717673063900228030169434256387941298075986404694314274405388786057391306453894081991862296094074030184521906406647624468471932761880588195157518392820582815537000852061090893053111312553796118392275376218679477696696011392168814499675750911446380069011802879130677056423779226752551176227623111623964468869394011783112563316499645940767916433679064172596547217291073288109176227950757484926879602549740631661127333698164663976267340937225323016146161082362194390025113016142694342082897237746868695053763724929322063023131810471981760218357045401896161062896497641399722340032667946225234965996255986709614342493252800271198494898049361096042409303341218456974805418099800657889803506988156756300147290043617995235145644718866622115848941968049962739084189337059780923429237758378510755016592799794016865518943668769748243520539337302816071677051142128201740707981564328498739511792326435263675446660560944262011725959710608160019687068613587295071936034011202467675825255875592762745441601658394422032238385416667938141511782966580156114497400340913686897940795839069080265673014523264255207094191464130303037552468092185327151582771462458786760010624009322265180141490977909809966449454260236513070730097641046312441723653321690526053983282704752607161805067209648058711327326260273358535572533790208280243424191637123871669250641383617762345340579374748501710984346730375324138402039280027330002326007328091543548009683452981665511781175932499396811289598299138897537333314773055574429141149762672543175143692890677460967933789924033103805217329034892938986482993851983503949802549114046944913739167066946072317641828673609053313666720090625428565224456082711216350425794103764173210179595834101395003739938763634756403825791160210420555484202942601048840526098161615143741003240270661858386315567927938774996864962816598134766908711987441079453358839103519603422813853715455718242730719623250852254100526375587136020489833495060536785536811645418694214909819525649218616309072563006343943768751775422871155007608274785340099043724146817770033125356457537128801017354012994764300409504221893250099799414409791293124950717174036295907947619304477121332854789212936892638533523316548678256565060069457544510437449898843275126278571929449992205824582880703200380582518404320027872128882257258877953167147869692384288813338650639633460993757230898836721197718493483327056055235264789001762681457127286366981721962727264102583656794358434574104848928748860612344483169879296061654235204834468061497601526765133622264909429555662480193547142738193062202167813451816023481728839624848318874917812064504145664342377930591845554362886576965400434387068965308512923977454518945807182704189855913514069056970655467775135489126541070517757655217581658219442434216014164542579507938176321433989748703131921223265125137237914196648942059571840450565287138181054076157764505160439153103509180758010021386367506803250638634768129946063851569440220529588082649790167534573243021356918214115928883614298399966096926733538248353065829589683974026848258145438628959028720547819921822125154043987984302245953067392875206437887902719585355015097448160286138699303893012035201968495640610660452858861598209677653861139812882088393209649299578734021365841700298290054699957439880698599618029472904776440841178181829449621386094486116374140705481510372518542024356362694689570241829384226926534599881926171602772776377474984809715250481408365160422345864079305744731573137622828799341641208245704552897751349958912457319330136714845246471309144977595794957214249560306804096593399015244923280987640109215738815969965621936395562602642940854091333255374979811098210609931193954924516245362952349441942801997374576946551008930257365847070012907247914326927063399533019525655825673279984514801200244346419416522075534789991097438111347200290160670071415647376591209326939926267963576992409750545971026233434558368497594944760615775420918403079017292012586318109129379868038279785456778117331685701139403574087272854973650133136618217315630935299399919022889243007484806214530704790528370947751768881580711889124545223439814305517573990792622158526493901107564283039587609053201665139657379934340844450670148711914846261451467885852069539348059808710934125239202149387732302116380948769898168658261818133030557329049251768944287179079752959880784219524338611899572103177264302255111098190416838142064337813541531177748480592499536551236939234555114845083559219108998606083558711503877976532388413440000, - 89154370714314926822137354468739930686614032457312639153002123984110549510219445538086768043689965194239460127607414659729658097891516642216726853330704868592714236912323590048321495325216291922592237601111597537628065449848101864547034363632476976574142430280625075280748533400587012143200276426034978374325108966812507666312177434223080708484631200833243963661593728494702941393888702463555902822948008173301691884859580209978636601116917216981495534460218717178465664941488050887685354312597900338999137595102261901961407282993060627096388274183675361637715958273017075809366476160393283908851992804430363803211257454342162905055168709957392542431485413278628330274803203254101358610056647911324560778088432403972096249878247960960539817012775334197335591102179433539062868556559083061906476075922047991154157648092048672313579128190308355447829113354971372962992940892575139191128393026066446584187221578219381135747688268762224487421706275362194341580440455139530916641086293235500602832283835853456952518557894087124742096726500762075373651388186282851270155843105654563386819330713327774200841782109275462540129026711494268863963776953814242883578725004920716309449293243286846628080220531521150115139205497764431491830607506089950816878979576018974083351140349707543902802152480607733668245454201490792643827047157811801521821324484618170238648849611672951945330198369046303556540978657079049501089448971715758309617353864699193128522951904930263437031850042757190449265953409827794461010511806327639981352998992982686187430652492566257433357808987083858127688555689435750255739575588789971861438887811282183071568713405027526418622829567999145772379378581489055141912292313599859111819219321209070913414997323598409872338545317442818428543730665971052178879623830556648414399308958586202047343606042751291085449344712371307463076254543891751027533799221040725945394147462482086400508129872439997141708458621462547722887731020128719970815581626472886921489601387795451327665642101103392763509369290659739965272883918999003584618717580658627748012654426630821578648409064197988515157598031314872513123663853876996088042077249632256240242200668924313393950392666145283704576842447364037373150561786566007856173700800798285648108957592309327812690644848996109786209242253511277846741361558306950349594349994486033738768175973841115413581137552754253364142480988766298053409737440616612412503445230355549307399352204639447966822831798219902701946431034489749994218911970509499155701121529584301783661938782945625481740275434864726999154092415935135812421858310228400648438026151627265734596300158979711679104839348360814213497833873395010683616418159345295073521930629778043932985110817367252109221269905020885894772054294155484159561642639817286224145056973822767917223694497158856081042713307159217334799369661045160196709210144900615243725903741605862776524275708298584006824673782974091752883914123795276559356195443020273302851665796554707882091064931517607404221811646990852019122772882315466990589757423903421582007632982005186885146399233949342122816056823532985721188766372753073849975512557563142074120694058501533074728060317192898536597733572257382923676891177987540764223633555883353694620682847467297179596134214008684548157093703456427818810767014371717936965160450688928246979852676893236879089177653893822405175846619477745021588267255767647320551701461693805537480092156037305230003539164905371417794133936026354169093984022887840983419256748276214705293024476531328629352082448873639150133969144490002146906336442119710542731095330451382031190724395643701757181684038439867358883221394191780270328188437163018998072797834302798207910738024288162888729188737830338919327785076959244395820250986236418947199908365637859504291011764602075211670250099525070892856145308498310690996965673223578266925984263139632803320058693041555257059710752015671953363530214714211633113012653456636358155797732341577079197163883943140832971008161840335785934608087586084974226732460350207638555266950935144281882383607232498633635005601372349768991788979572347817539862243746279487852304114689786221741524726807116468280960681714301089019213506936705205082745887704969869345785188684712029959061851202718467207486936504415987620982575267126318015039725485549181602101084326586134880523884926205196697082650543875172185510704623289934332305569076501988373492276727583435354372523180710566466687893422594429707748129342114877781647188189867198812971824669505487727952642869477100442257021804537230990322339571758276587388715172203511042908574092388766759613256068022365696976403413244652716957825320215727820680006091075791997870059493892594928213037293861287479214515060025214329752738368883335953447697726895113454388964497241284609925691836663559537221417938670391090984005574163210017001894088193590977822872826836658391868361916508255230979045904927888954094899113500108384110653312283123848824528887662851757384535812652737396758297562842793452130848999720165816065584865466074111497605037628782616718555577066805247077241470023586241762089732782909398750477377048009717270585158083214392032617569024349002386494975275828477833746838015080140585726405864771810513183713768101071828813074307799443920567496765253410520866449100832617925939253441990088989536352555903416241135481975359083278368916973897732276478261438250858006617129424358401023976812673827826988641683471489113461821214674435470006015098989715587178415571269475052599847222424039308088750657149633546959146719960408225210802247481005763411738188455516409663226848348702771382284193938531769981683775642144014350384925594593403299190433416125978232570403716239598948021945276417452312762339278168393674395317331570328000780112356724733980004576409863226389209349768779863649003003168520680046886854964393669947292874670447935688931326023314391551331737808382145222521566351688038799520798316741119103282856255720214240824333735526570701504251200689740555580744653541393364520671566807420907673189940343850820795145899374781431794820867639414788417476905350632978718392148372655427320531970147559024048100874544085708854616059233102090229670768971348256889757668337083466202791322623817211661400277709519364775300740618834523512754917640931341982282439941053506225707455323773867632964265369892967935902096939947095261876950497820619509026683031651225599509299723177194560330142965679575472772575657846505386957590724266638374829853254099481237745823549222956261311311240060490177396298552638831192143200369443073638252133360319248597767224986524841951724846700997776505498461914965006323259687202840450917796504860928236073277160394446730287198185433071885842537191859096522541432723682439038517507738809734196115332487009231083363314352608701923747367094332539111749297664266763828759492035721574031750004642502134015850382695151462222261125120000, - 2689408936720301697526825229751703243059644254307309601556668223029545570701163860870010420432937158706108779868535040863694351899575108018043919627277731568131527734662144537000918571769102517738192728540839932494540091880397111671945988820039211183729168159036332150929834954230687303066966695359685206115313226361770846373581431336444978481208691557238453448151978252130662169772841101621864049248520520722599928006025176977291797851905065661006593741666806254905905770437311624309616447180800735998113231241991693637905908720578761765664730723584197955042179475450355220888170635684347934370510005409570997635400008464867207907168342236658522878094727942418236089071837606735191785628555791157704898754745006783391655831340822646296198813774059974526330748734772635214376672887626935775217964076065322739357323462697320090567868822599344066047201875610462195129352790429260994466921279264222949818696155421305479157083656484896305412000502703610596528814853636165024898486992791343443466811789744685280214603013541796309909174852854839117373718144687076767382078614793820850236916755905292483247714270097644157639429177323551690075891993374856810871490756284186368482213975207770652616074857732860901982782660653498187194262543000473000434425857802219361336344287872791379225619681616233909708900678440749503624999928528262645363822408579450774225834270494616677270009960620636370843933095451702518130539102109838301761582292371037045710875857233462657022820366272412753740014413091167074447981739695226590719705847658762694766823538899923133009815938912892858288115741960522334825172851777525785342877534589525944679854129958695822100860325316279390072107706619299619874461968962575618724855956701566145448002944318367900092131774128191412011286014407927652580510694498646471707205217550797284006441118538995345305544728178852075755339905743439434778517488376293346389162132290786473024742139948259200830833370769080585200477341477945697864011549592182156370548013755507640168509592241057188848219338141964206818424325867602758061846287892469534354272945533662033667663165923407766609509949993918981953364534897010406417747094295503962387535682524180747283276410366474071734039273055953274269115974723534840096476510148955324601671515591248761401874114086497888141078951883523285409649505133919228739373938403992984182730586915022438135332420396721000311918147625312832837657510140532675370826211459252153046749688755346003604977581807981269111137698792315043609500805637300964898914736546073515348627080420059982862537357275155691523565094714120933436868674933478486641485052636523551236428423497748141210033639977603806439947400522993825933609713198351756181998164333733731071941795689701925235718605007489598590833446401822747107420896286722360558785376203111874728154038856184511922622208009077843372337919411312944994890882776523652137999888398325316339874774648574497820312139175361956816752077619839631288716233636682565577905766211260079010716931654763572781205527174371048421972690139276061742875925848949212116296091306094620401517051625672392211765793321931440815205232349964044941339714531295349395933684598359462933687963591019630395533721086926609739437416354649947841997129368392056690215745997116511661981369957669596056059874059057249100764003715629975957223704268541781482384211333077300928402218102756867336826767713482602847523747316654649580092032988960998976298985853441093758590796080010699595581299229534478677152822126092222894660079699458691509911131738671284619176104286261354245985146405135808854970249050126550800317957269225632462744863065710742397300104173760805771608529512626373758494774273139548023647375893560622772405905201375647050157428344467677694919646362611047223736723606945460593786269939071082838357333281169445474137211562441190906234821890476781352439951684223974543314831107357647481952558717467667731714612603977733613981592351092415371619893646014848522150553778277860233898100097531321017609650095986255846656344325092495616598847161950132022393868653381823430261481475325392713761434385664247584710330116154501137311146422499454425485463440370549072390314884503964826478734734578826433689296853432367442562979783138255265559779759938571289865479802870332511655177508613783273571534251003046222290169629316828938924893793709415697016792841237340452082613639981554754222721451051749982010315208826178214754650038088674161597558746770277612569340379880525235667550403144819153146158443867253362074424519558452641491275083088801091899020207786988185437978993811154216620297262969543519440124405676341616435354208140895401204966875029252396672520751564373442074917202482476729860484955157073335409875790002941714135149852546670022969328721362883998827851286500879702108555471781163998756566263810133541548433363556533795446952186192830412496406397795233894042396752960167344994877336737672723492793695431925881786972340431428894040494160018478730988408009094449599315705231678245881409128360273108560708442293213222434192128036891204985102874422904601561615336940954110721220965588678939118801990450991754288513980590738288012625632133583766532189734087233912301393116256282329308878685848783295649680817642248245495959296521289102797836348526195825480493803993572244204939120563716983509061821819399408919644637711497637630590911234737355066446632127477908351748262872209615139524320228072173921771584147118169264466707633872309497055702133205890347311753923212400795359080917256672798091944961161134651811362839071449809527594765634147802723619769871421853788284640899134771698404821866401117424296450414934687972612919025381014256559469150570431883005315258368133911778746476713953633762225315120133189970880809628977147909335375029182333305681079090177933634701900855234010960850803296880824989552720552951204006633462297431392867449170125461073933471622289100330047812884718129066527947930558618430133865090814468068952284898208532518424483399122475203073276205427463978450676343926271039670595061636394374498187338368727605420648060103350401065570517379343696461024743614156160109671931651657206274945781470492712557907204520987478265675945280149493359515790605526561910691738943407743720531399905094910742747291768860785910319683674352362604967705147476395167947425624874376929176634322975030950557495373441990547563376943049599399137402503862140805947497299865485950627036268639386805312039576433513521506578633286500297128272884645530372490929187791482615845049791827814193497926671125613321728729563072739509883596598835338766897870963543423874307315443881143679439343752217591233772533674988980111366631521980610623673849275786482362455736425382657405282812500051180221675676099533903261013924917073519145174490056527726003194709723761410937515130993201102955739448594023176976346574304848804409206964870878910912471631040348160000, - 32412354463903689000264170047230532859598333424216003925046197117245212925671870678816731395148382480746622724829665746570861169062741132734898291179102279978904145104084131177855255204742879123319300594347759700446653385009432354866330828567922247753109556099123254775551562052782633781246503812205914044752067743779742598033940846797227589842220110684843513230343940487454088958813566674542414255528062537627097728534409754426348330701222600986677801570573896157293651884061778018892573915590784047342455345864141124917333437784322305221993686259574442266448982157154095185052263442851661637082180554984474842223687428971820447285853377473151535369398892945040804098641849273957302997972163968597710318915616862644448201847435111006496492065848582519598841912914362080732420266360430579067715179639727183152172171824866864346346097102117653194277729076790549696978039136342881557015848942090300393038353942933164589892254517687586896508907815062462350963530609556543609109053909232588695478981673172491496849225628022998627578445271207944891511480877952843923087166748070284119497144997432868722595947781428922933137417880678131857175485586222654380801013551017183287815644556004389093798798083599547352035969888471434279244570546577064935168770825083088394061224220363595239788796907276559656763487510721844960029979436824924819654162529803398871747699199536913423172134054292787951862452157354800705732664741741655364438652105219105326069576487864001932901946951850342548365292307295332194258402875697789852812585103259671289718984697121435372214994422192350932299662537833597100077117716232457062156793541858271496377869629864310901368425263257736244522536814232607713196077074156558134875228588200365881915958330036948702188086061674529187940913289567254567442883588471194194678175980935271517391868085938424631123707920692257271603812887394102649642582771220418868147641588295491900320387500975047731614459586133401460152863450324361287491564559800068115849173474978135948157539530855556907199397569875727792197619486890470447204344870284711655971313147169456660943497130478057482308359774270619521093397040506808548579745747512207352083766661068103871481078203048040018632117106931944296669907366478594762114729397597319442547753076985392223530325575990647319752965457158909244119719298266963246215930353518196406548515366014558354306192243868023829185248604156055116866436390701946828694520650744293217493452894997319418545357566441792282529778051444192762182718190288083588220079776330087101145524766769209894381050931651088369129185532119981624779699247340020526304162050207263410504806166133975845783692520944817024609719471117647652067585362938691088361329504148952086326410701836892900585969714458589176960197951509608911740480539024305334979054926139285807623622594737315520271272430588462845425002786182579311498751108442893413941885731173508632679581918984850683914312132733393390962584883445822052454785756911789078875604595094541477336183920909191195084221798971218811141798459257300709432538838594955441449834189458713635779527819557552676299751138721099046965204419149422458348992164922952608113965149460452543722280273745651171224988383980399572989689474072308521144128853780339430372234539581123578067325589492363688866458228612505369550076625517260625824483082033392511909260684683496298692997256988964240717096116737193688683723706197808391076910424410355281878343558718548089297358049892926748583893472500812869278046035347098096411065796945431298308852739940549125180727842613156819408587395127679238463484966620306440718761800710232908256255240793071233517654303293457208400591953732962366371851242843436829045563192439906465225278557069253831770626669172469670139480294108078245262525625025207875911322089041384941282965280015678548024870466173650906924314227195720886605899588861819726276780323292295042394967531340189204982285426092288256076149179973785839842525090336511601544344790110828654256714093888579402377239461380908338066111329433226544275292048220657906796315371439116430100249325663224400038896760405480573292340227569935426367820908972461165301037330566574996849249845080560535680404871142068038039165889807781533668352688888007392487811284671028362691805391713258294918939572395824901280382456210684536381362670044380437436828018062145733470950600851774381190051844371969789614724160508747730903505484300253353940503542379357659493956216954853446698589236810573580125512719838170460732614868506588448889570909922047351148664407875212260284143004270534621788328950789268574726346724579294880299895682566085771334252677715785147345669622209347540428432079558553564923526487561999813274670262474966480917882726615935381214878569091342451478134864849359839694798224690984570569977896753923973968471502485727068916125856204451086742659815266948383965378548073136038809958732154502139090105856873412127932697951221796253753849699870946443098452509892341524514209015397866958232945503542980311509299683871228634079620669227717569858971182458849790956589657234569329945138109599958727201249558363442834671323883788585014900850154606462915022487847360560086838181766166126413733053734700102194257894751074422146984825686614183135968858307370631964681203295794016710004626560072224612437132162192730708115897801476652324694075105713140082676007822924351674540331290391675663357694051568851249360069653456138482003966106215987915140315282298941463675231795365559761881431694098428156689897220873867651749867781260431290616508665578198125002216445475655015108606135691184749788535558401635341871136249840937657687926285319767904461706067055205418094680808931281574539695340631628060583896786203935211356081181174440342983777774259863040702131671005042063182723291192008297606883983606402229461200550614675237931716222172056142626194784905141728511636136674565218605780415128037333627551692941370142956682657452591359468476935540963284105721085861640452137980399352274378974755901552723321510603191828641185777701730617726518446201151295209867777748340194891230333270921111830752175439572910373655699830438509368505963927041276599045779955082951389058237660614863897619258719631646248966465075858326754219811473770639791753210870934209917043966481285358552948380435453601448707398209239923053631494936198716621949221575228738128179753683303977061121678310344288398291127853782573605786418862685640705907534057294370186123080496337562212667700800535005402154797563675253058089133973089225757718108767095506528577754988312847648517262184650581512043250764919328766751574455718048727881217469008489016015683859770903655481927628434297461504132382532729618490172928059289127827335205387665406947745975933181745403702899200910095917678455766977066258628375229203826936050458348761602829087412342004308114787766711666828609777167237120000, - 225329441312584078644313337787262562811755416046732178675626972062471432600636979771901814568346587677330594771268197456757723258371354578806565547290851830028153410638069681689120244152314353169002082207565716595679140266192993928031194238610295241738551000599314219121462709432590823419668120659186988125647956638001675162612628387747617632394977973026979652590542209943587859715387643873392501248925151642305477556611991297668889290620494879991861070495796895166545488655937591261840699211649382120365632498521632115586117753553988452822824337544435986134861178357231305514580652376362845498554528509216239997886347246730852867171296533228438280391793152358062944977623589046844471213622330560688774040873968364845588044311467167890515290459215884483331143650378737454135563902539540949293719935091412481124882634120767665099383661101984480291412128810111583870737821001073035350203334597237107753289265643668519361419199874045681402110235894470329992679600936602581678272930104378351240433035378326000941194275268170710747187558591014731006033986682992957853113449837162313189783745089042828746421568712753062064873201447079986191942128129920220472196809182591525991619612671255937568374162558767610560640935815019893269116191874741624903973826218928883639823403723463814854792716522771368949792500947490654968869421651673948224275013614773230707379414356402225999798101117344276611975696921692719123957228974833769391769856910145609009460273964765528471986035415456959134475742546810079695018920325352981690860128233486606206012610142615510789992439182878545439906732413831411796091050915744853094563611490941217503296195121010462771404073421344654008028054528259584718117343423877092857462296887674498307871728320219782004736367205104243699978544166408423861690547070590830689850048246164856422231176423926422423218700331393605815321886951745441060421919043381952740163475129732637824967703132704079697632466503785326161633443005881274151190600049955691732257906815407515882472189493177715830469146879359643289354381316334013576208157041927957322674248454324052480923052860186887503103577208403667487728377350161880963488983388700462574646689905218772435548383266427728367157074824209747871070043510342992249691267595198390846670192914434940377567422807644557621780502737186966606572481706267680292026358952646849402407690415422916112910668707864373732674157596947309952376325069596051780932896547013053263953578995990970176169260673817053272733077615969913674561135321705672172854207187156323374225378865414926430876374679467850916418648956547306136320599939727112345221231183539018776290239843865133721467838287366477576688512830892213178021081494664372365854803038531566527669302504811258298164335502037268529717009828939157675831732000657062181639753642664793528354103356569276684743572546412927608596569855766881858474750071785779249256908758773456768748880425492969537743843706102202990798085516755927329578763525438553241507352518790936260834721231685330993738622863413720724299727372695312562375485007955910919012101044421667026148320980496679310339369207163659020110442561546866347390392935717242665869419710332647892261113643442639312300926998312213706529411866934425502283231005353409853548670761581261776392016289114735964312925446599866715867124548690016664442568929226419667333719888810510456527794628501591121894624600295653743747525485720637887251799391318576222000268529186184236889353413442923762797796153679876661080385393823417504217670633893393390146529849797265762068027399470143386030689857024564648325105877416376489251440799149115853635803161649936725730897338955299644779121818797867630104838516883529539853538587017481212851606432712619355319591421870997029504432398450267783545936012560753920840907448371811138847942567090168641037920602622605332269722270379500214612155957611202405839868016800817058688600186730723061538253257838367229902579327355498220728484334918312540029908730102998811971179885254714667635550733604658973991687955909105888023102849900724250609733614843281750524615607023175844849825794848042798350773874054076261158163242312543441449419759893137537904482703319542162649175272597175610964232749492856548845305493942490347285085804406712224415752981582162075756820105404867181154328434781361834985482575366387636689223107420806932182509746888759249778557719166663460804247933316862991932535737752525972613161228067399879174905630549881555941667855898011452130666218925456631097834518477912586913830629958714094355395660535244021838366227631179083893230933161370567822475416501851024849225352742237655561133371217887758071569270326847221983983441585320500349019531301136931104779741051741329832821994682304613636858840209358545770013790966881337519563936334952952525118586326195143630708184517309232130664675299597666964308556338968818834564079847039547766598391374282413598461941170003917019363354933588632920331334437658131308081164380476190015876585868830694299145350550251295000517220543190584207483176357743336522817070644505915864248036915249454375487115185500876535417807517180265036162107470486831373596854672930076926754021106943788193858477841190621870776501623752886446072349379517555976884409891571180465236566735792849522729008097707078237587016135387254808652094223812728584955657249633931306918098801383650191282944546412638830720058861153032221658509096709336022757202565378584010794791158164070815779148076452679800543864662011493874093868295141665789700523527881463844980166576107131949447843870580793483205493716494943000311119389072206273598696734890826128570434681149736171888885449842923642297191583798048321806791536847233159968913543643837292222316209554585936385163386566955700858559465666074929464192862848402850010697301997818086071392991909193528257323145887246812000069982292895984381442682373254452717965627803702704570636661489734705049206195564911959535055376550865754897200749726945665435487156660175328618927051102630372136001683347843746858622853200122140180638452576042510700739656162753847253008984856119162303439878326014238695588695707817272946944636088113453840608044163010687955936158339856390725152723697907934537272910120919839522934969954119642673957784672977030294683494601943195277630514248110132361570471185196784543821358099596838871249497837720540821079379973809414925584888008413386695861338782781816862238566348612261931890416637067353605217579743221423135974781648642288709958327944902758452236604200532790312048384670377540037220166752634540649290034180588286204799758735373263610398542901997275987640450558881413363705762422453170890908605033860487921273464738264239727810421650508471106747982766256809853111441960250062665627361042737887778469105876710314096052332171014117080434944206347824499181895330785951287264453591040000, - 262390648824030201643744571040247024741776597022391484287123447980136293370098835971326137796993949497471828750269252233850913076008570884536278172473480763580355348359943346046127370179152243726232943870621978652849711880461673821730367743057066019551412454224793771637158696690931115097515812120952517877152703407569272432209505209198035795593168658869151402116735252905564789829018733894345119006731433195648954208150155517698381990199934532931850411802717908893756683328535415367644451238865898239516236204657267087143343788821950002590267777954117321538912426059607304763482825894766602453199141112454622429275339277145085254148111405864802103976651640332831248417188013287158260992709256031332434319993435011227298861944512715466446544886887249868418345380342020825554364197960557259712840553000601462439070916795165309567651334157569702683704990702277523546782569191709803821492399861091991300465099124002826355998358193755858985179454197739824610851622995475959341841642143892003389479911516832806617330933281644908724254737270333998151714914222233233592043980179555901305129766842867982323256792921967125315215614283184332267330107286073829679285955953072483620571236204430825307164765843778797486701307352129260143757984758941551472624127929381249193476088042925239805665317552049103170530674898586472235229276416139504839728716029152806132964493001877537037306291311795851477752104787808217269650695278323620620160697749178107723437845636592239138597685756574821723875198898161029507728325223999274349618091306552241081531234143248999478901762663738498203129918532513432155521653097943168878117359319155481279767979842344929165801617893507570408739235426555311622360788784258244139277928699337011077584261291802838823836445613884607135901422748015045871400961841233912302978955037458875995169159166077588929703258388531959055664509189472760421327381541226267796283535771868915183984289090737184352052010153553498955710226921255188198505447417144114023773485918723998208486334533489821773592164077405474104862396852682684129798111337045417368452756308205943310132040206859811822733220995839969030224562352087109501813471134680255475489710155978106212649937652735937832849001970301558461648071472896607020999701702224436912654660700762559565385067270097236056695497141125077559669885650279990952349147803979262206346216856091707877069959062236904707018566484840779296670490023885272042115167537103760877514516133609146787895300775781145546619308628989840684157845565223983491624723222651153812830263582716457963444019244304061384260362326474220287877338459558770179587634447865930347601647371369363486200473076276064596177145860471110483172347142581849167793545908747411528609526385777007473763889635626194871370491664966534524819136918286902662870483016803419642142667230126134714144188122218235981781417235260892397633829613616953698950601535396877635077720385791239449084018742351411023699696115430913974498657913405704572832688811523382734593429538052061050852425492810091136122337557920638106798187327620344507451952971221029325713013649435749200272162707897229228427914483914867697215147472839328883857415779758908278030135574373382508967935319171098061322918373973621252459035049327338642748881833408127932957033365098358212767326693359760174676716977996896736381442603662061951348810708016270398755653336936360065608508799614134536519310125024216296862409303690877550772572815956270304910524254763358442075429519030956028023223224516138561585382815931784923754080393682784739954006768214076726205344025385939337414809727583835082624034789046107022571178002019561814186999518796185230515975500643615325922662702739241332094384654619033328260754258187291699497800521653592579370918339457859034753522329876302736272505753834465070306720513828680853060258869208416312188528304137086462932236946429465230400656382172403303053134141136951841566781938473830128290271916843019710419480759307910042494158480960468072221916455587031371003249319720028634175427329873563367593688527863922036850522121427601975338110934403561372749080219481862106958090390133614501246083334070353767968078476555151992431252787713383716089458734069544262495168508979354139157181149027117520155558471598508053341693493987179059684885909408385287234444674681776124501638783709361790961574095194949642394859620411730014079677552647227019631613452469925031070503679801232936334694644102751575557240890855981643789314585142206113496372082245438836217477875555455399279595725217209269791046472410300382688834400582190939481058872771884425193200961654289031662528957038195953986218055607753326071407483056086730505193389500692666403336329980245511407713722140926608055134587156601637905560843519431061016275720074688517594978062584494013826407218329618828582523838674244446765721386463495363628974775945629565042561661070845195513817672599263572963029410538415633818177582809668005565302743980028603133200106324763934475657247784763910698245982382385468208159936167328283818684369662558404204262403811667065235538911082349090478798585561989563759493658329795238637667398968043857063301247691863557959581108991028628789034333496550041391580357637158478954545349137027793169355262643589453369303561956856621504023048938976634519348821437724549008322898820679438422695873968267989002623601920441183879752045272105676384694964068072551085959537266281348314662372407732034070932486259366031427100360828021141865302375825017080993681303251974276300168464535979174763541794564080004758430452470830844913037062378578632810851257721163330033556587791652305192213290824530473873756624077553373752472029677327734278638100741881464932011716213728753894694944881898906630809120944259132930203997396415808088735913311952909556941267288785532869698516561760785297098885005731885372806266683038690222362042491014394454131928698644771348292005338590821175706119591124506920138349219210548050594094266241784587467842158698581998056524739099000661409577825638065262997580372924786350769294257907221924427713718886968420106731588010085148006174166960529581489748400416621254868067322636418661071421200356230102750612383469409510008489688179428205551104097703043382301686435247645020631237760166138192808638631281496402910638951952890724469531426908094248389273771498613774889414030131178500128662429182786207817855087178976669441293086189130668806070062735227716201446949227513427099170473904040175325858020948749129956879267304840501318560999535128900203706762914899920016176414102408043441912375586879352913464843561634555065811366876538015183381956829516816523396842205713115261327461822119969698112376516500844817166773171991410882712400496976398544973276908878960336470176790089403115385749289804583727629322678869790252527007406909030400000, - -17233934562140298644591265829290804309350949630639935350621566838694316683064657945652744893134877098254077253647623130348528993943542752825413717354153936943658218966385156016809109787619219897569280073459649512149080024347358147259428491556167823123544930502650766685619321989772541054580432677011389995416839429955075344531783207895124827381792324629297113657251401204911551449796453336464617596445677174084320524734599534180528500372372999447909817618093215934279792400379043522516915697147785310136473718307537937577147250783441738019396925534438114789599884184210146475088427605852100663127362218626826672941946373505967836969543181491501240473818755785308118546386034554101039655099354448221870737698863316881746846908547944805528928780288906879971699590834009267755023595210545709735855017918390464763177996113253126771768343781991292859987356227722535754543090491690280471615269985136304791605859728402515974519703108277760356203786764639556219859651741158973528495184543456542860146404579490800491247523005863506067423230823077356771663484908158141207049728067968380206811341012506260162431936308910204990199108452165994253078492345601137409619001564213572106045457118650912583284560339995571083535123874736099782785968527732830801306365676857579374118347273347709425092238822952289649182382914769400536672686732807186651307355604590998578202104884086320763776979274567700152823538400494358501809722366366982865443647203984732912312487632378784562188874758303066055362352914815312750944796237319346473517537986621361606513569096997108986477797898028258379544706386747659903692585565797397512403428968903575561998505332319909827745317152924986774989740983257027304010335603123586911747483330082678972307276744730247803042566402979790136807560084733270252709417512656961528257243501690909462344547333511289435110314243985196482410080295148031978145130238287284541654545716531569304804441102145040387594824210894787524204657390850655359281931024841628228145661731928527511190750291106901235072416824723591903816849841459069551823894899427694184663922160923850419356674387737004863427858401769140235446053118284958130219163234257836483941806985949889658220793759362698295142583211802774447966238671582121151963717572404036539573918597599657301986177540669194829574781669397555274594561209024266312103507512688286229773492570525074410269347619283484457192693616970369368599253810509696252649975589497550324472781143618928598096835030168719183512704119856452538463140833935669267692373730377073522857470394115302908100666039967902674007141743277519914521722906915724097797995401269404520763449855206610641935249301135112792351080662265321180724513057716417046018231716438246687728344500887413185721072929817045328773802366581541004416803213958425455767212145377052924307363809785500261844946431076240084435745713651598743451766218906174791520890236860397061099551403334984537197496256075890005691224960798561564611628536004153823186493972148576583567661194539538083460210756845006004947278491770052463325424713297052628411878200276954756475175832037003849274215503381673161569849808706901748066828771285672630765008712992666628527878045054679482802036167163054354543987988174733937470109332415055731854697262813533635070572540021955832440684935803193463367231438531164585278764566257094217261176816166698831338121767783979572288493853026763980293104285959841426577368229614765992401293437046148439181920349044328542513712017012630633469465372782694814029086921565647322159896095929495466715175519291773397831093553277700255487897659057654527084878074818768644380801241033739628845882033024890999759976959766394540732076635755088278205082421350979592666110148300323366449944181599188633844712807806686526124826107814369459566769250855227125158991909595633792494640424869179959034617755952307991382507964026006965963832500323586657545983207105833012046166099477101581446287629982051834772360012994194707673415511488106850475144705045279174576822378959656671749377829897128143807274764250655456309080686868185757420532619717419492686762932229936055484702398563134824519288786497292168661176944151508472077724348838078807425634713643748097425016633499877458439523719735123891137499222978952586969185929639918827072722507311792107461352657616160109158266836201437199946844543846369098827085756572673834613763951654229955221027498588907890641941053632954746136833097592645351547509237604600478159093030072654513575666813078186583556622900950741379412825191052381331012888298355947989523564724513392570930917419309978723168427149892892679634105873951394231685628369258027168295741458435636073459715863784618002891176008628318090934844430725181680094905851163910141345247803073127753554120793265255456860601725519277033122283619635957674517222803869006121114505517678024729356233846909541253289669188804262402644561712195264728461500975563482840883483307163082487138630384768031023398037726935702592812907581537975511612823531077444435111083846852167648252375145405965315996450798856091667167926659148241542272671855964636933913240287462808311088737967563268462367319875434216912406333230736940982830352085362296435086443739851775705204775648698638495171640579494185188778687832766353460963850707467168691502564105310556772640358772929445557510243651279545380493417719039041875384918287744330077518624331376851086680970461332579333070569930151338979261109035598960096546094819178860277894681787817379596432933743606258301863919111354277343697741084837100476035317929023899023803687924290038965008669450422676285431523253276958005413530570592613309913639161346267605350179056634479978635476132986567342393474793027481821367069308643296761917211252516239380252635620952035490546704893755561818014517477733171166729492700455193553720702299868683336005816534168566149327471020505139620717346934946718556276211917248813706669226678644308503999494225662902972810494967509384498596676424624383689377637282495913354135259741052814406580810153473561760621787825077804724626609773755700571413251296392064639182954531900760061472313936641481471196922501667262585225834465201733283953243024845352369761956662987501082798723718424166735730672478970073837972100501075750622634965434704469395259549648741362815148873688215482560897336936024439373511170031413093029211598854984295810468190458057240272431447259029477723116079682848805826082355345543047547023327595959676810492697634035681122236209742677154010462660223685112284343149361504493142853662695124985520810506114009922721668554241770389815758498521449722857315537475111553770055825829381420622459120918701443942335455885917475798815250373155113779165914639236384982504025483688674520367075290459209645515385562787565990993055910461440000, - -281186613438651625961946813555116547979760792961295832276431468319714755018639715701284834584732858578090747418576499397583451364564844337036817116139511695664788810681937148155635041299628657447514920819398322118953936662375543029511702243323126816906489601637271701454330255706924422644861930935406730865652136349659100610022528088742823391199203245099156078068045952759632121726801449180263758145596197409459122039799001035615262838383180737704854853852577877489494005481240965236800532490080610333749236620885115900175484681743415615949061822452377853544167130267151544909170574501760979798758330656433021868186374936129705420966383440286612460302245034924021468095533214036449330007626503920104303237388671722851894473532486672433860654442885560743296875814824912094892334338462681193879375351751060709067339811612489300883697323943824730864627461208747327535782385387351973316514581844392097194132427741878880399991850284087999675475999271621156907314044590235185241931654498828451777822604051033960145432495734378485075317591011735292174816539914067224586158614259406774300517646125128400840358309763773108193652626774565965174155898304411741882968323888410264909046878990809516987594330179976008456747619214492018070523903500762432976596027306088041745698907968038876076925965726185431267623916057867563188243083912499975834326270867914819873773335042200605722285889031909255183566492744823572675017579444632161275394404687649902884492258035816366212744363464854899241536087250096732140021750300020666109889008595239135573951539697873664152828654948167587083915290181328545780174896522963018945349280045174246311601885584062837121954287524259610220045506383706013555101848359258404826461998847704848862736445141325608464996290005099166793154502869870121891720227618140270056035871393123500823211488266874491300672628619945285413542836443477158745810285697533175338285962943214304134610030655605078899575268607482442765709934463409633557276730229762876754469761602547672806879049432946381489032606335720053129819234844888897080239040345982205679909589311031952262246554617744477024578588086755551727622558201938842324498445641656055818715398993536388947582830082094159877992017798319669101953616031370029495775932086792552917163198031748321956854174055853131208460881723975379840766717902424689813615620854285118727824087494937365212603257697624653010204117800212569255012749846428671978737431658920386390742859884755833704575521607663452953751605664426955228129211400248127659864369980061756632853102188401338338159965672678208715296024163708885611294233836023070805240282508288624210826739558882911227719880638470681895385471631209975906355908096023921928394957690161401232706513946090977892681365878782461450692375584820540999116619386259878534328286257708584907719179047870592761920723789946513539052329365515546836555875124203378647906004268233903277351123970878330894362581725335122620229609605238962256007054236613070109506506321012261227472247999524526707338679657770937966850960081796108781632774496072281787145377750370591880809242678971115415433311824470235172158596085368876862364884935271994842904746479741535196216516489697806049524370943082420168515688778461852984342701482583715476414898719875605515141346407081030461465874854061219074999158058560138576755868983636969222679130181143089541560136857956846145860667589174413310569672980260088376868693894936290290868501050548311954740468868915249370762669033856610449863291072879083158090045008982091192447989729034556454113694221201304950270487084702863092360960652162893936149093134993450187941806368500147555997353167266117366621721674959905072210968288825807789874361671468530954004110798394008664699907541932350434517758555753065787266520826867073093051947089607425262583388971296451313675301681178473121544608665460116383291695519328751217767089471759394738015437894066609033053912391746675409159650848023168003298733829811184869557865677877696819248015573122380558985497071726137052797925199707486257817720373830376817486957819438969121410849951037392115130830775997771979295713461512567634586166717075683210817653204524241345414003843147021625028330729430472019819013984029087060790673925039398959504588266360647522448439596435749588664185834187037690798343647894902208011666432571505567812583210821715405279070841565247489854130547392281961311088955864829886911470240339891098624368455377620902220237842866978875750776558944762365476285881175566378782488314679358677980529658142907659570939241571055796186540912469886839915325525063370107698402648455148468775061109234035518335117050032746269304716155569139039436838015624622678289011796927341726497924985130583790624268682668354312245929872857405067095129885842649280478370189396759124810414400420950005930257266290474804923929696652726908900891966230902879458016446526234473535685713024392872317429852783554679800342799480796707201349585054236865478934208430817629723675069102462711397420447690477794228715331632693508026178233829686700443189901629554607719624230239669757333768564470282572284860569367805778220459180553783117291712229715367128296418428976644692435642114046728209220182852748126610911859901740333685360938098424160240650200871364876653051286025951540461468602240323388841509447017389436772913978633787918019114117733801670637099158760118581137369194476705517701286218305788572533552298925530261606814755731488172938089237196722095409672702634899246851544846728848676215928208432996010462286324842006322542012098893944179219971749676636433838631840404743539738690292372007257282438094203662249646439559961976776556189262873128640027687736735453006066495403541154883208637053039175282439801066856345285730789944579829487999128447673692119303823708957762571438574419569881823567125250213597720880105635908803877458735350076679519050597488472413030766739581039395769078796036706694084337509613860875810841153954594547899243537035371121635081898272934628234865713752069604707402146424954966315202480652845222299472134052221143189149340369059884369536668898510239233375900125017679138093196372405490426211483252315491118974117969094980788665704917256480048675747204846398160524617982842843677407773169811396242297042893484495918154200140899083235084213997830000622012324715059368665974599389682536981406075503712248477756609742955208295253217264173775663161901676692935881136739262249823620255052257489263586605665790777707512046897367843984455970010039883147805410946242519892954222595891510704785905965997204557110600781677756149257459240039099635117568254542814382640442454514079062456585593918840281060408029379488755767886603183282085838624231358352577932508305480773110503215018377323777506672640000, - -2664087592430968295970870612988255877134625473956364782261870605270790845060632822497758179798181638480939457266887013461906378031392234694520611762137917867075915270974435856201980881518070888628958124447857581589856936725182412986511580944423665775668031621311644321868013399343356157053460318811579847991274901517118623588057485853287667260471586050881700542296607460652402406986288122231384347922557226266209011367399343009805461081959935914133003069707916752494306050402197029125508176239248175912503380087742688295365784800110546083422958509156564052126884030352574342689809432540721469496313957474100622542699690644990048465442918162986057300811445167483365631125104321091876501176544272884398918462249720905382171411334830246463386553223314860311409144222958500290918813333555810707185634203393140378721537588503178218865432306149709103958287829256151214180112984233097009181727076802697054557469318187857356484704001511458430235996258217520286942570330394451977134089752862639877355931602134104369115490795352973583590879382664471629576754679371400111170487685640944947047769718402802274830277733262964732580846545694768131712545425940673231426071493112850350583840623394192725752467452113404436753568005939000413224418631008166379278640103420257057896282834379545209380956911732981127793285373692637258706465407588480418929719849161577362374124744644459853056591121997841501559803794349211903836896122619295188896781312771898254832815624472565584710909172709155938243136287558839204273844257366670427711740302515212460360163598646408101269366955604272725561154734499930500525040254217795901093161596494517988835973934371195882282251843020445565023324829182936762942697960639974871223890960193082463899504564107324012469679938420956377367024148545839264434729331224302427937188742354046364567359461995356814399218670315482190406758536219710043374237273812358146352276852501774379019321916933629683375680685200722251973211754343605627219114857813991157673890721794269681416264428603406155637736668101985743009620043185891510976828988766564407156202232591624336684960819148975910896900850318955215260205609310141420398339890189131148032290368749823062809527891049515912580348577336135769092619829122166043960622910708648807243014872387144358566374428690826223788437384992669784845023319014523597225925145478704256343814013526766195372695268441655502646786837636165163463117618721575796601405608338107184400199809932660086568397789913137929165864823031576507530640875240337773934826729335730898806849485724445530744929083181726203860268634428769638424878410049784737122926114021515075538884994252533303693241631140338120963538257009864802980772229559909847756731964315223605903560823801137669689547609801765417923760363981379321562364912252964182497160871611046869658746470738585795447271498143714654704182105663863971937238530313143176840226644885760363368180762691844084529632073251334353315264780543329956952288465643322628954953073735532523368100982641669439547447321771800240157622137283142982766198181154697284698637940895614532675354717773309673836891828806025655361398264778634830591281525642031986762178819226783496072806420929837705256198704400904785109015709846935891765216961450222901437079675055120906378212135493934834424799977680688058787745923535828579703517635589468299423449552691545161483959860033219180389378521710003884702019726958564769561377181890484377298493911921348949576776498372262766375192151797249225168704445257198254684985592742270398777842555815544148482128110154791714269617899520892144222062444401916150398274067047886174827173696532724111109484273760045890316903796120527983030048030759860265192216725076200720904771483095547602525208522119436125443801511286689354961790691217933884024752431125301848546861669455989599362346271417538334927785573744553556485653539714981881360717718073393697761907926849796417458167953205226829172175242839437000667173262643926178435292346373703553987997323183750564296690087404371918077637250992493500004142645048106490298317173748566312003788715958723947064117321131722089100987395475248757430391063188436156258059272020349434765052812260844228491223062506703606447078948710964980321046741750391699925329595351670358271844866914094557564827506955144151248910225932068503691071808425363321463397848286297052880065783177603310362503348543884728225872513512169724871455617216167525260393729445232415803073100622966770859340972296522024138269945309046198898721359290009660684626689982226538199868009305187685557016262895565087925251241713993271773002993190558989157879329673571156185405034381071544896581975977091327930349821899671409059310073466111628779801833705388225172429013305847472621033384266256839627517972207326992727653621650122048613230270009280726562600373486743777754362103322671873441907131129204028890352752702369846380196329405478334045402363428959981150604548582778747868106126198197724252734991779074113078059437846482721326584340708097872312478812613405513639894844065468953539298515626010984690532502601608797015158924298507020476096797549475863386248085784231009409126951222650089918743507660624740859201137393778575040905103452400088910266825548041606327962857942425110980458844098326912330931723344770714047635430984856861205894565401911919618756788461189539993928077309001428738814747598006827721757224797446209607872086882265654551693106107197877648166577112141976284762367243802936088459373659973640064788457709317092037135611450961650883765273104762195356644281163823815837574171935665554326717059118443985556438806062645249551356792197094566069607371681434894429241787486909782647598617046107713148160162457092329917210537886542226347972401096726720201080094732154103581868058887498882694978206994694057265924166283436188505620514252722008202604262853759537867658882147846901243885232920007596789202048896152596380607415978984430772378178725545029033900599954422750071940182008453121543194409460365781221286153498347259820216444395472076016096474859951481595383187191794290597133379100086153370858883862319584500883672114500892041147098388356773140383882939600573172325538824209475741365974988931389113608789429756895299409958600956648020976598347930197874137541888352352958454297730903041734689961006094109793935546752409017079208741645362885655631927483135965351317114977087830011144562802637564950705459266151319065451443530314611627773461340549546694298691754320484549087373069214074103284492349060338221059985362566125058209835584257425667707208793572071263491809732250540657054127629491427356466247484042056772521981605376931810506380917829008059005335188228799710461765026708413883713189184840129341995089920000, - -15594809182950537096891336402164404988654972875826149798090245282003261207988388617244113844672522423990247277602129649477232345342809361385435721357153369530162130769624092881990093377179472301959797709041352949189599375273617847360539840463718320395426504492877393782928454556685017120167055751038868909016011686732998854203821010616082138552758319734918368102867842260571623451944133723596684772109404978118188605216029657800389610506447871253095312196516218599774721855701638065135330526701120780328165254676116991735265980747752061540650355717152215726142705620282902852886116572533493932640796650032488390171467318082036297721362711471982449837627229137823518916893979736686619307686901547570768474906497960701499375980440769966076437055762966332451720080870561813457787181644359179805832839157793474933124066185378181572208012812617649669324505166564219705669280789492626244790381888471781945095078433505317662553392435881118931436938067792507766474446860518302382870007288625154273592258491880143978366503214780727184490980928508370504698638327767811726383972413087352268406594249511643041267303198239730196430950892053627126583235780099116933455748810380445635595677691279838305643657282555784183586190752473086774052204887552681995239156324024399769555695042977247913115343470099938258745828844140710960726954489504369554992458325342248118050672134955083619831643614409419064746316475660527925168604600364162102953963994422301488582445560282250951827223658015196283827796539179294296200108009036303126546019803552226002753174501052174679943584998808411732437594063566778841681552610568278563527377172830886401738087916178691697959780288666206046458851488971821103428508106646247609325072201925795145565818020738228774032485856204417280939212372903877138738810725789078824859892103358227118288006794298281807298147112074002778029690256579632930283500992083095711595379528273988979264072215359833879628222709364835887128655813895644133132754547449575814813871713342354377183128210583441086430182913291703019522175885987818840700822879344441352222049413758790790159600547278077856068969278235299397848808192448034268261532205592349132371826350688650883651394886835164554876837291901901060677383002512689841732880836792957418549912048501892631278402425817430339869388882294412176932631749898673360152702978164468391071317273958825153188566836313903755236840737280070365099789534990526389724573100302376982625584006033085341383015599470237370497697117361264339953396523410002555114521095307308357251508979906315657456041808658781402512704592880484438163117161301243204475896356541719660039174861693039922470288523235925900163832442644942407926395740566904669917939169378623230404833511872573896361879553969412900717951031829766821897287582834460617060233513539178057252286260400681893022165230230319488204186106683626730113947148173080705540116664768194190420401421778228282966148821605948434702823639380108704679815722466769934577260575107999531765654381209763151758436570755028816062720161546574668443886713168799044234159191525476086451241402253239967415627282548535915488505550722159150871785391814972644098053637079816399259959660543947560096820187487405573409672733998196972401275500688611662677407824567843798019386997524156418671984191238618414135937448414996420637769246634642053799904769013129180820394740578207010687623443106859701994012446770827351901168100755372745779285848301864123241130017960108474925182421298053352907000559910707260832780312452851139379616433394479543268328503368807572649484528273163509777675796418095472068736696814547938969678724237004787895715392200140610719552205407077168507801525790202209929845569948689328440302530998323164327203953234359095888829166330679230201431092529500590692805303731615038092208560098052403576532049381275557053432730602563583142052235697204922078331339310175230096626548884078871886044641960410756473087644565548317605760310900362204122623415173767957933738451744855586901583477619658759320487728126822908758173908256857179991666869413480907110175552194984017393573896403385393921406924168579766600608335449563355894231099264065401380602712285728554795854897381942343631767939896101080968325816469560359543317677354340068597619928352815892505801658099113834507331226349969808210997479857092586020417640452785460201386135372350644072825823680415111818273359647657422334609258229842864635596749418405022679889339496430954243592495112263775153754634085481481967149102995389476026540451774131218730496320804125043852854965769401378047167562747000208246879355117064901628335513144862532665849646189643875910427814881411288400620679670383327553946507278568784052126478529752172619864416402773584879697253045032477973498213506898470115554712332805417798133304548803788195870401883660784679526211908465820277860735141956793739491907517088523268394734172918662917954640694982085096730081102031473242995696139525850638019220665531385953874538467612923934099409029159383750581925804623191996496878113848600895052631046937094787226980757729697151267681187471097832542916991944839541683865036194592550316682604112652819824403479553540449867648629696057909268986034953391321800012756905409871342674825690455734450890918469659937485684201110160147444601468016467595162179295428780559921745428375137968886315213880023868258083513758258009745072580366545753814917199716400559368564800308798576635602487920398323322338915885023346939484209163397447052512341214541807095508230278430609673651468031775096397107311095708226695867943886693873841854425210516393616784496021453584419504688149128001626710744922747691786939760978001920851279264017875109958570930177061298664417238636559734176717332740005727938450664001541926125484837762582202707319702421350718642173129189214566074206555579923876693501413398617912190982289497576740873093848973246535242499599431273658328710484840022029706479009319569736454670557888205868398837339134300065905359119456041123420748554890253009293894429036107909911928289983518134131429873021983524100271991681734700517420838801854104723531152077798990097898507614168879202788887550980227047166130437764320814295919763264323216866381364634433998191417697814310120733869449359225151257725368100693260362195629687236063469677569646981245733139630277763142432889572023105171410182415435967307953839013665153397095903380141227023420792063014428835246384050550043787910076418495379564331757521369048129629643690952644831350435109411819363990125895562645732865975758644352034557713502607512602510730693891111383084113265524517899174116631153900782846542204630637890297540093724590103010278404767133545584960471040000, - -13052775433987236462041718715547177459519149910622239934627644853684747259566244814459307990786507105637581664216564371316538721042068983772199070393087336536909508906041289646951011124928344811303619086731991226003482961533065943067583540848056813314583661699394021634291101899594026997792187735101065682309926314467352743486448460025223546542727360766747340256156012893373490349339286864850043805380917494423308599686687917342981715617804600946921327678566697324238278853498857358239041511921348406684723442708857866378570601450631331414476486311331511032487667000763238924246036824428471932196304043974536519573233012778524858843157629503041279679074977970873909743388382198566939260438877928277321686775648854131552205087001326901415340628175159235271031752811732248830607593861327187065081564976104060042506315712108543458259842459118131492298497282247358236613856068741999436933031578114969575774950534979880577533634340772954020047021865029545807785252701000783400021018028629948446239696945760030974597514821197461031390973690273807491223613535873251962443278326768407002443880230808036683912625292715176197260717170154903128148522943708430370626478948367323784835410316775319605319501879935564230446974097316244669894904779645872543668553781869910692286643468628444099549173545736807092127751541315311209315172488345474093347076154077120997511531619555249514604742924499707786298481853337978365540200029628379420212256155624383149657153761334853076299587968469985072215123593921194127385601670298714402035159107054721286790806746019564569667923247153336530463139760595688942266302748254643792641816248718572192510409700425659770832966809716280906563239246736318800723181402447190911426738950116185331861970044679019436806755231115863254560717231565891715486811262612710959324891389141295287249214773713944345428275166115730859539184368149810876806626871754663236663409351516449950398177605206869034129347090200707054281565430034199120595363865243168899878901377942409585088581556946942570137249162003055468366642171752871210767066533973005319640130040317265895930360724102995974781059807420219003138159838242950922029328747951477384516830338573028152725676999630255915389772081800017875919391561619639302190145031516141138081780663220375858597672499439337673034134999768394057824358208040969685126954929212979872301039139842451726137859730344373280946412253770302270356987347400995747734350738056852497374587283222173029832675424012986759521684178024200103022306150928543111403801449104595881183924452953052314865086477980627738382045032190577475076920213078119413724117629898319180596816570413487899854788362285118564222401702339545092514748058600660673646655709463673869578335872223772480324167725777726658186876190818011577896456660835387587987667325737531603369080652683976806080211973987630787448623359476038926590033174584137389650507818286077060602340166698432037007160111116438158489015379507107914238368349112585079343487320989822484508491009416054951817002196148071146183626440258560416946027435510592066401439867679851559489741625302467068654880410681834428674920518124245908911963006807899952640334952221367806298665218873353957234130509391655858714344499214361347299959413157605071108440219760717073533325656475037909330815511637592228915996060889075606137581700959061161849246019811124535907198423036649847003512977851183191692690190801373497442953200894746757691248566601494181375984301333023152293336757598466448454827951233205873326210921053038239992518372700557396678588991039193186465955543707513194661722406321846095181541344588899610975579381577972524505151535420310118358362023079620415014655097377148364506674135153580980387015942295619583339765954312270260512433305223773866188847415912983637110026150256555283784798647919580939985274231062216848006753870690223997353666120152175274444478864736843954442844182578307149675308646233611849724335572694690883794870583461749552437704557918640615004405957314088573005082441618390485115649752899239816639271344860941203186996445728155374842194279469664575528229492992320639641104446344107615963735361093242353463991132046141851145376004323087764752003781330013278721017257359421522480410745393800170978083906183809586861410286913934753855940290889404425470028984879422501851456400462620573005734169595927905501801434212796740205132599113183341900657435900444300619511654746993816165255233670645086536454742505562735112487774051393650727918631806996787666521241927985567174830942412021989457222283505642463603849019734716733734361474513634649717084334571827105636402670551344031869890130311728769111245261823750523502356879296752472112280167119564989686694206071101543006993738692951884470550915120847259867405023897864546642667629879387660978280761438608577328069171052781903007850278475914064444536190963042020692204959257309298349642848277542971962430657749469414143554088781586320445164058458892157284515742260232016546510550412248011592880506444562329953301965073867690111783463159152108292388915008431704753625995557672203293442199269692076855385154293614435487158994629582327449860792380568326809525679346469143304329147747203555923618755786067177970499926198313815517532509928756658244797606300771565065182273501918211183903733521167222977662640379037837267681979341328271988430641563267093806381478104829265017749554195025130369702848787795160592752684387324504601058023384670917394020974581221648357065474852939744635897803258100347000343353080508070110201165326076165644675284569465899765863990000253272829570960517774976058932839689899146241397423487886292341549323053561186077719860782365654225817757712537182591699474079535859199673169347935541102396790858314151037419261394485198718924459418052200789303194866746750065453532653925401023520166950933352274219333225646148721978050751624921665108162227495957022401543497574726936032700904895787299770660835960580991923114485845810062260916822105229157210644412198136619293999585110657220280439641207591500413343363231647787610633092544602170672269713256787741375785178656600983511196196567155873503021993599250805145254414697563009452404458084954717277328699623149071979842392636957780757578709038698259949134837385432601779041402664328600617804482342846718419781927628938340518544744886348658220959033304016162426836512298505075816568868466509972041591054521682834355824453535419559713785969381616249520493928107026003764727264357661931482075943331230631992670820189601849873763053874912596719759273143330801184821588465937786128026403814554039119471206183487506821856428418990631204389029495572337401242066732586106880000, - 1012182891128503978388401519965107055049476725636564767161729172662823290256294692112452219691397179784111256108291129630748757155769721301065873680353383510338020274058738023317065595492820125763237632350434818143051512624413483566354027437220914669634951498804889027441593977508383927443115410331981555938180241665037268940781568000564224580112088632806762037996629536628032315872709974059227072550076583303087312845668603665588683706782955576432749804278403592112679706245824413926611544721958937866844739676273465164527692450849155613232011538286192122304274712733007015261597726910064266891853314322225465389184401847143284719935688744891361398664648860841346677938222989452116981354505356003876721877490367926387175344371733348972458641972800643370657613532428757357392658101708725139341929933421958217746507232100940077020878300029031689199777520523289610324515055109630101351962883266953947172087203693698279723028662508603315073929701661237454423480208779017266757565540298538764084295711731569670501083592975845681299844388267850160829283089707893833316516561487165779303739761394801693024181823083495031902007687483098559556018620617372436438635148193050878980798107190844893999687135575108469437935332803267906184398674166401971485043938496907970337647951510287612796955926325903567001106382490471924700866287519639008851432199145482021024344137162264247206538204275206011289659550974167379941020918119461697652001218265673040398719378756060235824048995778734359358870684715990141113631461822330248376458604186334139393293195484633730065440717222584849709613253984609430038875406416308042727941127261786979003082333911132423482833582027270591435701980878264921756919217293172929565999748323587239866577036677338196844350836325479338627767246577083512055540163002700481274206483284785153264190294060140198012769784464195431110159671876300808080427642375118946210281205170394083256452347676249146191345424417734521513883216377914505320007405750340889051995815027503457060448586962691563011305428376237096467149079750968841248390996858416835858760936171757802359321185279075188236667073329397717896222599451192743762280647734961177192649867510438086417985559060867398655521715637094387324126954151532244385709245139582463496171664157846168564448574673387923162127864290935729541467071568712833761536448761078356780000122384587960461700911167388968686951757895610242296990191668507171179129219037338060053978659647205986117777032297441472030785990531421097930756257194633628538167577086279133959338993596281096838386104738920137115181716389129590690977855661926725881341778087204511347887569713438126651189833424830595260811771540494818198697672195221232756365922029679331682997046752626727353732050229414291737804340953586504363238660961868010396166829973219065519051221208770909616562879956973223932697445303704556271254590821577586502959549697399871900910230878222427093001049861118646922687741713669775304559695796740297774836772112678519252466377377318401730313721843617437571551408389993650455422785951926070413422191900132623953772765862443719822182196222105149346021042550340885948973978008722561919811118674715000908298746436684487521530928973994929514119039519723856002526176326813835151367106632539191023621974460273745982589320083937382819301529556490505642462715244529404044957145478345368395722056223700545087668416702782399678616787727300110210945078335489389643586107634993858473173525499117434841839734213884214337580071994079473865761962659326552612024741797911558508060737537373575078231541701256380059944260402351753277989909735125940390738594686766850324868248929835275159008045640404066383201630909760883723988267198968380735943792211568024049941096774700255044297738549799768701894059478186524740830378769055574641828017207461537559499004531539315291094685881825489833570082538988235723597496264822180951909142024924914033048971181783979585022290153543374024161669286563986455002940946471350857665432614576086715808026677810662261908749883443202460034932321713593450556366998124599768855861274418532384042270351269261308825575751513629108444807394473741811303194279900026942722893163594831830294213763067953630146271580203799161149244833195355413070437921995831905961217698117740988760714762842911663966464995431488364220260870925132836225866761102573438563464001439954429221556664890163070034308120595564485765284672003991044986566304837695436673236020277236070867781506093646415740290262417668841615267503651831573014742043031965444000681074639461899850620048614066468083058236319485708642152415911173998563173938919900921781025538152299773085953725519670900614430502571074558544494490775303318249167639596845215736471118540741120981788119868980210461925112565047786777978683306626227396879109019469733858978174802880879390156861084134022266224420359692681827638339382352768794437604838428777085383179046979545612706669352306832493973879739870245298893074951384874267531387459180015597609420410948993013054564257119598595291728189875743388498286781594776782793353302860505881386400177091414863952479817676194483970188790947217902846325748660395083427492000882299305287025046472800816631689777745123381937126499991766347183139498833065428638454725562013765276605926379326443686742218738587302258020186917902878175766920396268533763399706328233415876301510560021642197040226218354729808396201271437133572359009579979717966561399126157401537216080322793178424344824334652077075496012502047513954396392487049285596263672119451028025415719427559865651395516737605414598161797753680635657890754473252067809479690569952704208538604754168815848389277127412608272689097143095676788886397711380670100100005264513556753563731542279173875088914054374380046444197926079366722609263174667470614408478759696092639608235642233224667828314698801974316849594591252603653797178939871226665111435419073222176359510842759524260279057663633110655799365535827449829805592495368258394485732948407942341011001378947474825133473216348810319011352968390528414335006303958188548661252908038389840977316484333530163526041771892750019736931122063716355509124064122276523162521055570056816685675766174872051157460758682155302605012032645594856491794886421520299594873028604010361657184571744814952442524823226311024672694623448986662782344173571471994562617636102435943535696676292588934702087811937653045316557618713440353107605636059655111153091507917148750333628269164321860127139022753676740169838303375372376119885982622486485657141236639377120807930522269707735537260498692296877074306105328021586693981371400314725335040000, - 15413226647970370391742980741685945501321201401305562797133185782475356995330733177310583137529958811724970629423570240102331328595537193493979007458698476693944403947704425534963263722272291819411423628002570135361165025197467666407345657400784128340507877351836121194434004044058225797971521321163598940075586852136920331608340145488895674402183277153488290835274734682377490023565371133109782904825518892462066349732481474909867844940412096847440750950124782029016268168991874130260851945131838134951745006904773194435407112288488822394628282184019081635279410678038713798475857881518114990367018033432790902826949615236731307020632245717014946772643608817079353437489211681671776197994855112585659021227144844078380007228408987590066503791803235709176517823605997749858759096072326366827587384996760643876339270931717823843119312811780475196570679242788648303244781052122804374129947600286136729818569312363471648493679026599505116425184697623250473163045857890203025925866152795903539192142287453501241092244022426831492850321697964307218159961980896458072756845747731145488522902726029836732823194327080505584569734539480353483430333575132098922225826179711768815564967814699174827250174646432642602890171295711801588102572737175452274151080206654950968911350786084770787908380089779429051851634923606543635868360840559249289774377774747756066356978199593697662200365329956425225823573964067243586995391644820488882447443089600918563278223098846007991728324989678723205032589502140220042065319600331160259001912445751003751665688770166324182686681523849358377095171976808763006177347197760878188573829163048654712764636264755023337251067905250802150492857842645428735466864779529837852637264672707352338462570578812767824503713124165888252012878986474166830711162728274544412033636439206171004203795076673940095237426482126643197940221635842544216647101305535780384182959908692436529231251034857174242969019235404161448625975825320898654037749231262419219282662349524351059973181404472691171315864968096425291469476209580483360083845991124378526423750387575255458468492715340662762772425258753532571455546300738051279286337621578942144494077945196961900853125304781917638076220408596989372911377202152926326633849518455822204913617228930744859777385238928493250619405561531650929919409762777899829540946254758485897385987500743697850867013897770140790045451218965549299598133165342420336158930026803712039932762341809677361188860782597681825836960387522142652413785250957626515735322158917392874192175782752082436392901359507441095148077862393766190879100510090292171456349711014104593129689439865253561998059449274281507351971137146625418715830651921139103703833068032789326416773356028751510912395175469905473282889778875283786140025263009488151272060336071852170526635193630002599784252155486705259496687047524447583208720694552201677415575624848766591632267091900301981248144224305848322118212051400366820596662521881881025058636108859484010518249022160768866393953384019419197781020709016633251972118476607828089610210382405703471772412551412615102472165221467116135209131513096339227620050820497484535388841433080708287974051110314627348557111343952027450341344831357114111583793325323728184291637682091882174388042502514388080353655315396589094164927424654849832693009004045670049705670321955997152268667267989373903235538456793818688092579249385993101241425824189012362160882238742638511548243881472268946558992265216158634041829190553550903082252867072262260260887959744905706814485320470119851408176774313445993689181639967467961852599003221279388449390665173005483410058053900755288406345010363284167973984610453056916839127760521398230116192912671501649672654277491208558216563902006819962067847919897390750382732180653246365087734617424951952587839431894433222878923524919591511167960406612201214030289513551133929866184696368566649549285684759691468446760643548932292246785248512393520805288629236146050935323828730833622323616617508918014107786229086514166668690718709249466730427226673599203870620146967171314808034068023336239474467883870072643344897737225333665761176533471300206087401612654133697440871752248703080332411430787366529415759065258841169296394282592260699743103084182249209761823830462075218752436278543030128572770214961757605459260087458348425998785017436700622256429112702549723953859447723204660435117991328012388119648027834346201293303572401848541627419101854315981559367304273467055222221830096923447157681524332455808858051013733207457875956780286640660217006665293524845730205295679313428500771136435123018809245353606254463397950660821043053601230935455548914566052867832572044170681831554163224715251686133176843224265767206316364462084623524123229799848896540261264964119716809435061195399244579642685436168918233331010470144140760526434322661605765870996176386316143820133672484494615923773461370110406354613252000993445007755993222261235503454792344621305620518216860983345082861979905365400934595853910348621341072921351034532880629165825225670669026992277856028792682432486741194572464921945738202078190489073081599657609857196131286740346737300500451543988162328762363248754566486304046394729422610177179975940245916354538154013220152787971482143233322198873845010758931786211726773480464157391719652075401872675553290128338354554442036218883018678421046318814981182412799476610191717382702027382856799632717779893638279415617426623516227646047971507309945997211635398215329771166303098471313308496899224447002082602779770845316771007279986920708499754316878166652559768901819084438080958077568119799853030877452587417321730577649830111401151362358409015723410399228238666754829589530926744110658932216583815745615906969719449808349362696959698115932326437323795180402119112637823700285631770545977985349447083667870208792827674518434041935681189285519806213690941123947488406462066463709080643006177912622067568762257883154428592716948689686040472308604537434403409930318704802267266034672819559422915374110156373091875026614107079238509540598036932145961185955879528308528513947782333631328449896869975313874751445491160353398907884768910279227528897492170956747819112961945785212295767151563968678231661265953015730786265814516611724980881369803468344868566809783234287187868937351912890091711645860641924958756996783222354922355134511715175344520374035178235740289336175917343849495829115000914071297628249025703698626049868821615185569277521116830845314124987126322716739359615439756815859726930951236904021509108150433200908598983776010240000, - 146390071990313181757669615658787847872689992670420102658883275768233515795921801323435332736587259646449027548947717534466859403500246764066959802991511373838321474670577342590952858934287450080372555063366526806449144410772585228824702689983374019679238607004079978424995781906580682483838816233623917301586870915827435135657365378549737389829533843362146779901369118165813914822361768717076434187990419518449760806613850479942604752063187909901837074026835383523763973069187918697475109551350506329499313817671557423480711065873455472244249587751183569146216245114528417446784232817523400209597523415116387981672911966642364090501421581367198675051446505850243029008050966106401575165221495609142114248662697561760751412707369706216666264819840005893528094852630484378024673931390332368893642926617388109852051165397912559451294423602480802643841814429537645499800419704329538036749421486650742272686336275658707643783070499042268739829762581395733894819801808932618509691137595160652337672133657537098051776112908372449593874658887281877241896741870079281321240536824804117523387740043942948947657375994111725507150258171235089331127382726492596351933817886486998460102063933718239831485671036964488852552760878601145893415935015287284871285951781432762264092590870392738629857461902307265894735523745305573986189488314057683304525949983768836037707493070363635693043621928737533009159460529235324423212188897027676839588919478084330474004206726485244815002353546230154846000637647769838719188912757287772422210276107218521827049234477664784003631999804849855203176727183899415718066835468185015236610156607547805570569003658549076561299756725758892468782165443728511937838832968609530341351628753170625364719234957619543999927186201253840903640481060048901991797304882014720336504896875111187035039615761806305208573889012039117498704129663670576802136743026518663518036870739365303579912792906579862033255977367047911132566628850714225749391137893036109275475266650924529932233500101310750287497727527414507345904313238647825441261185787462454326936278956142427895494704907905549101337350553257713789843364992324104495622977154921511062239039176203305128290583237799725091025501576050619877286984435484565080517235365348886976717429885282372246298895549372627753619881148735269426381398613994462858032325668005332398233663439284423120550568040794873342910922705744582426047312045180283981193141655176195580941080745823557788880841997094146598930151684156429073570391180638756487362788411791738636329217213771083082202757877177355482505793643417991852230599968751537444883793095843366622745072538584450705902974920120893743136168196012143761583648352916644176768101317586279795144820402787514855585558077236866247003187145754255834842885978772417958475172169607327620229708886387869324157284597967265408887820403697590122254749635455489427523776934474883255831545927222663842927596476385979172464647403826088452052408892818731037937748810449567736839249867388354269057322867161676904485554966996818059697887038065385348390599042106393696534201054820781902583650003553758024637193181884470053702676428452040121347961754426677574933673978231099869131519394611142091820754979733652205020049476826122646464811463761461130092151022766124253042356410193650179244746583769741013083007471536381341431250493358523785107349045265461031461549781858761681722186900458090608420342448379710341528596345420769954794104347209142603921948050039872386818614163138618171429081634226392056897564634634149860250172608817293071552122146624638794352438529090917394280063122707335993222372776874132020199397068887345610919130806176250581098622205924586971193683363567326357662231578738758313871605694266706776117089889505423526511665839023285520162209938336187411663085115448764432151351818941495526686014447839119401273280455189558876003719355169895027493713807942295874747917115430564525573372163903387064524616622407777124454944489124198448093733853891113626097210475048406652313394807743477046010560780896336049166590607064008247670901100159879935322235525436418910331279583342670855124422437923841715729397621294422601696173312138573955403755420951110376363545229249421537839392407382595661429870805569496875330995042487396877059988838857964858810771760684584519271873888491862201984644409145939199042093189374189534655306005957524417894292094406795460482297221528183470501275911516023735022379915839744381760772099399579255822406481100373873081253079947940173875820765422129987783362404343953844403211999874379834938769231205060641882149562433174451635597828357633109720809623471688792003544025354989427493037232795877674713096801068725858735443426800591171069959206191725339782942834809632889549514660292601546184635298155289886459250246952103679996675481935452671841271648350568151774302317797786711154851218278873568081843737040371504484747957666175411594779534859299260616511349081410575304442212321718909219040748912548673988086499673699338189033660929819013780491168445761860435516535834945081460228971136780154416679732460267884258924890568397247060808439113685402156724231481783658591675549337184121257108680586823860445700378286566744082440808957375702777978550280345736002054854539580540698614074354022194905909511658635545291561345894237968720136526874776807995597169416688877293166769186928019212277647714843602387848640442257759893564380916281762594851355230423730863432203472420657547015022766934393254421196030554156610823824130474016063423514624479767286209229409785267353454731119335526911265792673723863507694992002023898268328985814370469753138108969175357637831073171334761210900064848748954789119823733467425204786761098569047985823002435659284056124602524496230277541211645913058849737256600170548500522214078418496200448134936985386828844334002930325530455179125043995184214182284519313959864389858041470291548601441070305050494595792235041018846055399729426832434416603435020284040512703983653240406605960382463736609950522456821886510378170967432990794865136806412244444234964815893258660797714142840682488266366158149065981978437397910722754403984575791981174729354904298182180414806975200496196945341810545726551973721194879209720262044931206141112916906464371842252409566860782531302907394121993075713702474984447195876884342773197843003546779068499165048911326311580528090585792547405632358462969431328309815541403418810582858916361181205232385403521491589632137474198333122803174991084325626541953332506165800787792557604413338380727191285263431400161280000, - 1006180039043553872681311861333218727299531793319596597034380588157091734922048625692797156954960329261514512479715945782036831343605987926206022889483235752575072771149179604407502792510311051038993544332307792615542209870471055417610157140779504039601251062767009765716790251104620122289212308607058328253082176853082337819551694650138768729234606772866655539013336859191660274550840818337912372878575114818221325742931647174712587496045494817345805001557931601342554268665877859627715966001347729617693982657436742689139493392615191466835187114545656922278156887186651559799265964961114769354087087089995196391478235915202857573579327666180320139627582009919331772422183496543251067316036975838516424721658420501576346065355046213244652284375625062641112781081362651817311373755895467721197567759255583576766037310944080004529871958572959528565727233265019264715747572878987656610404383418106516036652590536598572902862369810498799557032923249300408744586841190850295455867966177445946502235071185235465519991754790804233720526327127258314549129107067313311696995102874546534299720041009489033098887467244061343332662784997994306476715007565026360679608426272989938533002467154594570451119150865524438229678436835806380909531846754777032623765294991941547364325113420819480587293172788495198743918798778787209941905996880661454306485580143635618571365955079904462732578281824903276975554330002109168758388359408078215522812888261349482651741294036373561494042593237733479175395989370381795810259358519840464077551633556727312002927565144164969493225673603112880182056081539521169339212705461923104571989725917934729297019945918602349152134322366741255892143281226084029242814697921957130760914391831316631810734894234862284761173325032577204142909281792401362653871306785421401559498693571349563629575543745297691226361428801435153764957584515387832485650279574865687592078713123632140076153431492691493370894445245505182885433813058125369722532632656627916691171707664007535262037432168307642589240580895687931268317530955050282220650813989009268434956898703142883271905549988918319677917751192507819062927623277528951172943892233795923749166131914324919500613114310089047100694816225939360335114278442024664157078462144123753594605343276144506011288687142006641486005485541656621180808358516620545085726358943439003789553964649121334907975519283092345813650533098887720373266297751993546997962929585098544064064505235251527237650183469659493698388126519342649688133286586943356189383355910672423852273444729739961984879419620790580528817087212449365830946987021860279939634608778545332978643299712311636798309679593600908169474550958561709149908043793929006480010316766866408583735347433078919424052191401254013265589683695451653956946333475963000512406144170673783780056376984789000018020961220387506451680805097461461761449808694979398280575349422776691886887820167029396434098851949539742855528275793255064234138203269380187985125357680583933279640613458839866227443520706842222319397615308364963934276779184002172001917001586919982897949463658842159977904641954007060195681700592850023845725711487695771744445740050686744809779298250132237570344843525841271832410308771870720327347571910676551415938478796507409302531173777926963201431504343107899758863850561231479866084369857292421561835813050154958929738070822264663286909217018117516305454362531764601585967755952736229176074345155132058464482362798111085030675683028771388909941183088661995984476972829536033078460014940951477666975230841647740742052579561636123556873019267899795679424580207554822742455412986070408682264645330483253712390154425149963751568970708881163062138635709956569124697225426148519511118127675375479828870801181103151022381116300536979936648100537311409137980548355792370496071217480248713707820063311257741195736795760531120491087128632580892961988104642997647881951321430925019620119577696231388227977230763073045180092700670779475920328910439702624178530082290670182555950386617919767729088222141390872190053068396791857045287577219196351294603659655660345674737727582355595658228586090873450956243372715281043034903867310929020922009419633304100467384933214177094015073191377232574751574834485709075112498902485726249455580661014269379087413334379058462364305313208212256726993549432467622443383481079299305450739102911496199699316273863607247741659293352543360321184969419701762835408722181570520953594549427135567868507729791024357227437020147457337604259162513878659895118740180153036510896675642324105981047902812017520248442801450582242640020928893002145049711259472229363116175867533310820215094641261988942794256462946674598409534348701957026860391290381816342883607059670916779725683270086644543074071911027419991713897380155295711037967621011747605557560730779273478819130252287069208295797382209626707283571709688881864716099813070911587223922471847256468488654937501329477491540119971948170072589793056860611357856526786519281938027791849934085493961803491823863035996408269431569126565122549930396474926329963965140855550078249341750187159856225863144998786678875432154918969828619505607030658209566170882337794529798473797029862263814279245297273568092547065460661708332729227478011177694212282701688566108422995650719240663549670430440436216203687489541699092209443154708269138880929412477924303643289700925328600956450054914097750485356162709649174636580228802630136189773044698975180580091816436014800283867398480324606173558621333040268768546382517767340433201303461441249351188673586048852940694967079298332906153077122815000976346134358967716013207062032796073635237581204286619447112782770101369988300758519333781039706066939246303485070048422839445278028553484797254272948555251123169317027177590081688328617237733005368362345838823324301502865879755985268651734226403755835819438944313957428561904329618131857190603225256538740926614878752052528628827046616411994544202391612076786886165053732154573335769919156441765226482946295181096224592256987757353408923071732384701087359847515707416882452483200469935442758049157252342336260674716957059563408180590371964669660755855088852175765234977009878625521496687167619872096732260234112831456418446472311321014770690112598412899395824707294282367297974219380254366781480756201075515113002712096029980370318160882650668503902244880956655045890492704724359849575593214151873910369669577670046568471743511206390362047600602982026466236026959215633444413807333906049172315376650813440000, - 4454138418649110411173839160343447570595661659787892678512550608125508013942131999409443152813964875130523323116585122407115051329644977199866510153594924820962409842959878382346980535931405285990384086948959268706696314004110465726890135928931329737955702281593145044833798879471437421410731089276460195030575201190329202185949291078936888744004683684598539069454481818624617200417927040361973854649584953066312596879450786259869026171987386305043048447189214419385354790289774794066961757188142349005312579861958850478867120077518372664571905647954394551907160344407976683541847624997164070134548428882945830711515286118809159751592677182769033180189957668816037507812777807332473574486281415271144871979378231981218049735778512969526178494866833061028285363964824969848566744713947324906778469614773693492659784724301937407479129430490999470599696750748377396670386234478985086802743426405278698181638864329255906372218565331384347110849774326819323632369502138090567344538420939982174351495596489920993536092334181275900646538628473883262255671137089538174435947541695017582469247993260405339205823320336785676342029508997601114127229174474929778963656621957549326612928202643716851664959901968127770952102043304136007120003287989824062696189177649860057982194432155477530161682927897120611183960226342343213227084869385526216407517206635644914826027742756651477664449789143920865056540885733820623089443916866108856523121158468448312801564927793864880417463159505042520412877124332608472501823127295367745596229381617241056716945614390487130485257826628519761658879135559898492509748096718210809761053635146964261543072741327264993767332078330641911912264382127981991548729486941653569505498139515553815355732072042578105092672435060497711364383121177267453209052006562417464722721649383430283516039860625543263477233405722229322366266631734154615584124185243349483640518433361639631574872159782279291252345754300165073329986731748808653444038447071378836588240094490643361115201286261232837637935017415714651335941045616633069783462391285323976276697074490214790595075401489427922520685177130570400631048674045390791153348074672885104588130710882979647037808340588012357545336395874071962289634921499432645926554048388847383617937084375920638048024974039332255516521320764949305461268611093028293998832626409184690553243083181343773747445348916701051139101379262236508181681307208175750596833675435558627426397927887787173593450936785698614215323519421265742807424193609103802437089492542923938162148035729600357829441889735262869261710840269008154321502915521773787274437557069926512612989705313842372389596019853286263205483295715410930679875434731014284298397455480106621905669344677890495328885716539188498498456782878133803852109236197063785831330267014070141494958317855432119162956958934587685321526587553185310002127254900274143115653817881221459098841101734248024488218733679328022516213272574850192321128831047673621561873894089167959298671610137687508969781161777893749539127429312109478739538643749538997760774156309629858599325644333662576166280207111806063013184371248693471231813931586747208313180227393337027479966529222675774164321731825657156680496259078668182030669428880680944079025237810224855146552778634749610070232121736485104308509278163127975001514675726823883980434877182699751595933121760906864470693574638720357142994132795871879085479045701108602702992002143876324076868733659136176996671367345876507191992069572624252670298976212409714387497185913493362680118150429164002616332178621643183954857086894871272111902146912896040656426871873583595995192121932809012343405798356151873241524904237094415479835680117308859509766535368819150648470053445592286045617278273101243488725569749050422061694566825960456106637406432199273762461347721316583179844471139594310426410233941686142455086052688254269705844911631463231651736540117082611907507548941590530174532486168899219166468074099320364146447226949798122014626259426874316897452916299218905255456318249982904487064625481888462259990344854030958823584990128147083819928495524189030404711081458452591618689037154798615349989043653786113113541708680548762758691987345809083466628830585634025184765713730675851970648849406632657108742219165543213523159019078898633108669340330983456649043603498929230458203760951868861097869295399918666173820809883354413826242618885958639256665752995308949289829212662514440417789674079359832303891632008709875033108174744480916350661259012804818141383883682001743626682378261043129367707702713357189854814704760971077604062151328668843064627679649800119210612455879800037335600954288174878211628481684834846044671129529798089286999343935976003154541100887362377663221296377164268423662830556492148661306413405435985529714771848733056615094477832730784094021717161785010545974563893453809230721772723337403374446386159870127531011259877414293441538894237127964441179165126307852556475152408465044878054384551091453414108068433716937413756970239938378147467177789791523284159719878845262879076812616613153667674978985766090478890653283270693498663555934737175011331466241724533221423406264414977140017476307236991714579060987063130824197087233854024716911437714499882461505423486669564049645774476040242680915832587181235743835679573312215660493784962667290437159598141377512332509790330380452335468458058670093771257720923375623502185151192387219961111522325148601726878566553256717125208511109849739107706044268953989094258166135224509697854994675118725228108679394243232383942555566938107694819781296715630100365959351837078135885783744696623613786234053620176127058221935003008988734429244871079900186025972371677709944580421961740501074714091706877517469825359875770763351359573005453308511711558185636943818746317241999540922240801713509050490665745745442911745006732540710835937629329707401838159766363491949134722147177448453757544103181010465276655959119526964976976459225034156956026423690097682604809135285314480373751298300552235158359002697567454806075275519483050529579764884245830248107700956805093052793903773848200754924473898204760248056827768699901146534104196280727060363013422975215127220703829109835802758937941505811719593470884308746214618672587516879315007447854622810503223451239469427895341132648414673409744260030484607408134007710290650422405399948896432514119460739461328404072655891852140587768916432598623206703986838473654356165376474986213628537713796045560872960000, - -1473675944848787050238280347110067384100871697430023439770274469599308119074186620821240474023096006729311292241823330193307713626356676859935968282997792605984039420496141184124993144012793734734216609907007945764605820879753690353738349129323769580526695520461901939482100552958136044991101046766643227195396807938043948391757674346945036118771472342866702056077900809076870647280214413486947109492548855923923782295455397697296847877311937356856696820132349351311754801967854224401122796783487710066355645879262335800875580004912112794587194106102327305853357804240537120476458451499495463916107244422496303163188845532618392510953784820670848918100424390256952632156998056892751070943998247070473302725357354534650827869469957535026089293346454468417611208744207453251147181866761807446012554321921153820792675772631285014318631192017855386371926953060682904359534952519687198023002627929759269187855112356311858658839342258434516660968159885206213709340463232016084199993240230244261963747988128995617968718616266184793666862906950668218573665306390185837444528324494925271637305546407998003912503802884751556035746796714009681391363798744843964702082528141896491867411564215357820758586506044558764200943323139275292212108675451918895533198038367916927885528926242217951406506201838153018933445198092349301700123323245648277125774706460039983207443019505788157216868844862450636644192959571183833665969324107255887043036091712523126948896224838701998609200010636859847036059216481323180267565025398476415640962341495507584847093794873043868996549526043817278530632226112807934028370973982943815270810257506651233664406220222749648278055928332533193196425331130417539380541948560127449523529733969192205537197766074863736197083240449890147348973389908371501085200850373603511744040541443871257250788135214828967541638582289598638938265648325060113663091650606513692858435137834274439424941326683249723675631641174493787730228472699764667656453780257584071450782067525702845583609869716058510204324170963946559117845733120036351740010445635851084327074798478786213386288986797117388164039787389023760299233789772802161330418089324239166656182350858139078334355565694723542579782666607823693921017650014051025297908500618819049259248968956936937457274876890769648076433548189663157210611553107861244740989076314593329546475694414809935918404069194140086683502506211746033047947243083070928468876042478757555430364103803051484488800175144706630472071934753200910314093031695248410562519222959299975502425916417583347725207397310551303526872611609565138075243791368885004696392852503599655280845867813500763766741857404568516020394051515327790601083377008545301884787248452408926693277510784638124941220457590817751020343254798008960812122073415401289064423357339688982692261244036160391792702732990954838484059049618836044944578617156846524419981492754207783573139509367478224828441584248281962702971543292026061347875079037834269062947762718510249038277454796776826487936810763878576868689561322148368543640450608299324398082139318591402847061463535403944397188023163956406426228798366170600733403902264876111428749653923473946407483847245770329126031642187341971707139276775384194897644923834161996202949308112672314628776826814441997207607714393517379972317969228768539536757204118043262952093538751564276485692030119659352879852492086777522447525924294629382988834889906689827487217973325983675321586373040501194521403403697974375375827139863165953882907310713914193776612999689737399544756678912831519970619911083873919806502844241722962231514566164539694727777878427491399987885659717166587194967860813007841776990278209208343700590124845987184623127631390570293116618840038886368794769701010105535548000881860337226651515550115011939036482435987048052480856939579153470172560016204040371222202345379563227329421571214155474358440598479513624020902986638025719350459197778422656965259315086359185081810990109855457662323502771324458743638361834162516892342151245495389164285677801232245713270513743556327172655051142738690806835282449605883877474684779689342353406005871116230516358779127192610768479562804313059839765303949960683746320270181121196072345296901698056593941260714770251681101710958171975283581311405660904636326772033694226766958251627323200452885615295612802077979153927107606928015692834168591352487655355096950082119573182636876118271975007239942414850624429923522066318458075851585469536711778707089340650718098289828789988395827059585169165745086482741246801302464665061320812098417962473957354244421674907539709830805079314913971034272158671139472778393357285910959174643836517313799367508761652041268846975369733758581978321260695617826048982133629147816848025083903646065610882228149313237164200268433424223942956156997621736063559325873443493764142633556739705035513435368012583088645831254473041615275080861955154938100022673010758581088642942007563449648993606768723195783994144142651353902264763726285502406148588151294906421605516201116421872877343737212637530930745335762689895185155406809229157624753694088230778779518071721685820668753066563542858812396137531694360199020936062615028316954677750388276095915566094302166523909310867044397127166109969226059301657620098981857366061264623886248396283985581106081572737757050363403436953254803869498470858503499410511386005103008754850194659844799472397894093915335737611354553749337850106885412901494691359019556917034186684294996827517291820782812552731582698351268064865179102918281593784648195604178535660329949667710503814170425244321346689461873534371088077886310866498107530018096829439116447749891659309590952700985607725766674223066310393143012325065819958971798075786113603840060096678518461620011819847727383390432360046456746012130040069727335805666213516139375512499065170726325650686521647218880475839508621243691341131376126507300557395470461618431002952045659916046099934108793392223027715219322217144580975223139213511234498389501478588757277188100406923461411350211230529391104981827533041192003213860412267737138320994725970425821429820752600733996222324549128629721322630386602245844733450328824722766449194920722481283034625985717179176510591039513201305237146781638593438482397085220300444963310901282589404957171902041492670679634932941324488262638447226084107555260807970407666169589589399634777991702515717859253563613120695006393458697577013407971257153551500561465999360000, - -287836432062934848701890232808441765459686404059078354366696187646062923502668355690234363477089629137266352310809254321271277681221341512835131682656691405224342687397406831388141705392109842704244511590754750025265198787587940152752185923011812701238888400924656538890623080058925772005181412115301759181954760516598114693455124096495991119175056835369839362251782512597468365620724366060438704047843796628687819071874698897324593517640081591154721312621017090742458903834590892276244259663469280247120025534274814141603935732399638288266023352411355200245598245235151671320808564150017561933480894224153740693203963087388188832042134523360216074255912650370456914241958106588326693746016156030086659251533452784345248312301775264623536952223034551038550223994830969281339346232860881680983721550591049240000197323277956583320903683596343145973851400114205353917323038337562258010864442100828690240392858973739422722888093985913302700239400908349086622752415823465169168401854122075846322428377773948284761112222363732090667740569434237458485484079412536173528181218918561700845095931262583696080177677328898260690741368429216030626237784957829830579404867592553143176467224554145728072219838153708444494304353579789798451053566220923124281373358948532093754362299611188488382785613932163629065913321436026609982412796541613060901561028870435447790620059631611075205569600338423372569584014346774104601781475321975507929490894049261678190849899712310869109654026475632261405186599882102733858549408056158532961671823750331786420056302190543936991328500449751929769682826274184150143978426656689339000379067579042724483947567041094879373082788509449190975496960879474931447323269814948295335154348164590017725293610077276840705080929659665341046164112080450556443573862496820666385022097066165013027473065039641667938743862725540246213158924483699419056729238792844053090312822515011952783166107390529000045582499933760056274970367461949762266853142177740813534850989007869690665377176260383024516181308704992230998286446925261378447930808697822198464047538221142600313057532890666225293804346517469812247926641268812736072182898107260033087565661091917292329847173768649315408490528779370533469207754579166202963056647097547196551499715617763729502879238891847395822868223625560002504891292000852126724059541536814905931396827121595141920361675663423132755538754407307830234158970902335790361545557438806209918083994470479075822511412922434565097257907669717823227514502033360852618781675106976558658746682231267280330346829470346500878625365072837385377566822486273640596358318131799593082227629519932492711083063445229955618981041408501571868431151820613932690282953187826763955303560862716867115200290248564496156610620720935170086490632965684069460595639870829303089634677778738481489588641220772614976106138979647458646242281844178153522690696658313684312469371237672956096307489564408759581935596668133065541765339447160397811833929008207165888615138819373652736706029365482764634423238615613979525988362283029549192234919294682122937215404635448370902630779700710493931358129481460801694647318378900227354660346534612068706527136089458917776268275112061696818662477558038251543889155810713472678364892357489439842845495022956876186855895208246952529485953735343765263335719358278272697301989062780184188536490179139624385567624313271807773519701289091539460666816882191519385685905457458897204591231478813689557524247660422060599851576295366483875764412788388627316540979560721841204855308464458067630949819335403936983608648815606199491423483424769538277433937219939662189885452358337580607944210050852655877140821990392731010905870186085241071218082730218368400935607909115170068088821515010792896766534487776781801723349821329315389206896464224877301032961019088096601138179749297249354727787560198742477938692592316096038719880716880138918436242784620753737351463705912665181020049174055436555433615080957307434065902247171815209055023203959277906933516795412103186581273839814816379997843691170400688203032566085869438492899401905983122215629614399580909298754013527170671054687798202107267104425471637344260051477202066355318861458275493372250592073904406646303230026010706000551566992211185800184829973136880625088729364448626043671117443271403915187160442522569298639305033554624799890316088923783187926994207599261512906915342903577290524868313953664000325017960889264627101061156091292396714107430425077115939676170847148017837392152288538895329361868290299282597785884760112545142070737539641515922710453222733371932438945202699979912111240168215617315186869730596895028981457243391513646973992970077986053946457850453307022365851074229839080971531479057282483884259347406656823297508060189722235904775416429795975757760547580920660470954121570918241476852623236011320528483279806214939052018258630964848810936626477203138272445536099719965987655006125147854976769616055601244382686508783507038631837032331091151609302685026551753707532320389782524987254084891460288182887669142012691978090570480565562577796900621552894369657920401703734578879000269114118718082730029299211449189836063293296652015854938581763838799747605218478697851631938239718239622472876890317332649134488503857207385831293105889067343075036990040845877002502607766458645300456256325362468467089948711010509357851590554050572778805021019601322959241305263336114314085371388524258356268381833565493679374703394198699941126255194537443360604027727323968691595028911754885334005479994832544302183101937913315104847499088942966697287935971240560650105956603032314060424082608444385124630722202769778254759801030577272494388574165600569588459768826311309823311271461349774397278841913843204243238261390758827738551458875546070258259001983271744427429158251492527023472913875729357506998793465358785075059067720648885508098577023779606446442329868200402129189514282764420058787347313989945540595848270985570958880665666329395237885268917311077335172816971328040142722165450753867115797146061272813950682599503555751462009205549439432027670878405011102899156208949794831118029332317500920601520028995431330440736882227082517415953572634636477188402392600092998415783009729025904629041290377794011607244604777895015359825763494029343434044280149454490980309228246418974536996696064753083874125823766069068095774563614822368233571482985840561776304944255218989604829921280000, - -3835108476030235165752848789471128143241147061314609144897590533687180425289963030809376846672167003801257403480558282833450098566995730692102013974078586163327176617229622412566148688428073668332908070670986523790629492775010783503567641692328664918285286941314986183283875128378984702985658805243433966816924823995716221220958694190887785966179002318693715244322475440331351520172397781862812590242781346445338163788173350230251995143542089490654615920840198713084139876068010002706665059852715627460927780540097208252281438703716445959676812947872013111465649420757790241009622941217664758535037213268356097987349666204954222308255210481638752211220724904556487922219036178259079300288474878671767378548863062989447090945325197361422360259722116414033813890298179435196522004359789402620248765054413949775874142456595821308163102437946894702855586961919753852318777436934240001304615178955825742151896392737850919902029256869252589705176248512693826591202404970321509296484480113564778294670611854386138130767311720571137772484709967390882140945744950907040169621732234359966810396000388636536586857092524884670416756583788225863794132007387114142300074520276213116367375057987645428908924473108289717444111105035291194100896900131415952478099426972707047991498903345165325140845909539933496099233931152429659535501683416416002528203859275425307576301561070753105081682237096106279113261603166646389644948224778242298435426526262633526943917062019029743340224429978155035453132255127628885404197755795855162334410604303604695149724752899412859952425356270537096982444873204810401409688249114128130007680150008816640950597960729398668566240410079843907926480766386116624277806195747631775677270216246679809013032404222774956740153081611423468243109362600474472481751198433202411556731217012467771713189161321388830421252525028905186683231679550601064543603045668648469610620420856270491970961058633152955161671759969310853507651545288034060822698422148630069166010489487096416831000543245298253495143440435785179431157202460848440807922174650152060968113263602133816039568327264210449683555126957288025990118341701006488009004380706619585566111061612670157316809113017201117457252884671688934133532886123748125819134494459362500972351095883110079147663890262260727563491322739422456537736691413022432173018213307653754050257234931025665929014305019218344716423870597443401149653966593075698077331146183186156067580795475841468551944769280321009927274200710765438466200750520125323370568324041871058613941693066111540484565943041074395620896133829887834430158363085730910298997157776299939461930250151281676574705996528130337201987931773176055891586752229056117485507444140097006943631663539707204293873477761116927507857402097329927788657596789508769607209492059129862886258915032186154641349071523490653944041407785008893265559974302839461788935872874581182970899787153440471754265119830623702834622031938892265701889196905957287809836578525991274781687937928131592501223560896444424686603679407988088529777237870952573391314653071184715957271962709027876540559853390185248388925718764359130348929544880762543631311961594260052110808603291284686929386773217805282547165499669272765937558797739772208373741674220328284448328632049204157122954165862510658274221207925761572070643941357846945082499507169599059796167509074531364051331482077735663362953261576717668823117721534014842996255839606400729830331747543265377240809356546488036333694554857642049308596374188776818858725450685515686503652802308165877619537180602725839529054125842074565647407479965030029489537941632544501871052954029324503272148747075366184161214397566630716015299802439746799444454229027641250445721542496997098324551935697287014686978124217057406823266651954141192698640811610022186902648495343144538039140331468543159914807633377500266238361698977128090588842694287477418777537856642734873000843985790866014820423310035799129682921567995163651370351191338718213715500981511380122573971277167764724591017019940531660733762423554543363098827306315842899656209808790301356735948977373376588372932521372865520220272296581348502198065721776989888932261994454561446687120013631395137732469349416960263169711092588562751814786057981104437301590380050785244426333069103751916948493682349093939655950782104793802771459776103369107575263529044370910115299843640567217400487612819370812546274702269063053410729879939222069772678690030210956572776360788403525656482482456123667337700447518671170092024546701347179717369226797670101614880942905605047831806992993964179045052867784340509841908967275558251267177422180577823444839643255739096743195406720581516188656058428190945677676684386810590835471098299449338360352928530689782443640927366855059571468640228989342783854169653470359467879559175582430879427618808283639034512687071501532404107870204693906514369217344220669991481863179874612864835647515080425698347108091441970903122330174307501661384485885191516787995438991487575923506934398063037757900476219895606173478905967262314720247458973508261798465638864826746840962806780894113891658006506621233664627670802525189318690440878880555395891651837295324243145853175875767123347653554206374339476125170331903682377115636030617638250497556710341327158048527382348822506471992625534516628190686102431327421526626389282583512011144232245147431421536860742011962544996230173793257401840119508408695088751158437908264063074684120554676026712455446106538890308482436781738222525525011082583605153798443991057233810707920154794428824961315582448296683273981332243329690093333173028028296265851696975552559597787575390391643093874629980091867974134966374655020788635812305389688312147728311082847437711185622894753190370426575164039689443268986078923576789855489919280306599394832541156225240644744868465149983086887149105368589373490078849667798516311505363265589412133684470524905819683184744200739656750685037948511105037005664370680877275887620860717746276945950021745459638852817648239327531415168737528070139604030852643666566956208952462341484650252829411529621867033338301530808271205154738246559311940825480998839668229005802015883560599000135272458538642779129270108956647996531584469523413708937929304615125557105046014603579494459419180341379264348338580809395006132716488475801333383973173229859921043933224476882916211953342293529721446890209280000, - -35968403331139330497965372145574645773095422458988960977507633671983770383184664764160938755333276792721662162360301655243448887829940397371841433496814495091513108705548868584816489898862837313777994067698155447711708475203352402479688943794841248226839166109019518921172963974475547773506101540123343958944413381901070631060557584846372869846733315401395386434244755231475846495520520809797890146512381298653771112117951965783823502066844135419547956466875028571092191492541855720045356451371166081028318870716618466681543393311843844994797098273767082992595958225248039850286743405862958578421932597867976975874270949211593740704049630444598097345196709066704780663699722782974501564323130921452082250750574850393882081883975946266294693792560649494673056521145293357667135031953107459613846216633992056909561562275754467861424195971271819163468749275254491209825986449449419133974923929860723017647981485001107456113057197539086593013934912676897474863284658723579456403691607845576795616891990492476325685132753891556668319268876777907076385235166373687249246712266518286652121052189743210819899623291340811662059782595371482046827920856634059554193381093555494746542932216663070077012172076209586925429254150489820704837740463052017691227429997592759195393456773065552035632223250997051565024295996448511506462483554719611011109988178894215621336443708501329734584769247486636562185785800366678102204921582634102546577551411648079397559809136152944407848785103203686231204932988036682083647870927984870429048311906715349629104519902939015301266814607246673762987488597311579411937500261258647337806279826674809638032884292742304427168028892629441690683723500540820474666764387159701931687335359620524669953317770526257487467046894072806679012161835690146025739318276781200045832782729389581055559407672690395496764585666391889399592594715459271404183970782246356515577433646020623370715920011567540698916659836417984911380122270148933008925022372743089669354677033174815424724724865250346251742094174276839166973822387909970538950380532988193430201490633429578094636146897157231388719773995841730265997720942992729844491957631453803477889229997138194475880015470850077993898496672775522827107327077848867393287757457049455867099196246041476308510779952122344832198519228643579838405944008403473144383164498729031892056756260481535801980141517952720950124928679385247924508283292830668615890501366753651813026333389962758248071633624365463670203785440520579133998228956515839728049659690592507123514049816054388712704494112533312993925513990464025248916282489380056269507190415495423544696572607264454251057233730217099292396605535729526708221168845104667956576111602679712359286982916427586473268721292758215246835258317632808378577228795946645589556892612336453669798614960547282776563709474780147523724445542892265127344497554808179970183209228762248658927317975743706864966009206476885559328411045637281730961767111534703129569364657946089776549249112851519485782538772152479990846710546290386308266860151969127295278127867935887372728329641721317376263581435826921753535975037944000840726701874874154276428558045649704676529562311279578584124097288932726957473468954770270387280653800580129851290348486892100823404598824028886527349423103017472539235378686015777215009059985075758194731751937931099419574475089171955143202688346793941643428761321344967567415300405083252156664164791678835917728538008605533314202091544126836963722748661486906892524596115749562282388950474426440243826599292358098862899793052843509253364049750488554843722823287646400504875359751863360421544956943632332749661475256764824159727914505555048108629031824801892205260694894874903614622539288869064598698726792510339382582447690765471317813560059176571577807983838012728857388790308008578169998408909126701382392481082366894412576169150913062509616632137569090946082663557881435425658921125299965450083140643293423251097568686848243379616552259879245699150799681174598277049318824224529782510789315638350481244956993073807903410616505515282009078669726693140187328289053615933615864334371568767242752790474865406094872687098832026678073675272768458970485542130928745751609630691554752047798260849545131760945126173522512083773027663742261109794027126164953449860084268885754490294782694509893054620805463651181225442904803627188295130657438394399739712075103265945727596193291322154168941360764953147225413343007033428345966208373577243301174720466167905079039366848655632103551272899934755803652320228659017192159717229139672267374056804091350847575392124235925377873544214913180178147572675607744104660563487451129173369970170832696341125759727447648274505387739552398135080351136244308118469746942444954209766467495693781053462031571955526498750277641591357120883153897078448458719353518546697846587173797441103657166718388569776712668852201360107788530405894102456069378306361165804580089654489791275558709293864198125717734529564308392382939166096189453486588019247179255041839417879064507063714534963075063674919639710973490053082422595236004193587341896552317814714965610114454291304919864270531159369802952245920673422995240354365686061425705038396825805282796783006610763677008284917466855017649740922901530984445341968468522475770621045940247761085643035534799592838824399475976319937258125948046823370250026959589033272671010206744301210046319209924957479746015750125277867507520649173414405986248888651877363365945465713922610403657433707431290023474707294527992146224508895176040235841098467288545142657485596680247841101741903572410456205265811492229330434153743846542998856114657280298204315884173915758724442302380864636298791496311090587132152124361528297748721152314950806626212009400610814351971426817512866963044419346549143503466926246965195767596883009761725102826720506290052810781504059553615106598912847321821083324503959797890115193981679080545321269246397279580471018785458546276699060521904030413387405197921522827705166705543054245882601480575536961010059626009864337457324786603471062995318197799312512141219671494112464945625291589706050012869490670423213981880119541846593596590885388031576724109858034989689813203688348493326505671167901244906209050610127178654122533165393374325323218994274004820400959473847309635036916983034356641126914479632704764960017050783420818391040000, - -280152886035911087514439357530824001682372368457707021435673848739811960516431226106264277529395018527777967065927753138910298781704698192274125198936125080870093248082953795814645892104143213038488807437746378012310236943591712649298568321124886964062450785815550653555624667051980494494422004361445092085560129532833345786917938478101339517505333315313092768195374123660265410392617647601141689794284393505194705090207559471141227240391255118546658756966289061004043609785988072233774054822948639085005300610044415995144149927363364460940459341753903071513714913600612026933028054579704182201963838217654060548411240090050509181640760655155587092630858389557772595278597587112422579592537848239163719822694650998518829116291049703979566206560912554493938295535520383859500300214060535872896889683446479580375752866035512304234718412757594584846206340572509215489764733240462414071777739621646671737680527564760264892440231523759658326737486779819377557393312803383590756272550882149790724338077307244960674356571119066974503126335137477506790458525990791340826149355781050323983149124181890941880229285652785980718690397587557307502715587224315599668367623196002915040402052359586674401531253099095977360436670665286834251972716757468863106545726856389892994568952506379408149369092862509792226912901588113375555529769667358101796552119881244230377651614920229541407788989750467218515087876932982136440106247842569861986419472751084521638137597179333116406841775413186408955507246115744903883788531728990355902819667214710737523062975549895075430140458264042935741826590887358252307022021098942827677098069627569639724928058790348661321901771638480003038086407816386276995775648006940482504260687676488300007854116197104574123358981268283078387306446213092952606878996049328353971847336145326824512724851427079824526527770819030409106521555854708732350479668458833475857963130757480704424838461779704043682924585267565330681283415051954927704762392752834366237814475752180031640929500008215216209192057580717988046641258400093584981427012974805388876920425652663480677621707129660312710705006491607444960544048077761681320886195338724776087771291798940946387723044083791501200913875241486157793558058333091695390317902588904209658815137873134878135976423473007573723525000046489970571183002520380336830656936126758105859236890823932950201337595521358622603409107116609047104115290643715805710561605056632329180877130933580177937309890248659260246129624852883710479329090940064019068343584644203196463349192620609192146950920143333149425085511226610384969565393920266542071171217505759965604256095673300187048734168148281375714633415005137088931269073402751293325430730632054671359096706711102119532114833249449197480117513451355871371316874750306487567123094272239369105985308102549448407567811327888324458718041955959106574308015696819770935053853239771085887996712404936332016331230430315662141907145506887565855826969988782130262905699247755385067184326401320991298782548007653178188854495611117572339125786539211828401297572474472484974754169896427862692013988907437235165899159178789363783676244716303136736628455442303138556580621168751597356548100941986584256702738797691192856176476554402836988572754404118075468375665017019127658543118186308721555574460992075839350408567984709657392210528986680849575306702133520790449556959255948939840394921519113944813966150658621856380237520204028540093856621709419579561068851991142611994806049264994716375158675016335512526517239298200093636071569833086873455401093036193165998077497778112904417317217305618934414181202995361317357977653073023084066311163630168330845180403030570999633509175664889724662260029077810927703586288145039362892917078689268147670231690192532544692391536761528854830885501240095024376647263972298250525458314454778930078042728871444916234500988495207190270087190827083601297182860705412012124758816995983376431617846335475064312895656049934204544364824549483149183362481628090090059154707142711710424278146817830301795101576485368888640138323235773580790074030989902344471305698764930359770396362955618573766896046490792098624870715689227494452858909978720054922106425147239684180386319301953383124226042225141470355713875849469389011315066238101531067385350006227155353302226312192514181523923887787151330885376192189553709003910011470656107950650536878230382633154297091262329983809529932732830767246797440680678777038425283924221378652673603031371137675869093481246375628418873853880395582275597522437824379217497021691520716756993768833405547857447260591370975868188074505190551198919342350604695460926076174045750999513623549139358320023752279990358629243912232241887704518963011667074455037594995800794804782155922615907392738220936863022564690347010011181256183959111221358182587113829473862076919796962660829149453114290738228248316848026900926925394958186171445968984313166912625130068440232706076258063208493643129274890995876260266279359598204583029646722302183710240482288198211433242124712370148283258280571870120013900425551950760034833384271616707456097579200366607195540763823921564163565683673389238170062854661085341740930158339312362686519768044122075894708316484829945309700678367507074376642506160052955588673011713487853558187976815911309715544838285941374907887771341670236419260048197611503030262600659259381846605352964126906648251663863734371464122931248108611013611211587359167735609214400037228522918417037249406697172155120364900895634168870307479228956402841700188004050804558494961626571053618045072540187391591377471118719658532214242985840797126044770952662045041912495428806159898884953697463263080732809509257343429533938058937750442086607137744346430294225509487140319345372129154186165225874786519435265671559391327775142309370287693730049827313930653390390265020793294911400050280352964950937656269652051200214274697457644046249053079642784555747147121191661801554187936328869046915775224926202850324058178994113953698947640125980079193757598790317256497224758608544451902902751892633919891172143380223523290848059575117039116882718013125372246002087778349757836660428805278927451625793083110019848624612736546763752690951013216498888886387954740971682911767728683620759281945965712960757838236791931244969478900227636794176518904756413888568292802560000, - -1914528361320367740957518741533253279644254977671539144509978745206316717197956153907423581011740841715164037469423469048772998867303717668230730711260123086166978422557553119716508855160408437263426722635542085560382581675845025867586367014946047189657342856022828760886082476701059506393697110133919385702859889866692548553459679068969858455770373903956310354839913395083033049885839674624168031991285521192158287802617415085733708515276329434192057165530023991821014280989334110995629619055270185165716079808345326648772731068895403926946912285532984902814974307904992713101358697508738765941445276881434177374182391286910482748381542251368570454174668676895317255660949049549212536989983483300022370224785194173611437698924550799385396381012307325173046152194964562057248700844263602468890957445597257378791868047527693721689368274120544249474710281919643928732658010577725555695521568929098425216231383430989709849501939723345601988280919553358037075705447051183516997435124684198788238449953483457838761608531614775820735115055373821872126251626931326563876248815156738172137947588321860904697553568649716369215943147979920987126588189269515172363533391987534997050484701034447567334354580725334365714497069223523896893989977299538169157262522834587499866589702786871737883979590307225994042271783271886950912564129651308130922318158500880100317027161318142705626038810685110844378810913841712152098410620683259851242272818716967851906438412429080425940309954292698766735914592673745274772324142661357855844826526889195966417431459065872610015614099818677801872239178391433946215811045688256580939270897740585073315442191927424682078472473517508731471252582079858647297775093877285498506667141489446916731521979978201317424599126708806797420893949557403099494165490739659085491316455633002416531407200109586862017230314385220066867356268128096685386241448400883727503310268419035239381030465438018365975662297823843141976201113329257785027562401269304337725301012865547421739282552414615955685897377116387584924632778140201275064117680795263538924730501868067284356559428069693690716977142257615252658731983569700899042319155455678217350837705005978145856651345445568847242496614435697430245092064492573541560991750874200063543707534547096669782512878851225661765618997700447782103060391829764576944002816841908047302246055355556401310185239056481691125485886769479987596676096918467035693732996786507503572749372563322894673427870096659457498668092492193428152433880220288885926763906892609951057359307462070956298456849763472319066271504048975636236977241175578285800474448839099650580893914895614622070486466407191422608663950751750058175223603447958466573665066844759276171361255269659640660971643820849149426658643206441121668922084910815295014238735471274075856607232297171684747560932023901707574180861992163879462882308519160079120684806771853629511387555823138674591564319372598125348183805904316033560001605430766690323955483704254699373033658509520607096606434830601916000696852196548971177297387855054684960854441782913927228163072134488532877545181064848951801727503453950853468817545281202165551227090363153834564223601911383029654301427650058343683123181365173549814532999893601544174061032109152561742986441985750151537737249346839721663007748856972336147683202182276863169404099342596271888550350947021100000264374928107610840535194725848933625040927420794950853573822520113931365969429604327038102005934175489767607666721925890532635703795290840777269501129186499133077022745676899101464617421511646189944025741973471167078628057435404646130688128771058845955435540791689904145659164216517648237597462933708341716622576966894738345939804908674574284602363075856920061825247962299069632018192683955704046126458397120691208532911163114880055504548885750484615524661563571275484410494958497919478066047361224643850283309280588010315779629183547440907721647268130417939980002467008143959322226390129500586556956858221219190732831747032099214777599361463352389689528652431172840353069801972673802016696333944318846558318567564981774550368257748563864207748526793525887364602160668352088390617420057028920471331714846528561677520208519653407674639671915171426877082457628295366981156164851575856174373429091633976056875467295444178056830765567420413842456873587492950761300009725706463409724184170084154181354578057551404139562346096017548445479511641776402483617545364597834931589951173027201160118752056324056935339419839407240800065033961474999452226169051734476640367048813315955250910686819938280818438216647575093232464522268695280669584344964112556707851500622209285935120055980568383509264664870907470526951806203977033226982282942986581950948901690519211362939879468542506955904941164658045079154410803560014823276123981571552986925799128379677996614010557166318388534847074112446003010721536865199343866693453502253605185080298110002546329939159869576692078940272341898856876388545500465155743777557140720248934765970692266247519803748683277092934897892156995229154303665145567148123586917402520930403128864841791584925525099041496162449396863019349242266163272302613517597581828578326785811811435132469969618368276562624947979370910813023092816755166563180716127992848136545534885475020987031626873823399774124861220798624017507883811091100271405559756707348418723241565645286448323658163685176291834592326493146948256616699025290319006369564279018391544597923663700075359525947091385406776950759271541267874271299109954262326510250189572731191605281118656869008412261541654318664569023301275697048491515210181343175347362685652923942669165695180312253194725941742959988516202820390440326345696134273395261106469064116212362600932095861480502517680345522947318062978957038624968309960254733496608093410814840306560941916616335420463266865582073780761220419033772962416028863464009186010221139186676553411288255779968560519707141475325250672916751923043969490506794802184212217329772978787755409466612294516711279817813026149846619315325231245907044468747194594998240349174917248120406666424201370170415337892300459280811282740763322474846321054025130536335224365169281296350478366777145877834205252315306682389636027054140502155830908560726470366584611615569929323669121133243493098366049531110306321960796160000, - -11779666193579944319533652577057256352964848005531601869768440210692518969561763932308044365737158703173193617108178395957637438693840650404932750607326159290781000338874532408370764171932255783195994500893137386542299803989417458495378827695900421102773168736388539186196797627881668246954803461226054589462408132851786130363099737502175300100995326026380497329636703852987847737002329240630614285139046815581245343651390441215800565416625219119674873834107457800848799480478284752577365031744508272322391919032814701456539148924491427432381180027217168161136267242470621156880954935071569711320923879785658589557801850743340910312523113741383696430698092048006077629682035272196868376722616197619915627888481677256025590622815148019903071142305290462992533511375573226376693495743360982601837314486693934962700389715553965126004663760148231574297418237012288293985836770597187592855030977754025393866493814953126448647572992044067187501345302280271073901816068994470224803391107291545214194836470627944533267150669890663861169089187859690647157740138517796194937494429626841928707174121665378433809200058288079264630361489855901623635769489664894998790624214680127917877615575968727665716162765427913881349576423860549401110034774638059643737255089135747891096906055983421035267193457562117599433286104064012247487474437692357685361047022419267266809906318795245459261311616646312266008637673688125013315295842771290992544438101637398706571224109983174869405840932422046745632279436169312195915855464561017927554685968061598571458924217180700480529118509878816510526992855773208008413702561174079042873529322082031139245107707237359215680231969653664127514662647666331092419415234006607559442418277723865223357627819158318733645929719165521978942194780410739149078153601613933419796071898641715966891829810699155474688353367686236691021706713255302550278808552794659281125465218316803833137168280090692110133802616408005346363291148063156121505959158762475036643113998981886165236069261120539034789961474451009092010792233922973229056416937111660455785626311674907861653349334680038073900012908181466419416129694377352300329405158312626320484459192400871450636244751153617174854914864263596708549075976882542921866569328996072852136467813794539680096506408931172013595816173291415093129822028397562964303875266951300899671006963630901837103809328183326458698909473483393449534665456315690985059980092007814134858860022957504521888416065461719501580705643141675333100364204748539755516449387225011994112914066690355961145691372006248336348707525081152995465743794180097267360065073667665092825247503964962434281819535700358359444451286508769592555515524950057136121031444169090673225887371208314633217644954243068670877048132439254191471410070234547460785541274572119434208896495899789397572096793196692328770363049697063081604098927084696408369545543817384105253312337365507431617541732317434689778145097786959377254047735677976226790284673897467111198161965182809112370517833574704825784989310192871676382412436036307650325721753167419661253140233076633171761951246741388410249038543502068730737177354291349670022020433984676086974262675052973917517043439462857381112352908558514474164979375992010874369404686679044993633662285838488230826554622710653313503515114254336526875069514964527009789431846545353784503515280552670772597906493391467510328166547739545679623529389195355076742388213662622638490150981391888262832488521814077873159967036523592581334989059467852947587158274288638250218662225366048062807656357637416202267119016631762586339740391150063102617968766985618343695947116283970037255040622460244992619054794149359147833685384502970191085946023440071319465313276506439225860706853778501386545806584669096172325748224735259737418997402450803602520927126710030723081264394805803412689987457114656074838962878138694105980980201495583264413133837538799880386147734589321555775484776182381747411356039408736847797021389991399474000672936706414019676168710431499341264990029420667185922544483188930098548976566940699344140571322558417457742860719598693618590789464114890749289618388271533493135881170446256397053982685729014384383046397362642482739205477265686562008320653890905011387578185230877484541344587593354646282811222919750294582123390723304337178726600640270076694398232849499807567934755070291854115736469730684114114086349689947234839906241386315144120387751817120559843351539513046309058386368268755325745680767628725169703242372401083206018466319373100405247969847314631428256762219499958767895797632600564949649768060976280195493313175173115090719707875960540924855857209322276083661840943748855720841337879063141790451894047547955606865983061079601163894003336374906254687507863909716855730950275321852822072244390769942906088991411526750050240380587980988792822768497353109198229058780542479558630984291459676460294295035663391816252967138780856504556689838947441133722171569766679345567462734086977155670454189999165815273582615596146991961321085291951784399740613226648691798828242917073206143832966795013806304976107262429420268624444564895156364694154734306569542878472775116615961433969593628312465890519985372762553468735367081676603490978320065758245857851055887429598381306953466207373554631082615822495553039512663632808135382246455960803034615410855559283977769433491317461122211821013776817559535433503018294660149130130678245742224073120864268411039023895203898487130981306677502118475291982932874776553234817824781553561661144589622970599271502347942315652072344284974042338483002225980202123978395047827609314212037314613551811717088298465120869217208507793194834015163751171146413794755581294726338033837385414540444599432786242813492602571824265916493237318787095581464015284879724761915068541329106378625864645250191503993723625325854311890763816497105143377368971264970453394400449165156021313181863835295070885366684886862386782091093159259447885226400812783302783384940148295852523045832830522222119231757668358276871429621913493887917589694486590214171118985317335066649762867768335773592527543325493172907547237843903791931105745164515888361187732452907298182900967435588915880683351617510761578953338430509462933025503306658237796867609707839507670279127040000, - -66206919870353852042911132877794673069208751222916675476451583798745882435470909440991646461383747783756844019034248782915504734572039910831415517857339119827490658201598577900161808064377200527134370964308411236862906157685783441305924283543853903271381781145794122026182633683655339962253444971212520855792420926194484683117768287122836020693115327718836062802934595699377161737084624556082080524741242591777364692865213813583995317255727916237641914155929058284518941571536662625001134446054102578523754173774506093439384371363962417727908027232180032009224171986891697138294630135062982206655489907552233845326726637949303588021066820745606274107836848363083099519458901389082463751726400504151480007916056839745683564686620390682699849140542010561183166299116416921911515902732112224785976645749819257584332094241725255286757056330442560568352913660018682594004531744604005900945720162532619004755796158096015032934273847605935062390564128206713589876493065310713079185883516704222784052880503630472940455432375427144498291288795534791191620841843582593197916120709351463069939636340492399365517736560450545541820052318119200776186327118696333648213663868521883625876232424516881323569761106520084181681052269753955597094606318788187745051024745049803165884240949113270842337646028787021266511705918201208718862351285921554593776857114241654323204358816938709127052416105849315170114855789687358181045836143627110955371168783498184590695601278780537735574533177207865208607300164929594253381044511202671539224736314807440624247999889719389571224134083734144158695550191573934003025361990553781964622878815296827765273861543248118239888669868161847119963777248663138980854658351915443475414368736235445261657858437412879304769549591595152215559322250572638684797131745897819387271678344272164602349734423764459906036080027500936318470677551762200581775247437571447949824343936501938113693800657687460530962404381760658034180667633522718873575637771001317824167523642878575658466065860675273353987436526196606862801995613176149517716727661198242477241519270913660940462800630585165934867328523424576831872576915611436863314625096479123133463542940731027539996207314492705991259520949058321308237159402268306825699799569744878797197548305944192898599093125450418653284743963152009481602002679671967780326285315058511413344850773380679844669897536496818311685297325998808360559241571256900396686610542806145095841292354875013322085512877069032064763293138686628075598968607036877865756057790991150026862859056674735403085315587398350930543091109089106514205052602695475650263351479313455761426313132314322178247696238477842812388447050246039135268221436816132166051024315261166218481098402967612223872707887491636651525671729580951980023808769308008206408077576891636627493735378282397472773032559540291119149365360378510303722689968235796554666640356135125273460112886901486348969992019326631662549678043194792534574703349880646788150266775394227960255394989053065448482178756295902257019163990825182390045159989406109226328161436748385211413870795082845685764765663734057662360697073493238408489958922335480588676710801204524513476009848627125053637771979487984461895777824946324038803183976202162643759232971259976568642262370584999603218845107305754242596755842741756311350277237254890391500538739083482315616803650285138073259094024292120399056531436141642519172832708285684706119917949302201685681038915740609309513587885910407860940534340783454782115071292317472230839025252108088234326784998684209991682993423862913603843447757354861353583816658011160961371012045681744244220255542043132642833132384516467779594257937363387971501744138686419969578435261678336274642914543515287305797063152516505963580441050768440668830943564880226572061173224721684905693032672432889563874231774655978670192464794141548095173127542980041953627039192371822156626172068625656158493988205454330691313719130779056350979632043051838626145321375576904928302313923854594811265225495846812381424366124410807353949053664843529867406241064844032564582926461108070856670461082165161919063873280998621683566805893296216415029620677452490902855172002259782035399994467081200340870252321814204693516114845733100879717739563234310342676924281511727469224608998651213698871715592033628869479276528117693069993139220460945628145388974806080223388665977873169832484664773499313096574426954014045383870332953939621922749323910147234379685292309153320035360487076123657309751065927353946835151300809390020088030821100713515513219860302944655583176155692914276440861123628509330783460261395572635830853273958034705498775862907163742883521152988181525217412831847927016214183712215188811998287803570667763115865772450408540666720102929214097436674077101651818012373503779658085303623113316627913352023620261003936438402046661469729897593602623520799160220602215181971115003498095954285537891123050228311389884913947089409876293373100831836115541211388966859625198478068418602777975481491797610020658728156924922365305789033516503164634216279455535107706769146767151727526213393728022454514165232486848429358599155669456023546746357794172017924468133081325328861332943818074705465567559509753838602986200373818523877515657270706995954623915407947436290832833538121342931902034660648351432682305706803152557009727577392813657767163301170342777665770739475975490265957103442414943377313624986289908742087450220015301443835222337782070147496613093421040501751472385109612384791973734885934542680508391549396301301924937877600049946852027514913802308066756404096671216896524345437738620062258242359859027546541257763643444177039971714055638150811873506516240740623817566690197974145423660145623722932951107275780292147599870555400819518269058866525032153985853102487802319098532038768140369657141414623498615441985503058575590195475124432866896411549255914496814076787988687304596545070576833278031065986460456376839766583872822544003411786417982811496719637942887562513699791677312345827976370014656190343412776408074737148743764531679212444091007788238299845488524871620585540083755694023906056357039160260048849054724003504681239255053654597255617542634572198427780885424281134250376296470499325098944878346240000, - -343014973077525821928785484540729218632060682948153519214701239861891357366644721464687868814920098950320453497002886447090670832178674061723145129400646773950006134168394069856875682122552979476356530123673170826822091619100415336361905674417464738147828616207792577646571258717394274648549948062690980078597788771888614665944210246587464150714920638737259247591157971741174462034011951760035462433800490377634744948137613455410222425907833494865243162598087794122481741816970470439779012098183475568062534594987710288191275776483901950571226519622768555469335695421835697087211305649762232887244563742255627669464524587924812752628154590105175252979311696676128044151926862907905291435820305461871499648674439931706699961133130207043942266100710494876570310612395263706461730321601489410517404560087868390225014193127818530281586542716332334330560810712762916648162104075154732446028746750185164490041820862863901857439132124261387725063107486146721914570525016717647644217365140743245584733319508111847358214625797155043331434821009361605050892996853053185879418162316418331984186318628610681555077839439503902219906186230735999718382886799122942533299871083930683453550612744026792149641720759444381260106137141078761713194608881308674946091071877617087722072315659410283550923967577076711766284712904830630514954071349521417250727314559900850610853355209783108588208378403289759502421740048672901161043142076630321190901486794697197155299995272705157258696924372339116758770548542514555695770418751345940297006774788334801166424820194228835241440830637494848907587344223765246841133568972442121542363113845091033483317727082864767851858219840701398092069597756811416625259043561229332814363006741480942842150954288684117557578351175604665942874974972872991748218959697310241330057383555253514448291620192870800956350035754118251170385125039978599851424969644399887247094932859304925002408032193697442186845633129474662703587587812883451910070019922063085152260309113328045074956728531439472309647051624091912241663959805454687481613674983329063074125815005773764377283200926828769143710615096825480187559154782970580218838701570904538122098377139291109567559964459853016195983764952084413276136670126669057602334937211136783729679699619378973974598982408725899911934991530195271515163993977127065784753242600451926982796196620417330218083472420885733308375907169232617134639943794341799966513254979708059752306491188443119232697392618952226202709041286078684763354310073884860468302549665286948077049352131585659842113918235417145267918918849992711304410831470259015646604602617233984316399909655345301978173886634821585337317561578233479990439129280044056511783014359121281014341167371043545544102260480726616636821979290949783280505931577077887121779511551422893433587092366835418898186166437927407379013338392673019511965377665207169454508971792252477351058256484717312766584707774007016997773105314370351317375009780264361535649853810830385487669931815217333877947427173921455382695841206985511136327494858043943865563452831940647029057231590490068623676186550379142219393541125627659415181350839126648770532600501014224788327740157685158300602484687994017830258343259332906582532575135906593778241248071919331787658617784951670603245056639172416536427566973813545179425986510291204470437441818793828863373599584269986070727846347948543306555102156487295024904867683303441321062529853367274711378914659847636559625143775390044543533375093554584184711874792320203148429276924677779575638306201017605020533265171204128233129627543760059214826968283774632529246589886483603084270169827353492220399563763917359698712139618945045755484148422573450912921945901197996767811369403351057406191442172443684983581809083141082633674542645198775665589405921454277521210320800156979771588421602095673179047476892716309839573182045881902955394615031463982423631922469158655050314616487871059774928534000782704786869013545369816028384746714880483402721950985947543265829957866648435420989120152810389829538940910832945066008604591569249868822331389359129584622236780225194129030795476039916457134487721227819591295648414805924138674542569832379148378607128910416256952286741531495671682057616202649780645869649345406643537980650914007480078777773353883143330559076809958365253369282063095719996880950416319397680700222236856813648917760435870393044316787288592050241031463243146448911784577848165063524814880877085219665966983896840667505187447205229136945574970937326134662154026681980280102472982185827914854711109995883158241560629444897989675437991480554326018343308797285559525882723306215161303835547675628963141155781469053686117560348471176912653323794699483155646862097030896817281774851600207063029361724974918257478812192773769163779820880195978352604857997813554358548008868645793825589599383503030094670617924960886028269452607324311965810638160607960672500580510663717095626067392753673664933671331593295928705450404328170612348721188068245988002038900360834595470072257982910825296375679714336704218366796194779494661919770844741214754375696197518895105089886770675945872568518803916985296400531233187151034189477260545360718654537263447417131971067027767483462117683943701981721172580507398041876545952744666570193181589492942446991011996334726775016888561346968835683305685753860187193411618090752270283240229056092468451848778803017399068705550851925152081995841196853119149383899853687123776302491401571836559944914900361269370130372802304425945263960732723278787421460445863789276447302683619861818509869477480680379444840399774773480299264616613492412790354335819093903475477748958962372178777444604809415174246314923006521667664207968225714253463998607263734985381059308142183511494407812667856280134568133459741668146969434361699994507148027981555938000831707575285312510613201452202842162922134857199267078167960090523637420392403395397276938382846891521692993815321514321161776125210107427316760114909805580911174705568912850162104545196945665074667612826493903069838659909405530205025014241310325147322451977340149876184689302512423927122932907154198424622566482597096110887768786656683267412839461998217574371982205060031488983040000, - -1648208811985240614869663329957301224446259494967021285115161174811897791581671450404439747862652965397346871809113678480450912471691386599648751027744784850126053624600225568110898700952282082325301991038257118703361361664825298433163376205290796638943047802388975711537876500840803561104215077611695717734562113020993351009354278754394372010763093748740532868133345359788915091012290703566738651011894866786756990182585208828440455110536457366036440963322709925378251143311796630476362634840239516128366264996630062958062849215886943619530069013734622280974641303485802098733389804491350486552443015603709768607663521298395115656973070696524027659077506244362142584033985037707742932693030742675414919042046030456079897740925981375342980724887792093718665262462142856635449491394113074899940241606740096989846625746894211532093599279840737275074901710374069767202364144571443020919892085869340501891286537528888332058133315594236048254740715160346753549651293900010667013172916465169272520977767933702860937879151867152172873836771691741993340097638962423629240340656783134558904290223746903946516919763549715066958119365863721024767885712218619088767426498872195569347156212393787417231139582426511913498403097687552651582251258818183328704243353517016409836533333483198267494040688844037857856942599077596448746462438758665843833358137880008609667253442357723073653941937055360362202593458068529374267503136829648618337746614593389460693943783020337803690276688474820391968866041990753968069436192019865121501037437712602120671099565197783040266613554800388012494558296858364978742816880115622869785738588512615818536479598095082537656688941211431451456291369685029739157448052177844884802018812213843335572225542789701044140871180526280887625867236703281668562787823844865886098793853970022075028713406480998289321145269901130271577109894675683072713090254652163136277263768127253003147187020608228603627111360138397001298094036261756763576735079901873473265626683874213610537482955509264689890327670205064628988713267228163772896784617870632130993148469367093416590960977221590320500932091239249442209155155197862973320354625670371254173703057974993413337425767078613313997218887658124404647546042308428708123842525981795568888356935018949811889584799435466836270321133334070233639727657918604330885382442652148504257805004317837052766319392892993272079320913665102305631068702967857006420586356315656365394690498616166213837755430714155748552697988771940450978383768747790300258605548676269106677920104579895043700973802228721161701724316009362443527127095533359745711286763983322099832181854366898445743306323800879456806206220968236934599390742642377285781271072025524376335800683518071106114609943239769674816518941419293523316385249580019466517631557771892151124498219320633160301891404785592969168512980392036227413147844517599478688619014859225574360944272465583662903173922748102653304677024949695432621597242987112315251087679232326003482755881201946848767994978306481173407429322797631498120864818154560339245766223767945721483180717746137006117352728929218401178687621375709602452614166171028075604077742353907760709349432885053857379616830753259004701509284762622529313813526125177168847410088096123395462744144387203380234442739481145662637629003167463303591860455154464047193988874951481928519191343310365237728995079244396173077196202469790790435148451340628872347664235327567415160609274291057497578488566996029496491085668075744122226224367475182665510491378583531095438874257604114359015388644717813936037942209948119706509214837045620445240745457309998790392869296930406490094982564123329297812989043698972409452117398480067844155405178354507138907825263274058012320861500249251389654738825312275288689265310266414521044981166726578855176339877380499038894450961446238352323571202916736720584176257606870090204251365009497615956920218821479733810783420237219967435969956797368059698200680728728012788317374492807025942778073457688287284502788056659295362743454253862486041411031705167455216867626407169911712189729651154978531438055022525327250768781076726537987699570524176526314724722995267420708760049222546116303104985111983343682951451940683719204340084400479651709902660654621950018473971761336375426004804464570888933514843394770962615592832576060618110827411637603418790844039463604136718702561424238183787184918884886982028131032205470000050128179690300476161579749612672931325868272522883123355088155413878293483230427939297272457906598645917317879341829593776379059240554039818413592582252105180036656653929146373493865456550344026569468053102388131204175558703990180760609576954030616891990083929127816455957330525807740308932400857317776146995283798316161120741248693472589226100662376107180049471123436271517311826099517508189979792609137102572315435880404252336646199322086923381583532866326766754365675049918149707875661203204493192369067878413016906245249957755161446215180000959688176355503136100510311913644056240487084917710088428266066118562067602881037893964030658943343989890853295190248600643787408033319042358295718348093248047864901143422117726292527630697287136269566797007947590496836260821925184424110160704144656959640609090416992454322875337184367786964453113467705603482852196875265044123763734882013282453949251289325492785908680864794465002847244130445256399449952587035487409253968592449332482599559927034860986632747456067350617611391770761194579448074269176940885274335906824808954135703230922603834178114989699475950996653111833205443991363631284581896807367191920374520111435896394365777864118834843049678306927013167756664023413572366101642967155255347345837220359694100455383874619924628088777543880913969224171058591214563019292054821595388214754893247604528784862438814747877674098100601271228322673832597709489541708452248870323606710534768274679274744312822718250534184849280717347105558284061435304359318500663313692502676630557318504465189490787405597545780461903510854943220796123884506907106561108337838826479365402262306341171988658307104404902622717659485329108930384802937453784498328381688538983593180118311707782033854198902517484905079767040000, - -7376901691707563421094893243471650750677071461808983722533930387202240761198460683664753945001814157468023308343650536371900812698414356785403240072946270460542494911886725034602620684057438710911847473628881212096307378413406360875854709150419688483458372405800277848692030456874572643139658689920268533763384221299671341771303831422508698177759476943735280043734778440589508570098899253136303794214560095488504927120461399794584105644930770784242410901566631451564610621883496747097166869849689523504637691139318300567723549155303890056642880362803055260374007744672250709131917577112793958425709534776881321106013766304121938337148574970188101923742425455333620142618821069651905010981800067877450827279644464702856949571688434007966113628137817370124663059701525736692153991577790397582789620407391015110203508455979842197404595549963720024976972393938502212587962579108592946533855988522989501968622964066099639954125946331279411327676798614036500558997620273091359104678039561305200250788951767808054781477492045946097340599930898276760067591571662091266986955682294950399537933446389365574984625608475311770947854688530220751784994359495444645466934717604266051398084983627676159891834875043599405176624762394247856262236698802651981289360385615521374622739715774038773177015930432909639482112540712337304815893514439679527009611128195302544481813460968362295347003013481878013165511316513125429928453587030775646105704460915091748608241580566752886997924179117269310157289147698222295915152150035834890791408043557075109151897337100288954674944131775727843184391813694180583036675509339854492435958024493707667339366242470346432852602766349067263049507221705213978645313958328460606957697934202900992302780087815835503065364320063620449121718107606361792747434315275791322516029133395579370737059002871514558891321943995213059449696283259459028836895695793536532193064222757932667549896729552872366810025733161973097375216288456476705483920616355332920157056631799925227515441099731235056972689734509953335262013098329937797027650417710661522667197864577994479379175593282228867829748925194758249090554464598513965503386832229369340451006368850168399720298507220905741256558506151803842077225358860248116799305680226669171777718494300598912375721450814424422664632440404161722948390866898124713476194831796457615352927765363736722721142041920935577464409311892259202962630577163234308618997535902244514778839617079238359171096574473518347769418811243857810205374333518035000517747987606345712280411612340178890038268257051920895127480147996987017401038579969830892988782629976117701025253803389746472664524031683486284268867031834174068058445596667644473256253962483558970645596904777969478929295357796181327942909929880840344016250090836057186626262181707216913520849376376846359959720405634280694054903550476172550169413341287701233825394385949882642267005926160124218082273661603778653547910447497458870286895333362940530703164125270968897090267783366072062130073942342797086764768953399274575836860386136342182257746494752784525797700843332524652494968097825942696440033829712781250078386741032969349708678355544927384255364734011899237567933062753144138739506604819570530849812450753671911529626737439971055225627431705498110752063223488382456570255739838811648822842422196821201996225933635842686348344345742366974454284300530520291343157032652599474955769748246903522754257692577429492801325085733422685687261348439205906115128317837471489402146238912405503701646658797281006607021208334343099088973553543811356780233056923561498603827270472395326514938767741611947343055187413010176170098919264048372829824862823832552691374617378836897753594539570260490801868105657459751467433326993912356293519325160936340425264878164195494635899653561201402490563637293759337546553102642414095770806349101475334676294143818751093018042684118240471886896602897029064848453016649206260467326959017310566452908466396727039997305424611346226449283286116490866106324685777190186574326292926725833263007095198748825988384574065487464905608948856403367903310897496367858637362057689027966308759357370297325393770726233484937996593663238622049884972294093012345077480261757110479930577906400447717582122307909138011112605490956649590936058908411957623945004608392255617578391320073927901296602225804772897674087544626416823681754661758300915234728867117753879392571846359385454630917549206678630786372359600085508635411034128837468164897667352085510571023274157492561176740060170260474143614009365752278460002428708869852482393887759027160630398534309741287397850862059063023673460098375029073381816477057374070722970538150408213926017264305894683236945508868525115050140719474616381029615732192620742672060342470170351109952782826541598362277836581941215144773048109242878139910312613783878445669669099100023851568265627423113628872978928390043277054573671304090307992375617314722270976099303496534763067532727741621945811136696014335181596626931883290104387154791695055220657498579397700436708979995316007242889773344738477071674922980004062586656745285415244728142090182811347842608298250623327480565634405967578844226961780664098451983905951849289328993041179039832398386611062396752669517665439808603339068669910472186504980210413780722888811621605199789366544723066740365851727677830513207899162727718993258553644513406844182696855157391031245410846081289182724302647896102683953615151811353212062117136952330251098509559245971151292231339920040385706649318992678755135170702817691797530494029869971259145965942193296935302538791831893612210742746289085970289511848090306605726904922677623058825912149462586123147074198349772513884464824608669426034632855282096212499575302013403696233840673597795553987818923703709724982509941512815562367577890722419038281735992656216080574566570437350745958355365948021823646558499782978045199045836558973093811191177287350374328022526020323390322011315658889677283445813265071126460128475865980858390855824483298716806702455400172084402179742427317570904362454815023437147004762248791703537354766094920009541882123479460674014767477736597047322460815360000, - -30850979735121152232698324040436447791537044314617353525437293082115465230104630329952669636364268585362850631112868643047258238035447485608193643621482908150502518944720407504770622535024697950735925821037168412886911676941709098046275425918872362038861123537962338960007702974488056951618414804677832875321957574917905685617384533290922229657288160477602866619845377750006526953234779434859392713339706642675586107311694784972339998262826557282958532092966588342629636390531540492673092862713784608906613576179765894011872736056044109731245218589357438397704339018430107402289670470193829867853191393402361177836694875910844705438419581698816568626748343988878442222668175314192890026382769885613053879838534578514682693032601221737432529538262405754033960819452370466379589690478512319242574904103140408422014714865379808709524427042887522862834511679104039717353786921182092493080096260546506483963699825462486642019468215432733162582428190636130887709664530890005624407848395568876860989387278596982911672537553190757941353373800731855476758588900269027955937839689000108619003077770304272836452814275238056570019007187237462047267647433688973017326137845550054908479071406818851921833650104479047177516357622523442032275290496307343432540805908589517528715470878047337494574568290571669958423262800678574036822239967015521001013094522941792990195330270248325020091443209199055305009044915000015977480960838364087849559160131355349508422587863147328384810947705107075229379138429720280866693829267762219591312798971754835217873025475354308478751104027130860008701373840021942863857844238937293987103866248513471229640687013353911679895443012935840796240140642616920444485386597358310914555505098272758887348582726423312393346045482685393947851466264655926384861700030857464500416403603041799849706803637846924639975262295431274290690785245724068455797658231409204765644736299684998632139649403323904877355020381580248148855575896144243727151996360023651279885939208128451309960464697758599149094512449585749218647565186400932403986301305322284504532799461059588813857465565193396250200220485805841483152744263219263024794600096066715843173442387693506702467021801124202715423532353891473648420589570503557459321387773462737635602803167673113383038341751946192541163274858726928274090888035972217014300084280171150250926285392408371656706478912422246605903518840531631445471061183874578559247281508041086872147545331044807422149270201105388954827044819251257809449797132325298984505524590679870819132464675744738542041147858547378310844381874013467790364651953836748917726258888823103534180020483540704411567027026687990440284639636546133258271896288783256638120363112803419510658322969482506559162394927485944280493050261792658052816545190452216275286118867077951872391012441700649542031594409350721926401819509764483090861276144850058858535603895858535019711701923714581031252977246792625453946178780703888252359686713776805804621972656824114592745850093319555461494690130023586930945509985139452536364447822892206099036094787890200849513962717762919979086236827556210089824183742707486543869677841727422858937602823200009946985070947535962391937327826296045129724774428963438366927729338636516746963717605788068942559881045736149766087932624854396045705787564714448293542210939960934069132777497219708144121855844258881094487770335860342918693153531778348955498631417154703106782239499325130063782910944286555735160842171661299270795065077574447275544122952027259443046646380495279527760900673167997795128805839443926311250841761165532914248590981971670627146655216782202473586342981988724040387559620909420003902430263026154595335154478971443732181386701367375340652774713337140821177637872133965932840811343299728667239474517046585920821216520193452114548580056303965939869580224465314724462351034987778431294326582781978606660874873380195016023653434791727166485901807318944315406833140588611380001687203579653505795315237987156485007107599695614424111531470344486888312559515371318522875131700596002128910832581308865851753896956827659734110075869127219722459248676754185725374804667020586556990831038873187853666087969036484377766950381081151761607143725393665751789996925909441161032767321996650656961777843308531848197394110245304153423744511764439916769315133611029538665768109969553380988299991344887981802359355890932204820056583140019067537991397896105395897891258573970063346096804089392301620998932138000166259813046635686705463534385962198313447331150625724729797865931715911656987531618326040287055371886289498589256455645260661662740464696016401459806875847556589764369656159527700063179403424732178804681568857952730787523813607482416621766308057066905946589334269880664330569563293782051359258192588878594838011273288999101148328383353359664025931067754404892074492022421270741015879538818143096134244434527765562667789611745608895183487569040595221134050238122909197436278584078567980751368214578601291692565860481280883414379079373567014017563369673996702812707015197063314233361362348633383647816230420951084141483038772109070982438010432869268260143882190372013339519553867109117550513259570583925030364301131332189518826946060830992066637094755676173185313518829914075127734254184831229136425002560319239140526145254933734454884360300356514201653812283325845657589479346141908290650236391149379618785446407478253972650552161683233739984783551884134495816675055238061964475782758049122812688202095416396031735978291538518652911257023775090032713273903627076858305029298663951080770070961373486120993868595986411038409069977220500165039412160641162865262605070298121055373635244534764757712867795338702167630081299315166133934010910210674083962780769586079109767476377861534129186917007996104151463751950344945189520689093889214447953589157770977405072222506532445052814523224450833925258036444484577767851016471329235850379782777710451048009503572702639761273088424126104645870190231128375208223728032574733501256392501499899810927774381463038917266004031540443908784524549533854636036547486505470351974693334847690968754808768430080000, - -120843719038352191961023915493442581097206478683339483823491141390823485476784842806875248148192819391064982476735132004169012794875064247330415267896875927562612192109686665925093125778930821670372214682056579284445219963079694633027490908362923245531373121024469789036137874760440703885924606217109402126377912812833362137479265074633864715442763018748025861982115527713487287066099568758206786867917390849538915998156269606769179226802100114776097717446370740318668422535506828880838550532188173659988007929286215262101478831276102223058627264002589383934561368928851993027488704277839007796126868057650446019180636768881286236311637387816745868731109298399659820550047282836949097268382096522188764144939924416444998368100937656261030917036018246541953660486926841047131057843025867000781675335077364999812899363551314207885055066388096866384327407732732238634458254719219863693389490313722711471167406591473102272022479590638152381696310219175165073557436746087073558923346045924457231871424648804003517318248106760179646806466068110942263520949292068313928953187415032174209618545860364504334379769500248946578490092351356698394523453266720567484509446645672694222162912110405893150068829702484732170505297335080046533345491989209180505412611554885588536686734713771815400796089619496673210785550635430466855463432379268340167732721777236075271632246479185283849113827446751284251175800275531775696601829735948305511195878514965492315580991563522476090987568634858339383247807078287260896384371266591766316043720906184772597050735354804125629789009380892251543459913931259699151405284256989867345893382126902601386343781329784230358585240321900869429107727205259908806718918713586571647258293342178190511914586252059607665131632749986642065002559183312849789892426670517236818442261147282641875409798031088945481197459048504649970012721802261279173810566368443490574202329249846121246230398408520513408389501695540535213766881580341323592990411550308395593159912636904027230302253894876859727151625527533093534360696070915672570740464142240781081513299522077304231129936303923410333812162103436445507838572742184796663896376900694065489757780190034157571318030417843802729682368856839657006337992715332203849841620349287096575321317422347838777398855034966808131809623675880246671456114746597075763018323315851547860338821267967990584584953233955222144276544806858484776279845475193170233441515610631468995356898601573626383363490440745927410586468233492422307700380661690407049848330271487801453971950984267632927052545134345582082954627058358185745574670396190400834326309932845309465116056231453562162686308788548573843962001036571608632471887255056829238466114153912013340688907018192371404032419458034391389054142485212796884573381113730548571291640881811171773924055274990640465697865182194428436112820418645745874618390141490412755007552884242851561632693844540016001237500601494446342163114226018243198732706926343352014540347565360721221807057124720959541208151168162407453905886931031648542690525856170237475176189637389726050820235460456979402726716098218330508517954256657160568328578627240320342651981819654405879084029000228624641279871215259550734969684067569817150901164590562093901709397403196628228300360400746435618529232763681753501296198857193276976717759391258564452609325806844041584501982798454702450036527693436775061979815339647994143431048335798625210552920110548192122548707843742301827881295995603072390447492215280556383900291613694877898137223020526750452473721012646256741268235311383555237700165071574936542725881928626860484781882501694813761059510285705897602271584239729572307200986060026590366242538803920459362107573707517315311405147891116034848889546582802792265708272938806991054258402483656649438504432412705871430822690500282140548429252801126660052931203497587581833816909616199042542423454530545846530634643774681418214832767540327446856966191159143945073096946763148199476895447412988308210113584303099769246917017221743250564653006303738298696009266804645483677113735375350845084803548286413959940158473073997348448230115014013946483148662779177675412666382061652956059501072184834483035924244092233589364709051599036933084888843344755755421681087017025435080998134044440127433831063371415139911922929671150662752332283260439713023546056682606705902508669855154557802056657124535231529549419676918536354352017737409370790837253616181514226136021514483482496219637673774419282004956171638387030003864600522942034539029064966986989014692169001349364881403007265238653561346635718501658043102534656901149094966028713001044162169137964749552979467124977054956196088811690579322726811257199194749072547042317317349017039977742692600178412486470054533527572713452873219781180932189067250467794283499767068699850690554541860307273083481939313136089906543374530212012335244317164177887622336662420052717859625348404893986185257346445450285525622371653803178656649541031028668096631821767752350800342902803202883918047787377238051870474803814083935782355412030277848137097980253768418412813636557204783658316869945128822208662448149878861120935762230328635981275427998318257763468154735858788670711570363931624220980661110207948712098740936734966771887027069276959723405097110541453947648526370066782042615936731719460348071418472545781542637559583340296619794315154945115000492440845574292721314410047493060243464775397232773906932632699427313321831279170511241767421107154068399482291538934812119691099239347459140029348773342657685414906740940836812935655718293688459708922062601202916434544842941125975380386608014760778919134185164254844975015042863593444610437541167509865092058817617347733249523629948248332038460505472130897344922557375089233391901401284466341370622022523910806718028990706869474772592042585821572708181442439737238398565647046837326627936150374559304095054323865002974976876861120884175346889316126097790425671694369131092568524457651965574654429742264259516805871810631439205483850435671642509168279184914646518366210902578772949709251579796804256054569420718080000, - -444140676675487162211858054489879825449992775959323895663426188802715547270423040717701893650997784250302627638012982962562530055677175388089438055709824382776055461071568385452477796480027458204810288942979816656194707369625193953005791254509511891329844105760019805602252054670444980946692858580369250092786221668031146009055991947523544102336542626371580443504109057571732992566783625121273835757218750479212893310864451686078356636703541711188567475501496075699061771456339271172262117049071952450871131098389992409438490411971563342641415463010945712275044677144908988089561110547086153872005638496671161435060764368461146518948478717379315856119780786526423907977368281848022918771772107043185803311610782681253484736777962559879993058649419190597883541481532339260280910291467349603095359401090486754203681335142260247669746422951199889370054430922280903296147934896954986304235322212439179105949224580215160131951471214453454647808340148298020102948482980957445909216175234037861892317620390397894946053006722106516941594091589439977502990486288801582557234588545040976140315349394779372016584737992107462143090317258172752362190051108975670266706173370539042665272380266154242761403539555260231696432612716871729959379169977101519166492609846506113396831386660695984458468545989230743081039935134133216625022905601786862399013240933455968381835234808637690137013735075376830263008614733449744786877589460069944964904404442837751314386121871283026278862799509281429302365550363987402898755029487995058590625966250407283433867642272020488501824649802337069072033233654075050951344428393184826855050013186046199048922152670451455074411106538177144915913455126939197446854763430179514478141144984429121580836602020108197387635890660569193430168221738267364964238508638354362460550166073301293856661484386511917697285433099381831550616739323360504240683531040172520523263555641805711454554358057859350734362103050509025672098896003096150037132433093609120277000962911920195643936392859091895305210725922010831301203863610202595377239805164987710124298734695603840931810058417796568317451636092987593591908945462005644111507932123113964846136976246545588815045549686990718684682911009474370035713919459479261682537594998932743403510038118715311351168289354970907199261179608386975590848841605147847505764462222604321341243228963251642378857348179359855993799713544969562706217668360531259507174251413562316945107111884928654854720450630461671764332113457711592599863220310897513706400688932489845108033785621948704536124477441602072747474554266083961201196295827859125959582046776790849359518665890626478212294284555860121504159880683397031483791160332684014052559949436677851363373538068382209992794398205582657698505721003964963036863645015338412446097040559589155665965093392738697671207176075705655894363429669378201705801636883361058481870625377229915432332923386091717985243266024166348391831482807824547003641399926236842525229283695719813245833039310706571197217484369715405470478333286543875013741822594377861574756165161654951725655743711931632940171761006825543633368879007994930524755326619807424463173688225833980296398971874629656176502267140340532601879045912419027129135691359325068763738524418416510776069271951898759940314886049637121214965855183459914859402723552885023464039371373232675626776759559996525359221609369201077611302881219288251426788404321489502816484566745749865249340975426592094970167012991674540039472124318671867410050569298119838222407248554008079380404648899624475918862585248295362795407741086686537424799380476078491032109486686335082915068062315762394621619101352299257854903461168836232867734973168518845505403141894943508867930081431232326568824457564620036473891822572224463439150651795127035475323310098694657691976247892700232471206438587996153348425255989385668252983646513977500482481631021843679002711323353336864932701626205306456980962562711551892891803302219104366902186491972626775264172709141082808126079664781427367012503391769327047277747735967432366896840008065450688935915757019242748644813393819010005276442483842284739731418501518213694202714638601123578025414179267087326384276377588635839830537626258296936422327732272254220528727756465099773317456846443422655498143254374612248927479647275075369166475953971900142592032462748934198926829642568381329389898187040453597275426643804820036426225262493682593431889587720448392259729591983190894937232374850270930776660554381400291811378917510987939711264359370972830765030125827615930332260768690437754539041013734486619412017990695259166292775385302034449730037264345306995291003173075810425881487505621100094278883049963286591239297837911552185188471075575244759111749277320007818211128450445410689635781860999442158447744856281297522393878857917470372748861128578020114333385427235701935878253150208835512116791443828496746419539795162998476309463856225857877582853568034736251417315375985632248622090051253088857909408435875380858674683946707745693616344670354654178359312407178295730104084171049310956008511325295069853047862216558569077215448875821833252028438878500372489246929036824398962592527404243930568015543065153448481304258810555697667399113079874715485516439758364867966966253183229200362408404989261897501135322181115421372550276247156359680483089652784164691628222076379622952775833909914586150535264717313315459845662019911009743191029622096303319030899865777770145743992162605370287205889511574203494313769950103133281155416713197164532929668379902424847667230710060687468501321076409372768960899446348093492859331441543923374580642332490892279563273972640827910040346662409338839374484935276659160450270341854537787093949477190732324857637986911927359241720052372794294808996753068453115137464691703127299766962295744306771311221632839258057626918669070461107986076804969692443411537798384789088873030494839243249412531211749487858785503546261349089379454355406349135946593412729392836676183179876731677059096409279429028597512310103207998283088238094642374637225246720000, - -1533758827826593795665387406897947124078304468215015615043569525172824621545538793115945042590949802246897770092064825174562511985971319780195673508637110852869164664805448119892278480492907618247475831717899147158806706611656639637693132859589345971364223142945597865970994850817827441227353363958127504514577940510424029690888560747111385753074770775826615636919868078387427721968362788269840399101702081407059192075557274962094820375074605112342765489132987452390985305400484118345527566696466634628100492330478207688119711362637549455776494929000689168978509142061277456478263432951003865054770932563954048085685243442431210969323507555203063698677715580511958383034551014457451928394148853286873304028592797008224709424959205121567667957067417997356608445562081825031127832492027374074079532806032760363281286106564435388951418681210523586399070261259338253742961886938803779240454073651922919364139601372151439602608051797562505810306067963039074283139182217771912636147023254127100544069923124800300135876450857539413301843962575847666870056698721474615532853479417901488601276505628336893023621813037294790684169908925159719544223840235149817897724062433141955336773858622566779410451465933782654664152289400166851021104692200140257899822654749820824015298123109695996560775493519943739026713656417528120373322201693800647855990235927711953301776157454060337381951662962706158639885212707323219047105914478319562007448660604893593833483577257868777502022375438975861479984196749676175202026954505928394458213583127210898042746761007154481428065755396012823084382861760699307007333252601526438520268216079951130847786045904895045846620667238469513282407172420103480865775213817094701919756402421776715134326257682780059544417408887828135669119616653705791161913538629314861048293174702694382411579592787438790739661771144746797589825467934555157469548273679842702153741011956806922048980128859770183341122259914773409444345942186611977727307400206058126622000440759179922361720528142870557147766905493754793861286499383077392101125545759456167721363231401999690357459148523004925498956921876082664561201901488554506000477388768728668699582788358359036347781958880816352977298138714643598330362148477913743032117301158823647237050371695123234153814526662983127572273306522756859762047358190180301286616051685698578440961273861562845688921391807933177943414457595987219214711946700021775369144289180906973493248741309243862962130596883835606014242374917156595601092218900430657797032089065218675595140777108265145726148825718154232256982954783689411591976319171464142555221533051575994632991252444608694704215672798869333773559775988755972872739457498545908238885977015451574979670609272725653127736890550912699267903442860163160907105360185581409531972637656724772997420160213112091255492540386779595467852467419939004860517289309316683825865796967152089192074856932219366616497047724729206170294215993099725996522438401265985691649390127409599223751090057286699128027407368392937592561083710556472050850998128429161057893146760924784120268563030449286513893306841037447475249362591891659181972613262186327977377314157680389327389369365802208556192996501055653809310728372525284870415378416622335434417381847084487935055589971774075149525275536333573896749786511829684706383650918088808409553893624259353841526798325856414801544547103581587625237641354295640834336209836679359128863389645964765296612871797241592038770983033137164778013031109832818893917007063666843924636639003788848245704682067094186167816030971602057170712906593495455916307386304625404702934357435514594365777283862651589889826918548478737856512758471675875541729128988839019707297792415168081130454535309049282636152599459858413946292317546058033655969779274823259700806629759345497424171250385159078893868926193979241548928917709678527324224578582322717987529319116980379541134252704390653506937050173962704213142154275902752161229462447921097939281955305086635828935588581332468942933385886236247867390220029204656968019578419816987713915269065458521879242674354737349590057360267723350355135588856638188440740390790617495300806372958767312106522699374774954543407316079138345826792465001079798181049460394324589632740541107167789128218339090648331089583073803357707196625533764060528404790725225198025028987580521029605216213757163789907814656160882637524246606135480694705101074484326308834214876688755261033866790227294055861543276153789241507837602637162303478774508785819753286473742162888534701973932730087364112996949820034954618545351324901427587468872041782340919080903329121034315168329794289516351281055105486326724120168943036839278659544994502970129374104740633923069497444741184483717718157625473319258780511828073138200997435596472027524099636186377546035665567426943339174614305994072775184531837825184566923363840602796752126357028070993055447453876218339616134111264819559278881047542781264259674046305855059936148491027100945542321895089624025654825790720242711557261342889389021443869820554667482020112892102661622983465002969037635388874730908035902261472511523577442301846220470014213578045031309072020720696164391428963366952271186077551925658827235611974970093351357275982275620521489535822600285635061556809991923055605880234238386444031206069912944538191760820969144840245434158882054426786477932529099645384683234970700967910073127612778426797157193645404588259173719896300538029146704414056311634059500573174664709787259565256112162629899685489254934741258380369636673018470239190023312405150158452683320862129242951054945995401883428780926043867650948070415956949627340699454930454872622204110068683095896995767381257088093957044579057255648720431541215041693239039677094205606293584937018725850012704240547367353592103896598121048448576700526964248682937794839619157725459864669932762928248876555843981572418757484724074770661497235180649581077211430892404493270519253716880107075043948157384077547315253235166945357577766799966964415181039081843823867649159331840000, - -4981871217553493904498113083942798969225275257773498481480912597393284236854792650693021187151378732622191614513135895371300674005175079415093867494777313120895370398539850734207858442375522711617027131604348510661530817005637661964293564380096174098376073625971123068334144891508495276221986572323538882585451259062248555585514534187630068130777538461900907049971078851461545033254246126402432999488495715452169314461296277337754400000386027857180284196042842967999327679180455280035373907989864060520966943217947997990582107594812606934800504232034936693974280946494484822041790296739417364757410064809688129594243908812136457806681276468225127253228281615275464901133889994356200777430601569766655483144039596485391271580035345360939555697565265677155426251472592169775515163814075556859513813717415726137700641981190684016469955206461937228978004667343389854810371320583484522259068567148314864592749900312962017822937322404455588669739811660175130465166729149830933453234905438160360768846047355630651868229214144188433929167219867065076381816520468374046968389710828361563625031615715855497769889530471117362658426750874562724527806398846437487178720903863323847687053985219612277540647295686372442334215134132342684005537028107553453610272573438118591233185505492517988099304854819915099829553827061152760391302921685628090941554201755392268758227728659438210380595440802651056787836726350744062622740187943385578266383370678056259547414224049157586088304988415719135884998460184354765940129836320042906319456639741648773284251192902638202422797111148300604868517681072333502305340390952998851290576689096741833420312924273788699096571928739925436945014452238393787290204288825114604730180665808416213312426164862419069951911263346442856516734583273431413216329368880254789601547843471703244697283371753743902589791504918973249479296418652403087013774130723834200710722003993759228575348918266928268702123188216678288324920087689873565075786647415290227079976489116940260492064555802393965471103122076195330338111606730514585440366385404473308514966053136585793523118473843814925540661344439477680880165452483954381921912301040109364534054760913055403642798344531424726221984979454048069722836093897219607891885620784174267433303468256202054928124171328078445373365578588302151426723481421683773443915356183472498946281392025547393043812538737904037066636029734258459141417624058330853724205025244137006996271701703070518391167270462552204440063745759791226745502601520287638460629413749704198834391408598335950364159975618818319167454386801726620982815312571930918785521673277086642791959199061459085378041244355894439653099547900969125906144927772579651851685041206669755013677262707428285911147496420082335654542922054923503602685055704917191187515939770118497516169229526554063035138067159492671945945206354185161937176937527160068792587557283523995963309345710042014577259280109849426462092594733028909827506046403240978458066407410277789556569931326621744354579733201118251059887499007298177025525193919252190807469352172080363555551210371930186506056035400394076631894601349311919704135868700426428341502552400689545601051914164027947047271234881952136075119318869909360943103648087517153654112345457446534152232721192012230479047637036974637847533645800787972590451396526520946552106367124576991794387302538587668873391061405336338360357442329858395714666659943579634120427340987193622131713081558489554211388797468556711850452018470080415814085567032817223769505458721303744967209138989688235281485613442520783885142426464745305118163252652165890019043317001822415020302251373265175996645061564621119066255370719948345525334672611766569312221987911136803387769787014738932435729676410881615611811114748805346425161414734717384879359460419704521207337294105443350132352165532332197053838798539570005565486336223262852683366053920408818817422501690097339120966613642917477693096965997155816800341187719547109121724474930431240005475422375812515218979478490703954611547815615246610977312892931319121393974983125003085696830731032763974452901366976634607148036691055475685452636924679530416377970951814835929410732457551084685589575957714781705032129159994065031945129127432455756067320048523212243433245776346741257071328530084270283045929195320810438841728497937813509568660363728246791570425567276310938377017139563644264071621059861628133620013674289554847971658662602029804151363121751174889904900118612527106925761239157341731400008150591088958812580861922031452151180569596421355977457859479504536096463949616478049476786018657732065150086607485032449671289244665210868243158381913721718772077468799018994142609117163294690845766474207426052660372790629771052165543355756304796687653004864132236983727890293911254519842136771426576614740261959356985161185399912108911001663317186968446685905220982901995758664449494027589691720622083681598330987086613583332507602331382103741066952882890875182555094276906944462491810194319919299189804172859832025885920485622119732205149425682185036910669401016278338399850380450530272871272161256432359889811394436454437565792050137753320371004881276406031033145207264552440228695118806074413690616570725481031487217980282512734092851661602230799358290905640640166294054897726254258832975287524038659071099389365056825941125437544971808020519534373822293025597504271542775882743106943667945585685976084834060430927540647056942548715571865501697821282655817084496503126368193536677380004221480405731139262525466908290430772233390595221959188239020452190307451678768824830353198811197750505490156829740279082001828403368410734840464860441603674582046007535593294102575440552983198963550573417619364747232996297020035737805146542139342161947163953016874895450637470202368097364279847364143955828639094201834190363517593565856207947963271941066008170242862938636106530622181747481375238208661952154818254437626509943162274853298506222406859658936795433343444597108977068132919267041782624419840000, - -15232647987269469551989511604749569236361758130450463025984775467271649819190470721434996465824940727660900385364931125614486028304037226302134871497951971408149778838016644145654233854222351451817522582630113510843228608401318711180811121862498824406791991790421759080011160618383774168949793907942852543125606975874379141862473794275784284372444882104019129647942945390960862198287768312263796734787344809415735098391817391401934066692599555851982906181035779587065546421537808742323982057081415831453658762899939000165932472329549010712258714371821320927327458525127297950409504033489588504792256582110879490932930686482372539836336441283444211539907971894911195605218919302186545372642469015067997470410933974184223710422082292357229222180303100489259878842975720131091877598039348572162652602921453490529080371145980191407802148387184252613698697903003731874885525200124848083199079392458473954153947091347226942038821606648414120359759064952570824771201287139077356870412272909967513233144060686895703392593149524616636906283414456121781619291649408119367797190327921804124914790838696024429955966939763180240203903071814971249176524167803090917272652490764777480048769679856633479849816819547070879158860807064300733643526634542504464165604908354928911475214312184923237846342746508834277195194192737971303602118861853451925563505161708106171430674259481544273172340211040310198630147281937935311879430462507544533938937301788976963514635347210589177908639506770096274818551030967664932109392238444919972138257310283752455933002900797845314819215634538030727713577990522362877113975138273412310623136598504354088278791648537902215449147131948749995796345864428778871698882274629842250868935396565584326688830382142465654586161493940707186966330582761474865220944930283377812640299949094121593142809937511157408277232880548253415432423732348353337310008890548489013065222758170234497891675306872015716587797545715048243395320691023226867725240382655214207533589464828048371325556224670277305188442733527085259033215978633716257290806171306558080950230324111384147505323273376564388126712312726812601162130151246566845941965850165987330473849374306279466930220129649522725473665028197207730440104984010192859822913313120947643777677861300332889753409679778816850716515880100594542724522810747440715870545108959092139347907307845346076926238570263001848910539462446520884285827296252560904739096843148477600726868942404477271016801665904091760492322741773574435998532114504413171038267395551330849943172237119605196092401710556405698648214202755674307882784521369482406934977143336633235155698351095160167602683812454273955761338324220957205534873926679709807147122497976548292378483322442500086921039831432577086099517709947944627142911501672841961209254801581320536932016089577168120744842000718262451142937292908194054771624740903489222948307849177483621973944518228415176995161992430977094395622994633341370876741228774853037041177764742300920159851318774113715957424245609017404921333635211016887941094607357762045175419475970010240720992031212678466184667236150558084217719228245848832529453325632176626409496545074390890422511984928086768685876644206573460373090832604323517983799807875892804322770735458378049752407797394738717911996547842876244963367325329355285221349848923472910935707397516743036701095353845674458188755909730142587399751855100212257121861665056956575084120173606799270534628548123174583095285577377684416545134673340898211596895636299084637517066986743958437360865203138919667919160756509672174617768704250878083806394875586513111255712393939665604943716718006042631603966938156420000975643380339613131906150762840719082998992316959403408552733038907893372433372874540449967130833724878451625282979941716912936204808627614141406160948156346716886042128698615638358263737531270644500459252352733277698034244064149876093688798483374028278992373418937427156243638790416290186129195225319958965532794830983849225554383751200510824690134898076710581920222637220356563054689817645501810378815960764224021645659515598823453779970230317247914626779602257796575311510244278155785760649663891251510769699503504080082415698741763443957993857299161139995185236745141392561444359278090349758320389848070064731526224873592224095826144798137940301459846350376935175258450209524969027314393157251877926305300916426942045724369798329970335498841083181981922393121025016758232417664185628771220005322780669348265751506790717219622273930059376085658879944226852884535369142981323828490949461618189808562540148211886953658863045387314577725654018430600866855261411363020594583119106256769945892890155085995146082419540561151091400672829292706340200197805901992093157927946138928733114169647858737983717494624781096295321783630250828619658683712552056742842102611449525969983041702766092868552112612246940672924348831773620291356958785826498462123877939430464953818327310290436630637528446044138058612552996424909486988084754132675346784477148718050699308408510194649885071441755118865061755338971205249165076655700788745532103391216350659853705496965931336914444263375748706043288646339590759179464104840384515175183255913572223925224494062035768714812110786441052940644518883239414181590930228802504268343645795946673683370032505878501998164470785286209440150843902589755120959848068000221319469883136774525613245710609758422847112206515886217808759276052439409430625278415346116269455628260507828885651340282416105475679620662873549190350551215212875918838780677394423680682460467949664362221687165155854004002258319557629921691802800936159496485272446489049434927496567819553788777791036820245034597136174153224992554074721592684656800697797512390274279296652642268284750496091903798671225727363567073354187797429326432520286178253563869667393314887626121110089349504069706786307297183538644194520271775541837678631636067056536732518709352815104083241856652837409088146143833026070019515715692789760000, - -43869766713658212222229334742064101276619035360541077691636647474429405658409564483778405632274502213551222278767111379827406477409567199207953790015125105686368826537334264283718711662132136543754092929616606139382465189313290731173467002600166518157423597771890082736269503681590381256741880524960645216445460931398082799827948742623713039506211247381424808268931072636765653608229125462299551924952143780488444477824950477555019889597820954870043562937075069844566945740827379429612225364882820391467825657958024695077826441343314313374825807030110585156484923589339068542336658264181094645594213701997751221426078903696903023724081009048247104470668870464329984123689694931691477550107902050125936148615001041737920456828649776925038097696096536171814431316277080311911481748964399422055345771685058819775403964923818411700654461097905621027949671976016056319880635084754051754361300493701372130965154817247159610827822706285660207988105771079012628542938610206891891880822708835416812190006684199484020840553199971589778608104093682402403518310709667391281013210491045930878704243011251823319154813242916538379813518921440897765495697014516101379167142139068667421854682319616101370508782979629920324929325299308023672172450839598081129857989254935784267597080486621767854111303397000847908426451848538920083652246739020700670745264805712211425628751499876170266083747736239710065026657261221730654711361370180718262086773582582553844793519988796027940340296700168328032324379541301849012030830042102683244113640747815095593790604686054709863634895097797588532642318223610091017273144067537211342477424538483572646510859462244086544408055975361426063070657315146526459718637586995305118668446240276367556030865103287561270217928812684948508590578614637578673103788973495152097046512442929195782826912251824489385146997153574130102054565133274376599753425307550913483205526136844645003884307110477861201557509722936589569268124539962547153304520585414604431325594108360034447818343370294640995462448121402129970587335783133794913939870849400626941808094355937520290271259234087577620242415044352092486174652916980580152412872091159141915246994411998858192650678072213857953445921065345185895524168463565163542997278373155485833708825063608481050985496316429356247908652931633135388019865934178953135706301686845611651171143777536041411146621619339669708896044760471963594163473760175085213198267329413123269855631589789271929244771991108363017641030272767822531196491119251068965551927905765550043629883733661475304070388825848328717217264576292716869333612655831621790819357348770560855093235909290932810521399840105492382237928595879699661426859544989405726078703947164713226305163980682240853242555905605807809651849744079122423114126594440937468529709477403786925134632093741529998820350073028128988539300419711744052277447334360573657885869020768604997318718620958936613703404643489246597632761987054411065878249920835524192799769233740908684069895695905364225183641628837207704967386932902883859503847971049404213145138586363061558181136115969805748820932871842743497325209005790355764586769699132956853415204412668345239196544955634486408823622694848926437512060851389679433668851444190531001062147168373967867358943929367166845200263767811956402777603799109387044321506630429979418958483029105541719863954261329775380985411529958907963928887931330980596777445913274927581575437936954824200286478418041162282561370999898614415572882582632711355447365491466564584628913880585461778612522096259962990074417195503281790041391644355557714188462730002553293643679495975560898718002765349087319445691361562898126898130129193953888852345944446339758792043331308951037978853022593673112768805321900485936301120783895919733146821917062115985361619851633565532049012503122810238038534150858551909036124715912993146353983742489226521229857037716799271640668878398543530553653196221869781877978315737178240914464018078490488000162669943028103544685388539623250889052349219895451913236724856728561860461539222447230926972266107561048158530691335625514584678123952277591195178333902551848948130719664764935855703497331102333309112777112508960528597970234387347477512397935117835911233888404429712147774629125830988315518184435735519315202490625254653133687815356114763685388413499279543312297880143152679328663365169849784397534930106757998625686048605290666061049213774113753224058373329756465396308785251407048839885347166148678698377195575270609354308324961674992392590278821456541510953086899034852257938927703857820580595891383656114110692595506291308028328841208861612168874881517937644989510977924377711871687695648402570610218264284673925815988495558333828742863273366920916821417336356804442210390362573913916213055457971957232673224853001751514182372224102172997511391171602466753052381778857467123263453568309585805380424627039719708521779104097981147381583333665780208160687127210135259441379892559848051373952109046409746986388951840399258438093770849861934644834310508558492705074476660957455045763440068253584408582084683630080939903466988288416828897200545380032188027496608228513813711875793883493741495016048322290898116833710070748456344866112224471543378665195292324298930562339958617782365390132263406508583704496477976935324705187507516738551779599223484714803861997962447961796258589633907223768357798494703866986082112348802435921689977699054106131655131708563948978624143504710467377402341978280677782704949212220783002650891485914203257732328656423869738060061376537478128688637471694373205641412006781832821266095632417896658993801747309850145762896221465579190157504067714577256345802299620963961012690879785010122231705508230489633681561798140712734433395268699012532241497131360201418289095072326896303554138042601049725631714821648022444145031699614665453824136967381279360329975571498210012689679209405454654951948666558595365617683492905930583462043975680000, - -119055148890431089480954394372215923721751517299547828954682543011608771195959350774060532504815632076879565715443864888427183943407225856509876867638609405008657250958918056435971315550879297502861223408202948421156701614013437897680649282570521265430178570028012129521220457190084790904716203962137792532818932309008951922732897839485894875656911203734699934279027761614868998973105253432232843438514124856763908870597916837310611010008523443762579154810594955253881251936387903122107625845197733519088358181849964166236235313119614934644307376540152031311139042879371192458087575715797324144796837327902689480076759794555951729778260044992736119303470485993526734562488804807649870700389491277664633458028684585116008112113352439722011032839258477983981088486168812624582297393295587173247281972181632682357191738028526640394570883814323177144062938938760540401423287168339753240060610853411724246947433461676063574442627178094511479057086274951440250472719284835545352042952601998479803726193272832153939020379232018543678410149604877285415797387313214819453889647653858237537220887574434311795500080135665934433409198971452045394344035311473585496136978544004954531865110631017012087205001013226947980876561532366715099715392168839691404982516796989667778834015040073254683701716604413825205551402813753772503780297778302495792069746641332034407481023596703011904194943848039935128086180564055034075562266694719142344935990790433882903833135119346212098877053034304138426777221171515773977631044373202674045101488509733490255815628447039951280484646470998193222226897949508605902598446831890991404559133039187580303516179945085341976042860288867677601338013944689951838160862304566693762029195583646409787017448673993562467482827162342603766672273869123747567498049211672792519652148404441084885147514837269705913028284286771136712458368840711107879225942385444564119509306957778460104988091001280525757481550417883365200717720703279371124285409898280740221096670679890258702107919320419529773427074196798132606999183522775488760108106804056817378301772617797705954647526116342587723037313526724553990473538073968027692139585696461285328330881710505911984663139836241005320956895038795065678663127394649823372786729666529144347021555657827380706495329933088964742063132121065139955271667504942448435224515269064591065345148457448213966587705698218292858546802003134616577294813497313497274710710527008202814283041247359015824613006801198370488563955828840935730959764289965135608477022156082416300178768762788186914511872705197217612429882016547141362552820820536801828807747557370871901085101769185131148101970990167118323545792214996151763670379926620453020762866865352280956688456670645186818001785485677630663512341656417982940850310333600404942207385128273047135974257297522628565023253517250115815763483738664005075692692891034691562020831894456707992856629831689928955087081640967213535572870608914988727052599726044846144085589988456799088033893370653671265032654261242961881605123320788930707813188989331249384833534850697273638434405206471881482472615274257596226164039727810099401224495217804497748951932359730625549058190156897671070878962312455300953681421051657950068332114321344438002455189185473907091029781211475934002721304900364356537644170235647831322737743665904282160959559363775860010120732282857973805213641214267589346477479538332015126570202190400552148645017466170369797196462392635304295074804547198411954384752403980404983946133131242122938941314290892567421811110090100018690686780449556590547235870435513573914651782255816381073891218452054753425050954098631860580076943627367525196786415855503735267498640735858995125740673862967852442210912811861771777999537251013396270560492058360695973543026717209650304713656736008840675762924048976276427793917532818428112848722529852151914282593075657794380069111392264728707506147804870133375264765415158170372715178160414715760816043456683792385032451660193800651061939298602722167254889198790863275428037368489135940302787334096927327436890306354536414826213484055545574978795616722750895515865598230543025022604002283292175772570879209112945690339388187109732203573102828877151030172472240543713663038172701031852871842350580311311169939871769297993499028466573990475160884737689776397264890866658434238694500769337817492377202155606747700519291848207499378410718805320450535176376645090298924239589964906408261576862781860455383411686688530636540762204059157493108482433803260753774180604365258591777822862558327353508165591162925441527278267355129376616958548649638858421964616773472880824442892645718349488270172251342641563576909605053306053118983777620478340365763118392163671212057193716240175940641137343674211203217430770577891810977570964741037974786049316913913398098138279200593843262445276122731706840153363835339395662035427343164650402426236227639215128759761569701928929724899600787707698888321151528532250889149864383823116177806756858006705156770786918011293497829305095049236627772916510556863551645155639758294622371219765041198780132563079728751858828644527038132644205699165257858291886221434474401918105399767271468040008720736346833360874753747006781896757841634385093520712789188556082059507408582372170499139599144941028932633605651515923517804192974903165360792524635366213926365098180993019034968209678843324046321336688459004379205417234603716407665030079841627627115805383228958424217542512526020974688242242202715752058019556068462227439495073952294976459096747900263931350686627481924107315353111261723284156334786605884818303872346685528977916031077872361910214003964014306725484424752013945404649165435555763400986934028938927361449218836903128659612805528519392229987132495289976044260345031265528044673500344098024481203991115494148140920945157475270612124009307505315796215466769297950009626885679330677835101541323963832636739183181824000000, - -304542452030260609889213875795005302928570731674678046440864724847509800259713677154276571019848513480218842827657113133252108779219420780206910887544457725619001120363617421948175562329118274381548843495541718476194422638812585778087697421753168340644161876831720527305355896499999511453966683333621634034324804190075600203072887534711386936173618626638640311265999848521260556363984603795069679541610007373632893094113608812051968722972748012249428915483684848610191393771992777806929596449480251882047754679633984080153087368676099131389911563798239815712004117876761515477114995712230874286351267455687751570151785749864988503368216450004953386374402526582822549537204225924406004947108092686614262070384834937635225630885959622189874401711800381734286050002120612773839615345688047753609881361397516238346922988164367774186448885540650055517900937428967913111906295202471905572680094796666090593810742643859825492791738053848358306366876172225842076077328273059232909005072367400124001739809182514347714439781772667831979750205895090349054845619746147557237448458134153195195009750137762834160267104927239218069535058299912816595955713219289309004196138241215598024097824495257128897292508325390512391930521351796340505283652698993649429739768606037099516023774081711535322320010699285564269426760939782725434772888734289348974530120044532302499093928642988335938671031400716787047965526244116258981828914050600989634890844011386667725686197179311263875090870768350778002993049575443705232197359752557049863376102870749733399255246626464553819464416418783504898572056667773156737002112215507624879463080739718231900184661768149789174819396189498425788644269448134225785149634089603469565257738579560344551471324598900367224821519066478651312569411124211058450746230665311423128647495943709190591421982040952565730765757406211451508322841306523347330243122129890299523693507703971764464181866296692224487393086694708615800021972241616732613256327764603799952126796258994206925718631233970110942989070128068388508375936241021156797510502312787163017688365208055312088806199292486344828122052026834756551111337237182655899553912845316794691414185666170531905314929319291463459178751513705573925455507634965103766902840207597885331608587984300611325959651599746870259911503987990920940602876909631797751626805961268463220157740474458042161207487925558656341824489564123594199208885276216717014403709097845592184857170253594366754600580764821329017609247075379992490941981508864344850201412244588035195733575612774226200909365450089757225278720055994684078746443503403698465593492813731145933753055028251804463901316141004877285143006158683681572097587972586157558335934584767395648405019469536418081460620319104504265934050977267848343500133038540993472659775348019302920055380173379118605783337419426101815845881913945988858200631607157376698575110038196438547998694715449711293704694832644095165037546751696244548696945908455436220061467986584111677487346953238491938983118171931283310006378434761583278533632689844904726683863708246855301051045437620583577332740705324044408978245721105571670932512525051228049570413441594336146032951128666171817645613699872225399177130159148895275735468708540020837714092015004344360300634347645192758602261307245104031353193871202522920866701610007815455014971369977434424031614027262199873836662737042767139410538406413506342539171276333089006466546674445321442172483630552194443849182322767409531591426157118480648006418492778513725616797405301433418548700064065747668409551384045550575789547775203224780344673751610917116310173981674376480792802690563885342111068021734917865852270577659144720310140522454348302778924520811146569823890682272981260063089101992125012130678010073227095376326995206191269975276269116997968545709155031048246694134632554554792791620881659212827322009021825275482730779817256620529267423092594485849955335333675043762647213577698844691108421329590261962692025354120379825364709646466851690593018909173996679033908691090986727949948328122500192313692984086911438494082956322761946160704672246516224655027763817156208333769259560933902766605264754093963061280283835106793596980095198596111108126443807646437916732484748703668434675735269302828946211483704328146091893858122982841002434359848706931806769237031815514044606060622721178559086783629421912415416103209766209096793305789980460814408071681838188233100548364796508087848808546763052262066290163568238699864866101267181171284779501700738237998474057322120404628099186354817363750056117820117470495682694995504477021048725845557527800529032391194276148988374467851250359152319820307162250702810336570126065891724684921155248175430676648647169024321609700526746877058034338729582278502759839723427111022693108432497302989593028308020918998374117116924480676081355665685576998050227696075853406548019563574066011936572639552096473995473106171129788248782362368438562404772109022255469978075501938413187298810300027692596605600603770732769734277234315151678458749138117721564365372710480448789776911212858606425256354202087316980148840557207320055317445810157440213627784484267987164819299758782971311626605731742736917001050966353724985049852823094759601311474811027191331350511427709711440446994582145135207502257123798089097945473532474827305181428425279403177962145099510503016638441299657458964405278873566298651506564687822951979557784722301931889100564549943490945605076414724369115142098234208956803409108523951244101223189288866037657086354309473539715347175551007035708178415011533497788462591758478161026068868565183122959734795053220679310873457421048136260423246973626812697494471280264900145362027725188891024678454951892521521992330895568262577784356221780100877255328534255959429387273943255511003048710259950609469593264720196667916184971263979692493906670779218444046090846672519168000000, - -734403610716841069131889026697254788741052631966207939457846115736747322862978917129408575259973497827673966112499163657729203294635115286960109287235025781625062182124494183710978848356305186180338646463043540404810584549699437814520037550471260204116429619971416036455594147828730399171168841680663156220114406503995410174226191362138183110168770055026749202786197884788728872073542687620557040358130472067520091766118916347865452037728045913360165723264417424077562387280747036719743306816651645478726513151642083838304965195995268363244019223134332078303137689203958640728799120629625606709057768343138953881154127283564629203290034968514611568695661570078138788887450622641114009714457414913063516346349955175534005701662711922526950084346448293162025698606524357035394335514797520413582735300779510869784511415436242978397606594964451266487578293570742389891584407533846628110212260155460377260444145014785974802498608902703236110953585084442154887712917165095102521234589094782544573998785526738654724627099133686929766052106054669808446319822790771192471028427650347699717403245046814875326276355575702121006775393739679230450252703326991582277852577973873245778198802897434230600965008807879544906100857746312684669565140943504679893015395509072979787666026166222072146640510600863683208804912074148711577209145650238131175424031954438717530396724159917903307802733121785192374567535559474420816348334026810918885702737919010612788427567943604387068313767011170339387314496194554596982813486813887715192009813433796005441230458117762981298255364673165909296742917293512104057110369084751918616074776323340339020360597836986376321278091211553765793720074127288129694550510991022520446320439653742943596350651419278341905030023940163245888554890562689874115784240545951767576834194773301567027540563321277177464508707471229118967897935834236589271186300497986136133524378401143789242430302529883034691417782754568988316003380541252129715835781069806325063037639966481648963676341723515566695717132441514799937014145562575897365252642274822997825869890254144683829558906841683304109685779613580320860782646645604372504305467127319081260425857966835958609388098046168295921732936273419279685473695573786989965888849905848669071395728988932423805071691118302899995264768722374600895841274452371633662228214730684813612813877473066797347370921387309009877731949267255959214509604685743611419151638171129620205789669449162636426953881072089036622641103667267929110617532083957439570512484517558905977770033380019637320030515216364184043320085280620636142116679067852797521129555766469486669045113225750966310896166802500415070517138587198323185120262290980807289610771419521667604038713412929569122238295064763101863622469952481860038378333627377387548888766330424607069016732819463994754784040803999566550189066446497082390978945847627658706397022875056515578857600228747761974777297287711067803050143931545196557650685866724706006830271084822562235986433310712937866211049934690225138541541336520889407530057812835835061771668424162478360882873505696915899681519221679357558666116862911221938535407557195377603977637661588305961454448110897522988344752012198404950011250810151339865310789466377188249102936970553239572801247203746054847562950015819312256499496601156002177055890474481449979944519867189749819859089056037655371569297929553895110805123571236613336414083361159758696287310833331976119939755147853044096683246914161487075743681568839034468455663277211021452719373000123960868131689574445224385626524115129058406862717209826548999682663577935685426120238120134626986259487653559436316370347723681409341914163917896297668272683258971000422710157789969439849676137509176724905547950650262954361562503854610455379940157250348699401970312558872468331579869864579858203932582698019932917237514056432271078206434866321832365254720840769668951359866118427619899088539469984798974115932172162839701745015435985110333546508769437433062581103041114183638050693144961419292676165483796763511396389140616948768436870345077566793699951275784375932568504764407378073066624503774120908805159732345911100074583911662148696910285488539123923781908810517834227940761538454866611164684193164633722161529925324760741565423892791093140079049742274362374410316526201828293408000839790449659853791689137179748081051340736431599291434297994881181246741804787461042918303035760343705846530103518915197359181390063607198992808346599844978120032884655554629034553363366826411808751889208334079985521035983715504572755145314713572847350939857063167854575910672229929843517381090900553157791471553015901486495648630475842504405910972389156934097213691578130746974248702381541390265592355830196988453925302568553803923451446721555376260953700944098005380964690555792983674243738999828257108959320405272461124989262305579085668873326283073292811936345321021617377408820918569107460571909529058246726685372826359724447254298969309224992149567548425753088389789082408871879244966726631030238315986953745792644223888775167946361756160420226859624429730463782114549853357984154365249925704961982625479896639227354638580548760814550488224733462956922618092243618391503496671625748816552607266774686580154698476859860706793017727494244474126169701425792493773805220990364155290095679110694854522612047221989086210161078084273290844325471093264599100047185091415998952151232035304823490226057072772714329284670617013458199982246630781837365254934683901052857390491278776996152112015122063598139294289845130467285673136166313193650570403150411140368193715450793368521555355038251259321296971072721877300327758371440252590614372347967119055539942671018467954650897482206050491229509067446016480873006461496331335609279957015872921720701406021888456959483548387554681250127753713411606397602812976296343048566112035799040000, - -1669678611406617488163122785968076558189653077809981642352435413247460066949574869682913989455521880204750769385512113732969994060982476943115756930091376544296744448065142638523453632072965430500540009227123234586707717252220566988050810250682069420763514117269708174883336195320029355120849622129557278642069444513215004755571359813913633019007040199469137869084761894308518745751944456436339501200805572009113983350261395189382600518745565395267082776333418284505075559489204936744217389478190157238821961436605571170628345278677035725600404552917432461549657586833976642767556759452778452397070415438533962737006907286475260968184682554073599508687606349102012394128663009884951019282496896083297090917361012987625146543082259708308957266020879380766192578398105687515154647541805663701352700018736512554253178164077419264765499260959315968825699571520325784058685130739404071580231658494865892625112266512515173256876951630174036664172248981013069266969402655789817212420841722965938203835304528252956345989962616169818874645294931177309746465257013690335017169116943180812019357969759255602672096580890927107594360640720855931028000863401302888357644769597330952457583799432365081201513438041778537926390489561746286542461764024002077393440169357105674122543147414845458858779398046326341715060810041943307372591965185242167081490368037748334762573089381428745767257224967862616049650971421006182684911464394184356641958992936879624209143225041515560536310031785823632984875823436837369243863730778454896239152780822530357390287127217916667730172727291856403609055139048339278868063128310178702022737294527523085802436289575226830142213143231306995483284305941847260289199238443080145113575774727390630804981157575295677480675996439667136205915048696004385078125812793799113917915439963772969157085374133461048222526346838337728316099383391175623072208293331917462332472282661587061307818179212764456479469366147283636136143153173515871504687671867902798848864489336680670820828033485757775848659934249896385282425101578223358703932282092413217030376931162766541406103207886645695103575014473965439959240784677773392410791876728479730342139284239533940287349716745108625620360750650972658811549714075908202108228003052420006476630238967889147412970007541903375204382194264387748479128229037895984703819076338930687837373200175094316005192271655814999677868961904568580394127330030884449893460974034431250426677316498671986037418206132415866372563786007620028176710280850399432921318267650570848568697303703794012398664421906617429925832201766849948098522812323511431152026597384600798350409933607870095276326287695492311778921254764403913129621433108321841494118100496689974695411004445446062929087335232839437038909230683815288780315570413133558802755901069640470756416483455240609465455450544003207549761673919867941942937608889823856934831184562834347133288719154919904240159893772444787610045699618995975201244666407001605492960686021058668944968115983857057903814355816728180205833854805473419898313082110621619294165979650145034553907964173555982656695189667643794018333201229817918035896294565478108857896865428160038808120186181855176547325229733761578124627915264106646476160701841023031183730756261248669513380516362938867882604574128003027568150865094590347275453619582965543867254937673373428672236284012282043435194721871715468870452755088999586520227425339921580383966933964189110656920670288227433076464277673743313400267045243848697390594095542960143746896934932448580842328928279172578877938970645110740471052956096670549226050061538326681445952535139354150181731623901328619244713856036159470901960707241396669003559719023811640365549012608914941931279350540580965952920911509984235171793304082771889765846013160826230515357370208012653607387838554233066998044799401543744188303922887668495868047935773860769261221838488776709276846642771449412476871613089871687592050006230274562154983129287253866611862763220312448854143501656998938126699487798861008485709868166691396894983343730829313406431674625542838880185022267449436102391287454327155964989902866162857552444261352784251940465748614587943235367391485343172318042886449928407999454955715578967795077469217323967860725301292839012092581529942892339809631667143418529964060850947693816406864991361329321547473963128238924074612399558007714689132607909641525722918934005918405119358818064029895247352799846657573048390532805877884359838427480932002458005148009375459502758793060579374925415881954144338792977437433490113928335321400925835654028034803536535675816857108531653108679748424115058953253665173580024080177332663436077910993647435242455800028471158222669788459881160499264008173194903334651136015271995841724783719883954992017331155230285673298734374215226981087174027289654066321553433559993699037146503499069506517628023110409483445364140672997739827616442427650110182279416383677040762627088546169145179305885593671986281575271063282598764084716404943771805287149896142020192128807736908338260321445987810431298547109638744569350673199015625889223962304700265502220892399664988295899432635793716409743376450925717200754247469451431253197606388530077668447277710393678343108074820933828583391332952157114099547961558781955692451269319381370268121835580292808227085647580337137854419989342476428997573071338487314432443722506785862443325046145112539319964790103098347174678095187889133310075649897529909641242491092287385610193507057302260896610229130896829869774247989995151962316870626168767779409611045939760460324789695472991432075434140544495204978797695470827537542352666089233285218378392018733755209185967505668269286169122669779172972454784743869299386559345580546097897112816512292237764056046720425642356606508114470345880759608634562549318876431569006303314528174080000, - -3578692121645085060677709267388151874157565355257699733769447846313964779269149821830864232111022584808507953761540218170373250874003147796540744749365946311693775614212739009834672296672173184540651455432789813008710544778009775787062505926321101248030180214591065608534035574600940462385342966081684047311678881282498032011061219422831532307122023938297650707777135699929052624858618394185755619439975752273330253724693797506925904345523412155683600470644380548717246776652673129002282822858713179057538161053746826150376266105974516695283799413465957283270792417886484405228820734703396585748603285917682144377789217916492098234140226204010325702301989590302279170179506815062432656096540043881651585389874302301421039430952241705094199576024170115472568736652794723360540704376377284440439359108118223854811455180846426344744399103569118305410148659544069943379843320625176448191694858230363520494522117343275871573334306406796503686860361887587158181811756937372016540443348609852707944166171615639727122932169792892615396664087079178890959545842272338413161753676106840290391040382786134470457838853019339134572566606909657946425341815426369455182546142396029235387832555497964039866961990705887672039562217435388769987753010861974380261437646001650225261699819637310129606405353894089317379411071544081371247978506423063480374075660705357454723093025738258771535037414902697344845505580535132675423328105391581264930750413388072992234422681283016793746746911861652091145881124773792739749532455065559494885938399099260843592430811281033495497200269391864749693422587353254291290577234810121493799799140410202725868073709604484797705557071523346615684121807310576442657819991998481242765248777342048411723569698038016225407332419704678607234734901124665900411465623512930486417481190295708235698015259876716898309342535377451391970847923620029082696206228552444471475630764390748634837559331816630119631007796573387332120806938596102245880910782272238758369791575266517165113057233533561886471373122870711114205951354003344526146324497662886847654586445961032877341418786347185988703710643445863688657623776754789967211684236170801125797795202764389896571071944354488514425883576285367249805624949947996974548635246782951254061220377419193685680344168294203903869241824887637338874204991821831587128146795123665630217186358362709728301491638023660730772217483253613567551727455660226692956704177685944964870371402801239552882518180454445862980857275779020959070455285474792488623636836378698066566564798959316291469303039285719816633380179833427257243628329371426330335732557217177860170003674310582844390145763632854743319587433955641094100524282231935199982615563454468346840032847988286164286424829946429926431909140090417940140571141750222529375718234134053694958128775902373875195058061655502600281087493158810782856273076773955843671617243226030835037866783664164767197649215114893854414987210548668746889601023187025101168261942859194696426173612258965158149893132448811606535421843787859331620814765822675849461813081799580641681549096823407958432866193623162834196578950116613440369501529657346404223714191825368633405277210753967528228642152296989283181342666786284920323146868167973589264194723632589565125459733790905635412733737578619659919441231737844939512899746855993676826476904965653748757673881466622907185652845426541184708659376374368451851311341523538893332635790091611068871986554306249436033869736434286868175454049576391411388649157130839871278358265676435628335460572840115832150457419289749000084039650311880583635190517201332990393006020151410406538263268076323688546700523563297845228494479467810659648772789852301463521006678854895561324974674887219286562910098010954943279090289977018810507032255345346361374475183795254167955451837754527308259453722256799801470040294240855319362531362187012347917712465242208825706718945293470689857788544937598274527010747516143800060450063450315232150222987978256384171050148807360488157314356039304918773705275379088246382337390633659525269355614605484863930763051206922696954779030476565196443503925552994153952789532624017232453178357664531899704760568222974670054804359840204913270509172539924869106569916827916370209845979761015385535618872324577460840218327665074615952668101780473082868027754194451962642267640605250801383168481065539195099625403191425916796021275518013422167584246531689528191589737912728674544046383623892720467518492438893118462811217966301606156241404176883673696981766561262272260922983501755700630927959668503109460413871133243134403894754854767457396379616334228297415119887040415093850394161880964407525456308427976170795407387290375317582158222284961216743245327410525475177759028962027454595355531995545356220736044349875098247716562156884868779812028695301201935686313886061966072841614311508156534568100889615463662545200912708535648491472187780100079208516119778013474183330924652967628149879131722344966380890546477644858772445699752973873682364020097758143355009195873224990297347408369638276026252189053364886588206043239094847911077965765410877486531392870629780739775776954573119774140873046043155750767282919259369361896009933993319149565349134120533965474430209990447882708153641076989565389104067061920152593538722209050036068026238784025053125124087212499906121737102265362819496211017487221099573041881982695361919166888654040551653480488914866593134511648155281051164899651014909473028183672606967832480530253580590889766633169074381426037561618379451667854999119897518854904404194199753180151945302535467639051258473328368446563054664149358827106048863946765762736866437428198190163867358203603860547520767411203198430258521159294715657935466668497233089004378607024345196201144109039541502419600553080679332577280000, - -7230258851652978945558767713994593475009141409954268756485193168151094065942495531499766880318135254110947831908138682926982312923237337124207502942774548146441800122240068408586006694058637174896651204040017941907648079642543336995763020765745478074944836830154621088743838405403649528969526751396407964966697134735569618228738258295694830493177550181100888629473417187662045454934430387523377535981713005459161983050469948184691651033699154350621216390297463899826003582192214792276722476994470584619050284087830591406059389328816067245523308350129678519005750535405003829517587206836825915156519476089369333379771098229116802418605303655633702700165640884300697036615610620430727837086090841191722845975115434742738826505760183148088026842604326422877565172825693858554189712378175652128260209657869038099456974374042202109798001073015345708121727855372739955988004223924330113340868023457198967044007927521556318445213732058460530750557842579507204253116821072184544537766768771132825615548791794427167254694774605202253857378226383929405161475352147628538175493380997019881804678581457698859996840861105606600158004682418747313672765268657467175075862422212601826754348186259634663406531822372489706884850158972172934309752173529183323628837874585266887131521875154048013465883896352818230268680424091717375499667916492344518868111455779910766848931382531746250782743852290787230895919776066897491907802163567364524388774310206237623548104367785733858955641702670015520185308126573645060589193771226278816388909905516487861907224604049224643913491508412137508780217316729570445782594093332684183131328045143179087575269015343869783662957360904157256271970887994232978842855805622398040882803774128390672483484583159579911352102477881233807926022801792000727436813052382919026014083327197867294323974363319831690826118988865679060527892412330012520567033282610720836368988821306778747990694701164748690365081913335809142721821003177624592847742298962415758560030878317327582956032525095713051749824905121527320064489321652520947312474070855992790595449449367520530326767970319687415914695485205176523243476269121184734002005707880771844572005527808745126175698398333064447830251391258858319790168695472582070980919617742320096543781608671716008380602306513183004921462718894007082417177572703404768195398783529716129357359465824727318751140958598655079139802670247590432542527194143235409573097639368497906442283989647587474220873313311904195635678618882625744143011205845547653967857786663917573679925643661313471614067179196598369044526486063414987210140053091550787883708860154439989952229894483092464656232023430719547627097761913207220912672298851253071615655172821514557491648180518447385855860266376404030886510045669444289329748414052140207211125824152938165431236072642589765478431254468396209114625031123449361343677860136314086566370129457958760201649530542368810585737458902738649121206582494497036224259020429939818046552688440952129276805670476927301406975386217775858903526251797032004802000740443920358026666896100194963532719365698013829764063210230786194104444339649653160583540698671567808429293951604229171156902726507320806346042371926785393483734563983790873121131706443064920162959556694773641012410382505049132919175918620408012563435871416165127230001029499603221248858768673888648504205495122853880307968523851113230928919099261559054666215049907353041742762959339031389189531246459665319814983218825335686413504750817334458732698740412839463898558019259786842245230553343742309103245770494075467886983273538163205706518027223139287557044558041282636311718433472864865801584599349761836905764835270492906309612980034180154926465567311446403879178042088911073841343308324070902310112867188903543753306108023440104100385408330651875493399802189999642425266396612121982518823867750919009705003396363873481028201452101878047298254029854793310564723022712937831471037243309687689228991542135911255822448263796901521545322732554750488266406556549530801563626266888304466262472382931459106399931010789618127278959582966147188756559355738847856933231037990894488901566469998711662021161595715599408149797543110822337631548799468967447582568141405654901407027905288828798969555770733170075719656316471323182534210387223105910003630688371632225506641120111659283113287209720484160008482514845736879243347074403097004976715196618935318978352238029300108564611750490284015470508443157673853004478043720544745775223980289454877453658952139399371440334932328222759301878571395739612958276078008974118680687490366752680016288056884598218811281559946323069320120832608525138369336171687611576095321994831528663601198758171475684486859394605752667017748688085284527661111738036972431724360451521241688737571790197360607136724668662843799800597890534041620653313432420609292120404922574187782946163177460428522509682232326238748016493229370614301962478742823037046657060961166651344337420867069831601229951553379649482357238162817765605509236194523354276657820666256336471681327979798506558805323569142681821188664869997683846567553565402814213474888947551678967060552412401555676110449141923512359861073304629472114670189309935510437751668950041821771566418336435946014837353409698706678269313189676170128859661905864350222417846379573254847679917149202768281015685829460102300386499733413499550070348144195826277091254298795243348246507987161599862004730827433503589981537841757723562982271412523860158000569684007061670488250565648913035379993350782516481882221674097313219878613852334082275544298270245863512827153361782168704142824692770530571575548319734750662522383883783434591521115745260345032943670750271591884357068740676831640035246868731507566569721662424094099794593251020138086400000, - -13766755827988453989053154449983440601532890248434095132286067060456067249816236755330253333793107052075937055646725943493535796283197281247066692617201692458514001547060148771574526263542688248360021314055254174591980163333298077749449514041759925077326217570661774153573671378165218136924868371971041369700228173941762396400417625530842732931372908984487820781104815124337778451921308268974579353790252428871653597026792269200587996480673761783022947427488736130965171565211321406755536130977625583876012040028311537958666645985232634172887634181842517243229806668245864711467563298115826601881556725916662618785538247536929873379139468230742124070863705345194962483002541086428364352173104905752369246700411637333066428456999568948772000176472439192447013138634058598097379123289180973299377354023303293790681573992403907434741795498758520625305173451042695438899989634408465414574467325874274661653726027265596738050930785025332387374116014308268814769549164956056887950015140172885261085618850753746318653867790362943175662701151407657814316334163265910654273640031930628194875792096815692582082334851911776980667420652084683245105637072693858005049755966649358821423753361509279400560254908951773023245729295204927671582089664043384200941786885192282283760391088469386891166613773739185138729937101172522546216395489492329820582465465930578042833710709871852888543750698677309852686963942953802159015931676936593823865234834136276781085880975030646972707519048699068612327837519066670581120958748110833897914660069566250194141018604220929108957605160746016201322156076691879762666286335956009190445486404392282909304321888021376473786284396273928117075145176880210181084510146936857600480855878723939415096267705484922438243102505360562811829288387352297165213133275279077582984545371693246194359738569116214179570107090710738537032968236632083190925902907551668527086537074132778519103046189502980738957043091113104373281794919911443946240462403433913494179795730410016419341297256323890039296143499542254212955950172333314728883662452417923543043633088936609141097584353042523020059102663879174319714467863489908928137569893319970738282470474399460346431994275040545014679570073724800621302097615427722258288597343459473045660335376058438688241680167573728024387070697230433027038450723292471496457625651568555063290998103194180935062703086486023737787812391222703821498793116642334508981119327133284517533744778370939387504417145059039581190046528964285586812670162023201127548113927871503058984914502596367727018092003376737363966062744867400469156460074279646459643924731898348477675311025713106599511172079624050482345759017217012443731624952657400322818436168361966561113859293257829859137672174314103512688417344339980110767901207733800745447310132294317852590817290279375720400887347220107935393654291549100111089678371809975334878116128631437891784857725652142150112005774978495148929480839234940906329999848465071594229976668791714415285537927080601914791881809438894949918436804323097166517521305314345901404270787620923175052275140901167008619416122168078700175759816927244726293933181621151682065812117002896823499812725943530042383392728482908547523089867755068433294397781881662380199287522699334835848246812169731851124211625477236893099037799376450080774297103719357658914366319744817268294554026108030115992489096131654045005687133848565861497242201559521860160688036261351338101064014664831594269479717417214798399979035108904822222269204183028474473703552200399061877244035503212942230618336953670564906401252047336795170660263529819947708255322427740401150743325254289976899990537943963001782729398388829161882008703039695961208960620102720653460946866727987003842943300780049814658296596642729065179373664104604198922726575344697176705941092945563750874514597266991554428106920379164506101538938083058567745357441711063340970014534309013286577187559697067461574747932635844846989150629384810268805160401288148168416430748217693969372398356909613606882801478779548392127032385400794146727960951723826629766887856512220935944546174385758157534421156489493206081995121548305417350094058074686956828757865294483959448079767600699319248761751938939291494406055388301827906348849964261220947719509718291964505862832657324523922874105804125339485168975510281237764009053109764215712274821493154927430344435237655307021686835081304992048624768908374335929247264294986085295295087871845191156568368619783269207445929289596587706367822445994798559190937341139083791147012274262745132087186738160210203033527165687465513071361208253598056762852733574439447325742789083995338104112265450552073462808310499667075393179720286606068748916587116301814282725354127511580433310783665774827490426160020615103246344958315291294904696769525015461818242033956889778990643179692955895595763656868721107967647949596011530920716973736274005647297540229344434479195361550987972621990187722710160201356670175634440804463581141162432053110422398040438632932126333491204118801233104408714123069725520596730578860350947503769832586494082775967222302429291125036713196011503726115211774662024495173849865033281755027530150445288176950502152930530454990128919659413033632375656261265448147968199826591863810260035203147803685317551945506779841884192150687899582951044721641175567511473551462410311199801424965490819786743196517627700339172104723094046970651241348983477403869721843591623912024154890063900996253872413290644889005248461706708693205885091914667437005477117376299284546436935598439334544525170180592428220618937752296822580007678543196498338914585497412697761431589529149318841153743474363691859207933268940662625019403919240129547237320972843768678504915611250851840000, - -24696518654416827468244560064239686144853774373876672157033521757092072753321945193133536028952956257537380765933901265634904736665751958159099796885060839925691759169047291536517423550202255167705547914642566872800333749108242427619318544554037233301858787966285985118227549855496230270908042813697193931184270023614400711560582049139564702787450383248824952695174538543334170306034467511554833029690526806210274988461552602156990866177673707946505298769757997683496311797366161859601685985245012997389780930034865291598312931955051224667324960046380405987131038416925631821196848051667076144963366136855245433091817771316219331278894563933710294000680118070121094766318208192764926299353866926923632198665003648140024033495836825281136136827578997204625936551792281098529034152016058451734272685539166744512457449951440338602879718955366077306667331902656926896279465039132172017471453370898644185525821449142112328249413830046298438165322342855053164662474032071274224199183225282025680669358101698070216373930488878295272492944859118627814384425310178625809769850802631494021931295145822287229537540023735314088471709045500941881673129908249422889915896728632864151941332776554342468506572341350626927063505040510886564102030219988900196390990799049370294225065066472502929055011855527531834396170657408291910710866965388368564982565114783772966326189101541393605001059425843822973974122632401436870544652795644464108605793214848111400183414529097159631994713961083342333948642455883076484196815582986767520204432997279958711528270582730684439175184446312285166361879661608073423235762311996131863612475749937188298004801586199046199032492069809573770314847115278669592282415631433158052278747885181463183759797528157047318833085971076831084797839123451730127697527691160823954775795575434888347061301976121081096113156568740292327115114777224720096980052199477807882174443603623723757732764487755073103923838881833547507902774473107630404148471304083639898911620786131021602548604240431370808022937170153045106074774540782394170128014931373338050698102435686916646546155172645400600001309457115068692882828599459508138979251237242249474032937005128353319302940033322332723495172331894544384990983579864164010798327802807400794651345185875921830367300504690492468298830845433129717206336672596851854041912370487688605396573414408506252480777956319798926893146971720766735294747855345373507471247463653672724632994512828071311822901018220269829102537305935078157411599075169101487209905821067563401909753621375548796544084454950267043784817541847172042956946579018915453582753325332503085233355619378885464528759872626009975524628349762843421081677747867603673304239954657178039095797662778182106711630719831635730408175460939732683697313575318212658631515354790243123573426572834424013205205437601869205114599369112955080285197529352663057685787244783032786710460384968951541564162148752903821997294991725873852049162970797489151854908926073260315730523707649387333358113913554676373912111916674830992492255309314682693704340832917552494999934143215985801972735498285708520075940819791588062098352343904851411315447993299934787729503754747228683154766810093021941890428648231846927257233938543951019430852121477982676668837282487378859789347044122002892618890868266039981611466483889583086329819989738870181641583614877749210734141854699893391016643921681969734847816076168846140785975021215020667154762919287058926080660472102930861008843011767063699982948808657469060008666644493252855767138348532507500143050612710422476158315012235931943903292768460135898283385721944782902229378003128860591167151595473661139289066741033510493036433066901202295267832742411330974338421315981468802881352452824576489067793869980258942297955610275901982226092427853051152883719979253210301205089874688645565429968814108675877863727262336376864062904450895604188913038883311215386479637618306356507247593972947453013544258459380470253747072846242928767919402248420675911695061328647894296735405265357084733909920614769323003175557740108408876450559779463796007053746884958021830651473172216649473931851041185840326591101344954772942456101398546868780822453566066096159635467642594545951185481831166146617597067079017824177733483000950978470800480078993795390411577341664272855576460220953886730905980566800619348890587354657047985066762929745589688858229286112004345756450581115389331290589090893186653733098195570760985641269093616921624797684616101551464741057815008624442173264341611374132342625550449765987451322975662638015828904944643420167449250031271648888197962525876080180893195913410731174920404754737126847787502595919612980854821307579719434503222165889806005963607784593012902237604161274590935529188373150544772503702991018351057968312847859425205956236331276082487193970802820533998502482461030003613494218343516143107043170135744899838312259642752166481600950698580289407900986171909220781854875838389797132790721753699335771287464924064401814293921196787282119857730133839605411168175450901473735113709271032783150020361602181722208892733514786654545646680318194795190107429942396413058346522721210280223186836276100385530784080150025820169957845212331529305327342324703702238413267641188407920514989898122347673993435463256704380071072408782960063022241065885060250248276435451048425180313666064505245916715335388191079797061775969397475478031883589477403308190530118296794499572096203199532148154130308130112613966620557741883142858811632920026292510991061165528153456010287320148532197465204336673019127121115422301603101789855957254372554698262583743387133099930525130987150335825635130854847988587420805874957075021222795373223744634880000, - -41726703646235606571633552744799060726548425627268504636707061721582042559888367268215092907328630976662180400513547140845711351406319072026611420428153618367116189021939973601576363723253304092862293147751224493458484921495055858030441214534217074066305673236420499687548588383511697818955206881423729958915545113942218599648892976918528044550784266451832501730243479084047016463916213744176379348541601365745139095477717783537863628769870289569934127939746783993402504873452851522733084906339378110244280655873318933959256218548467925226777949014791134447012732353203958181606197234417321361442337144671949631797788448434593285377713076146362143332631110124899815080843159381363640215839775948355500489669366132486775067616980058496923178305630996734605477737901790682540196226893309492639056093880673313722473778860333803775247715022459493844308680687849063709450437507906646224370628362816991017994515516602092544564917513710822519484251555428297241505092109624704901585974228239758239827616887058412818775328083450468461246381079700669674912211821040897318861411016276277569406230930260258855219917427014511370409382079175231074039708342495917038152895108933027645718638326881365842707029387394490045747298596012448864042164817244167127961918806593430712906739490702075563266206953077977206939368399276561005078226622538797323419323271978614965102105435376400179678537056997924297676146827263504870794601725334410804712513326881801776539542558601289217496184859135070265792241061523983965435322016212050125025315536237345578421909593703180950089797607779976568748299911355355482475360087360290036553705934892590360562513943562634905724629937817489536536384814531395596397619327986251356344695234952605543748535678205384369136049156066593211969481477303033028917828268839430218165598993158682476234364405164215349010255334490552928875075999391921855626019845075235938451350539298550504467610506799824759346916021196673449600688822816580868470853866403220220422781992925178023632589412802688053033951633899045642956918593913367564017471186655138471928409742756809696791097008213292678847236956548365376312579669529886553412435859752119700842476392436941087499901887783826523815400546691009989614595030222659436137991032700141935927749774115947709498993251690764391547152089307996974830426085492500138217152564332240392230906046025028412162049155627108197788339890509704176033479245325051464090214092258326727615463155214470514843624021699768869107409339536408027154366404508089187394714808130794885780801697421009757195469292693845722239997703770861957163623616280477822446846412138554171604646929987589488219886575937139382305263286284129301514409457385091707352365091980682957525011414723843406752132537443933048874537759889878302262211401771873392760386476374554425826308387011668701326044925003678690509608931118980299987029117000770256658662885245524043129634319338295112422048358830126499932084518013820346707194027420434994224321233144731474865325617122568462676842157769535206622871016010866505713435154867038988588043285890874951806029414305837949160790508749384606672772798301664010783298841816071925322444062548928538426022071212261792875493350411414886037231435232530648608700562671794812937853036430967745323180983042470027170781741202795233170137664134115380552626133544100498381411181689610611696826860478989194397830844995009623028133211157408482667393482625573126373256303942811485156219832969701276655659440609885187107050499243805275834076144089877764795163993669421654523588588262483642596512436618105751253199843819279454715371448920819869997781632061817427078025984877162513870938705689503057498165981969407111633725927315291390355723396945542138223905861475256539611663175733520474032211134998495822973162929573805260734399391574673572926401008954112230246193656371703388480646253289017310266925671373737975425008484044644490724674466674687060576057279739118461555538958610877177375628927944029067578034573466609639314965741558527875984366329363977629818836159076719468808173019625897895779908405120468561937649996132743861092919453709338860242866461815563086963496079458223852165078827451815606992329190996065954953925604931239923479573229746716802100733303563111111124837405887383119522968552964038457422667534868226928616814447502509089807131945794032355552781275681215400135784500990729056060387430753217877658155916608819943586278318209869933012829634764566222883850432895541146003996510581366968217138893131783309274144004456559352600144600119011050536563571980702416097783619320803692596070387644238624073099255904288070185310743811060613028135325949378021206968260271698790858668104585840305261353331643872127670841311373376406796080765554682215559446931015920673441847723735850217877739763243548651092053058859900352752983706454459594579835639357255282301251147284768386470581410781998172064209575908496011806874872648616434726064467192004591396888130496563037840453944970305876067186464274038630259175978191935869981185493519512905206039414003713069015541331630520383916832570587699536635209034382747292682664244322643315397559420791541826398174598689628281831829953390079620308902486057094652547772546929101045931599004072161677106303118341182625981285365461603944286574383900766632427275260904311600148101071949941575341026114876866369176940065974717697391692220864089041877355281288284068199406684563216283258422429507539101559550977278815432922563798839608770583797232291703556323738140241066285125129287021838456936978592421922996545699229561674753229383113677497406810364684186358529968433670240397185621480283167974497641934275659886596869353559171111822111700859970566225920000, - -66372106021735992981027241728617471148249670148129119234656871208199536281987613563051266321457819494211480917819446843525532474970048227469839321675151749078860036505963879120512720937505085055315519897602236811153845944115718448130610832414133593167168177028819340800655482716781800918291543642947534060774275255149313622126647065303870870566740318896903859817996553239285127927989564209320214128280225013777845623818750171311587106765412532141985344812322852338894073564151742049270697843709228698321405769415072538985656383583697105540592331185069597445411206020235498091991020922690137333970377987779055883741796594069632552272520721136402965812652413433634492944821144247330420001622613860487179044382524378528445934939219278133397292162003723068643926261726498575455873879645593884404818760927272553563662593826979055080882092049334412070413149802094219631473033294039787669362675852764559056876200356337436178574261983551177980060786058632405744635303222590357405633927876755132144503358577366584899580573023263103190137204850183860173333135981432500962145198268864397646956698853152546123658921332661933872465198603499809225086124345148454211784543802337194564514034497450002578806811306147050717848143095452533058835329951426517760934459723924018827772566040178994027203673240479895561489375122576578922088100156069393793578371903276329592732806099772680592146874647681073115781964013599163529879987158160420023078581901839815710100058946772097572632698307565081643988532980382918360525884836066722605288840779477973522117359193033152503616539605723865792454544868355046994417734877726939804055145893636782130618877649816656761592086545996947179313150898783037084648893713255905314120942621956128684298867697877112234699323406141550393282941563777351705976778620733404984789265770194028146361916449932867764611266856047124642117042395963682628056673742755385634221037208554323069510893635109226934373491988594706666147440201894345605092173643476274270706830287948080628274908401300231816551275017471805745785509406155455151492295707116152315231504464009529203639866198617624679522892979086733263576745033615976644969935711268496757687360502455347713257656268971488165251894305718886948617409746647433011665192875838735857700098569243660217747478378073780071845940536144742471533151592376000574470145603933121318921501896073587809675066185604393627852329423657544345116685255571901281944070565627115813944593667150388269133022020070998994341283509713235852463125471024218158301702866974263652218546017795561691005989236840328748091472984974737107137215539910440363316543740209391349672631521397662578044555339730992493869710253665113722704436636023931411409433711219828412253882064448971797339377991071819699546782525107816096018575523116421994195993549567079000189512297132724514895802930274242893653660024711403433031255830263972938671715597641488912452739345397239881341594917003176615502458174052880735637198709721398270914665764403588484097438254833025608949850576161206405010811905086386496184085196914282512652588642929543190264844469504425283727769284162941975735097191885525115479648729272061632529323657775148717634351366136742048582605705720499689317834957577436475126728695443310401176935447631188871593831000800729122854284797888317881181644280210828456980264176205937292572245219989306680271370107995722000234861111037969749826258471334183714034559603217388637446375285731943807879293857045229933943175031182813830994914537128811266520731513179074549096318327697837778134912503253646917800129586766269759288603140681638604292638700736213039350529766470473284487609197547062387624249889518698667588464775599581969587022331993068447823339957734873873877078563263728461911429061229773278581167822109893553310269037042720939939892052279554751478015329013297178985294173803327262343279477080977240903354445754816325379579282868377089797128331106857886916940329656076915731813686145804861468950622963784693895171266291219455309351438312073326672689783508473574003883351598000286438210451750342472540495435169427393848975073417682369805909213756565849212642919689194287827056398785919095194029038146069261710228542309330625644225504244082816816202982982114537360810829387723512507746874291622909306933994156258811689215702008622581433457754912066081680210890595848950401704260422050007452051837813436241144669066054870556271567481936896632243507702143890464159917549260260608023743814281388375209011526755036953243981373426665451740317479245005667752785871575847518395897436975704529014878311924313775940921093306608487910763453503828963094900033742165677625196135645401190655666691664905005459415940972384688881723106479315728458645319513603780395135513485399498481806397295571932398652278853311892109658582946323424188703174148024844842824117557946125559567194087115345809275708494974234032091875955082615127748245564810191865230005916215458833605956999035996156497879904382314609232446816063454478697095549407239817336774578499277701851160382990909366643160799963133422910671447192255387782456835589376812517979441891864821303294237001193086309859283272384710135279870499598936479655460689829042490404957017852805908312114708849747634930660057057942640108964695826193743136519706930301668831051861728568506108157687482953208245500682846024883419584704840576058490899295944363555329027275065598563524274420527883900130874519154628665651961256558649010696021919571312274782099770639228865657588148723046458765664673968147566685724746591758088236170387078057662785911377215305788799362738119952385598925828095256375173710618322037217739770167147149809176820388870278348800000, - -99343942713167493940973958245678444251901460261144511394171253243668130747501356607128458081598803487226523964106774204397371409257380740017896774180865074470298032907998595385185942188969309523465168293210173380986884877522128406749507263642191801374231311482365956333802729595647221590612718501828678760586306512786786970430430911788461554353379349501752110424116444317055054076053419454807459902721240507509839243846349385580655929490979161106413374957559478319951693097212322830342420145889103508096384346210696178482752910534645763182677834295266224012104424574859657421254115483259772230789849909991195797345577873599852915674738612327447020411204836178275118608509244746691861336787843421197176200829168705876973645179664946004216837581086446550488930779485695481674284898720892571846441150128962105270681335608076769168262469149971667641020042717943359259660024598428564616016680720605767189822126305577597377055540492893809934816360087935746110555325414395482420216501859642505116155175200971080234529963820088741583635430440873153758436932812719717894396057833419597217736894561101521069572701178007046652497170683151724509034327747227153743683265294886054687426092121697998710015773286277337989222214888883637026133413818090151244473288220936597538349044457386959158466256024910936824546825036621578704740561482230963622751212935573277796862169353443140865431896307408088521466141775959510622055298146324377481352114602606761151755139271442674014725952644145938367779640855742992190968026919279937561385448181013995690165405384868592169037786541154060157364965322398999567967366141502676369829228131386373288472336782031595105444217571405884669605411863626838348018946307165003179256128046378287307702644802488228093403534455705767993247466041703074337257038005699497112821056249536681018118476777160701940161879501166857686476918584426908555728979291588315433166170385494220459739368210465032327960011649891819433409418903633681908754176921900365066522776418265582639001864368537387350911086425567926330047869352153751613236214534920661963422484493548455537514967037248259433981500954821218874414953984721168147799751656838168740922891515070872069509058717765349639311468375178353975293025551314672009174034651316472480208412116687845385120891223952485605965788963828620415805003209228024852331990291872413402991933362350590593032002287568705055313602285500899140748673815023199454992412399183106245969336357294818635081979700582127572863687730282795837152085496851840225704351192357369854054795145069759868170636835970317529805221565505324415031346694187357766478424230806142055201769288159660743225859487407808151691532307658281196699450787658250309423284059053700604817331502032649922992010327843638448842518542136037844298378276954410010736600990831653037223517926786166593543881371585962539344866888495307781172845858361504948209752784741330138454236879475029970511953952855950087919368069860934506428966399599951363969566901627169338835488517042525952029633934049744863716209894702699015582301037949734926625143698539931873222033936845656454554268510721787018755300462110800650373580045332996465656317246361646209544521327335571905854810345803153754512245992860149902589178141406862266131736607128421152629647821637616118200959541148042793705668620771643103734994839412802618785309028166400632769386962217546128031151496765341355250073143761491753891611217456402779984677692404636371306024513937240249961211500796705680948171997948126179436014477494132255299432902725816489310348077856796611098694084266996113401276576007395491687351451065461300076985340885861015455279020079536424462674950399622823878972909464981392951290961789772067903599051324494129845015948165648676705711476219833975580175820219313174448623913378576511894207411662210189848221074571937587871271551517094816895816238778515008708235276151731941543406424502902194496325665715445101029214593128673289008127554141840321967834570924287279412879468201402119732960356611723316208135134874658075361619118011008914007482039689164971586178936538124851291283900565665322185797313462674916425763763283635852120552672572254960435279612745957550862384769489609472037456919821808754783117806681801232457355753530838087998585145439415199404365927167801269883999459818153623079313066668846310244991600460861008342318218352609531482725675207213372763975978635002542674691561802732283845333977266719836225326874419554644684560776185954475096337568195771442899651443880922765720526400817410220005779283951957860140846485269261189616534501930493227113684770389882202274042723898861716615847696488531808983929462380659268586683877955085084359326403986774296596995770456103663837603107027155705134401939063209282459673490167379155238216084091133201008558182717843141868438447104744950608965163753710328603064205064928226935150708211281576550315979908564110070402663443620460896482311665411972281803031956896429308767415598347781087955606163100237718602738994686550703529272186255472415055405983009619266467748244920840343953003104011252783572112108944382273841256546627864948390893918333085676497647830321216172116870756342902779839596262052552869165638928772197041694614701835221868164842232261105612682250332860373657269676556685265694031783098825959574842119162265365718908644578696304612037502174317370256500413716498112988168482216360453996734723821947711951102376393683260984816188028926421679177795275923021731156768021221085749075485770465739056623779241066059435554576403322693517250094919689843486574403313079576051576977342873078934146999211826037395220669821868409189787552972800000, - -139844492178568884273152017666708681059357678417873673705005876744009794750835401552889630870376816583575846709536125694333017591091472017039546018213522468873653904836847788753434082042670363244061639614927464014207091856982357465924969727206147995747578154780290918068475200586241817427612533680467839909198936083500283787916751819746300590506456140405162129353889835326043250057395554732179943638728875090346172937129230956304409646274596451729531125083370451839275696368474349567488459673900312386451525012169233492543873040474792515280927696316415329997556877031611232311654403609833122492862529609215271305985638694599502712032599718971966040382129096736361020314993770371557840391311407767822978743400175133684671440459895258555225615361355490759229036398606428231946247970375696956289054059434365644131154737651715123624701813363844287457364037631062820796465045603118500596289029385878073555035883905319029529468585804273221476358062007882595657519308349420563460118938411017209394818031862802702483624082565568811878824587894119200313771041477263066322891409807174364702456028074069550348137286243700034942492413735523129696188996760436735930480319145601231383687973366440449280323539548281672174172008999176270945218178431860805588481545131702068458311075330414682853573417884761973564377005352515047616508629631442367536946991555682313273560319549993035682027379262631682063430026348850117873118524302462762413462245533417016907439679923657648364775958847188918533091049016828451360905167484231146448781367996993205651650349797224519297971801070106407549039461757443567225303420346073374206970695628192237343401363269522683012156238608580145112171682357848519715432857719737915181147309221357773246464754716272508334632864530458687576182446827092036030264722459512909857739379370777515289508250158006746146881095981447786620703692475396619602081444116074571763837744591110029579968807539777676901494585387853747884930933147206157859870647267418971977993978686991885397764151249637147911593959496933733330471431595571057246986985845988111473461741704250256559715436568639525345832114351182859638992938917116907452668337601428522601542177759260010309207264553829273705521878949227442423171246738734318047802153722183920133286670315027415261850648273167763132265404208443519694770080490545280073412010463724033815673385535194089794992481612017619046262722623482401438165714296349328746732518401172316492300510272626138503198954896457421215946919723973057446553180400343222407650301074363826344005117943956315528535494380047426918123196904283203733434539123624493856843081194338194413341952676657682372109843564857418557691222811783482494517133313264354341466778132167486869431157779533584575159395324808262977066950407926406270500261550193312209589069652715331415426768613410110137660035530501128349721427751710798747514072227772052348747754183650361529774550980927177093350953210315757910434564651564855315284383349367737907398065644550281249162193820559393303660461962357746534647701967621652152459364286646013885076254544630052430923362286775420573176953357625027844750491320181749567402297546373030821959301782327038512428683680740445896711426853450260114472289500597968058473209379446527292221477528124470496341859012670050169919047213300557394817406760286780477836449016175185638502285612447001547936157886916414459798520597937912396128990474870595551730476920530730011980504748368807892192768687115199475192468577335762137858317781763802945394519932888597499745361148358845023438795980662278668475713568224898626311447509918476623959233470534317827910436297018427250208062604104272042669807318850685574498180023095887030911162013438699239696670687449839621981128879545390633389412314871289770205451874069905048608422150473159345843909639945020134947498213172661561587929277794435296777922740064548501478368205047528026989565716663035666122432027349306663274492719901355786671800601314000273777946422920517410610661362421107010853372912203697654213432098263703691614113053400990766727618455922249119913025493856636880533533029338890245245856059352707578086004360191038833302560543836629714302986870610830501549683581859251580690930468706360329755342262517332399825521236625837773967762576582620772623587305795798632430003756806031788409418505323038318265730979178622160580704904128081612355314498159935639565715259123804248092630780682641069684829832407841403145913605360399563326541871367185933407925456536174924182682215335524355343390427495627432941434971677215236093526754602049228367129403898336632985671267651225759100121874741723852288122835794171202267446411412850043651617849304900787348835959801859065265633815592830680577009150980892345941890446213471620463489399305961644433661286956720759682310319748349730522472623540550198098454809597463056016892259663564878932061745751933507488993202999663333211029323605882466870085385785081972387256862254576749780342498574519181725645919215598928846725837771763473380240707734527400098641864108166612618251538695186422000989698776227643685353726687890750700586525210043710356998310517860925420701095644872843212438387189739846585693950145029576997140166969208552912030880215508055547060946416768070865908596110565685663092141191173062931211402375176253760941560414021978709996282332797103194144640863842254175994085148390766293633381130738168368667519466722887272633633362263909042355357560919016388699521675961481318153658519740939100849115990046949879322865417089800864459939815297909163466171974648416969528817268187014102506259192317858430533667757951549440000, - -185026812000684117680681928987371091167065628249293358069809986270894078723203450726024786409132875450629617361687756808906132081410488610716114204021332314770882166203624616276298819707338143767298143248111135682040114470855034347249006174175107238786562177898154261131156344494295402169053227528884449721834146078513188158133057414364168361043853249706972242637035770746140023230993439013442179046244879723599514053306009142814916476020170403245555130673351792835110066940951622592223825542411168790486089062641976043529745298302642405458439425149893018707047472814448218146556893006704646509241883620377778656337923672631344760621556703922902731799588046832423073906064320047531220785001400779908224206393467251199396629148445160430114542669888867055457760684493437948322334804903106044441029472228259101899682750348003393529253639610872855817523325034331950903737530605132726981317101238650684485724546874293222831797214687490466393865335709347101214532981076479555373855259149657247639153192272555719709571814236836680689561085051536641438124693715148212269667430066219243097152278186310604786596664677628149716844963366697702559015251082465664539518625194326607634066675360214673269336048944878305861465649771397197895865572858270244515151962934501987598197054640538238333235587364291678524969218125640858918831337819734780609249738460302345982629426057333630603217955756810763275036689983238383493441044809336290521548940029935451912026599491144316261868199797431132380882390150535343680982166995300168272057615543245700861064955320781197541150381184732674883569675207049328105065288450164089376820159595077662793818218824071327163507692385932703407254518254617214506121188954578149854263314157615205742715290748379287636817112740607056405249132601102814327009912814041071536015280338088713454164300998104262439626610991721390350130469337601190469928645156917153191584251849260921286358726214422753105822370694140509967890182891830335249448262367471990247123914507195645417625636216405941228620158120321699398499091853468355522499015277527305617647116351657682877994037260816073750045335036574826540328473184444744566789815660609470440835532715136971986586119095031551037970934837745551205373344760140158623229248553517372359120692929405853896036771980464612546687919299082193846554101516246103128155990197709007821034970344268754633069887041892032974805359956254451519433404832482101748635849405809679657363552670053622709851201986436249176802840556286983150016931704267368104356249754129092944768167611302493357478819021335043685643486407340458133797241852686277251746713730070395379702545703448370916091443183307860677716011552574054683689622933938381267069121790901099356452719341373906676720086668308894090932881048107461941707506856873806648957341910674876022055336564707907906893483795482109473323973679934389209999698023019616618383398013490200878265592647704957434726132712609808148187934196228736148115164949370180588874013261210275628844282115789130252672209502565148632058453101184804277855667960240735418346433136591651382183736979091573647455156577539913074537747919651074469679183350179145792532085606347659515676508741778010900992583010375339993286833750308721890577091959441830219506741519973181168330627107607643926011021560981990434168268673340523940665629459920759583261999707579447540242087180539495984657871058488699190738521198011382838964829365584551158164494110878460703504168887409757237921376556470071926266866999174040903388827771747790171270622624254772845398755445056500849388276805989855565039988083025022604939420534235396586991742731725501180927778343179617240646653494666541150935753495270342548729962286873115601932353514697357125829475208094848525367676432711721259601558617169718323572568641481649183732986368552408601214833184509139595870279160883656472243342492151210316750678302796223347197240706954041106261015486301287880706201833559235272864293270986263216791254694555492465194837016364377196847266268433762372498610141780318644432204315153296749707457918520209855293897399118312149355073433645828156556668257432851872433542709510177011925385710648840774027637323230138457281134182104271098076017340365365667659298290973270828916827173272873874394226418032704163412425870920747043401813874925856133116994675794342172062563976476515371527926555835769894908669854255259799218145533841030511852071334216444531713642747646013491726486025447290758424921316113374558296744704314086298353028095868218386755691192067911032035507191708559122138756409179103090274464252681076563320451805793877461537925543462136677848178126944814238324970124945174707760036974941743775789768312725813034070244419340687465103192290233706228718536791243720238196784506860147813872788976594948755802263258674500657406343799650023819566103463869196890567721575184742628661317902332359268359252638829877156455783979218150015254629532930379866345925892816233706084652797431979253504645159534110095435339455799141984490219465100684601126327292672296059467204739226278160433509313253617068744431314307297392981999560313935660991751003710540533830987122553228181556063028932231564241470938667890069462758683187548017902134829385221000983231859075004570139721173839295656922927531094030920502379532393741427461617734067119968017680565314812869539839006330117475334442680695905342493349138011981708478956416934025356182517555441733816381511233265871902761034366622821198323846587669666400746334216673156947713380566497876605184139782522505325532038291415650786146567999750215454162944000000, - -229942825321153553702411374586598171900044093396112359822095863638168363723189789874030429362444780355956789602802169811742131299688524659975696869790694717045029744596093254716533699504050391383893799768019832872091319003872397860452560572568187713953401582564166413336191547925422966539297676418260363483736847193546285349437912167116037393223402851544987856680414266280297136378946761137666414057991648780063905021798673148397042550103936928385936844772307441709711998323446124458006662672146397304585913589103103276777263529532412396296919545551853032551167866230728842107498299137629486948629664171842450603340059187143424623613935041382012249710400487872352403087305329766765357364172382506168678047224095515256964662491025472648692949797301235892241411751187861536848863108583419705987730121222316687989191453670385630835428531756796656264803971531960630593440016135200084116598641484153656905183532960454719877175404477289627478944969896523811012539925157076961843400798744696772918136010789728082996402316798855280067588392110472077855404011360698746431260564410171161813522087401862078245945305940415581599813364669619470316201119614370077697177312665821109177515240870396964990503579199052360368725768533996725167658389668424447694972811435929300747198282667603012729819271866821392794470012777522636227959897846408737275708094625936833931376369143082916176424645154812719056941774332784344487020236724665589933031760229378829512381734595984724158321639883865529848464650317376734318829684934790718775628689775093230020141078989456767919136988728728736165678578347143747277832117688856051284792276428604623374042402053656172710400673129824643124714953705234080417253995569630748638189190426958888277033436989339555994089531835454591762818735790407288998047266459344607442093117534947298091532947764500628702278235306929383867366258532619430264359127680412495510434447004149561321643334926094853523539750452086483015032124799737510757572718745462270744367211815956608529931108270816019677090930790317967150809529468213294068193731488552638005611195202982897542912358569628245654224351320336950343121854344029640744652547830151494281668504254080183053850662970131158940357487427045172729157753930602324972776664380244505310797455258627878946203945044683964764096045128591696359520949063951674905163403774286752954108543948252081494348707081338859123896212308619808114157136152252151756042642652388314854037408412361705266501627937926992120985507360052297100558732998666896363885884195538513189912296427182982521110970121027008692520774602037380909594737199440169533142117757453781901902022579278208067257151228215654531803786584944858236163663184678123431060151451281427320648019510843635764228521791218789648102225750565926561999946904016230887065431053785796033000185640547931098158290100428373280967240429875473745301495804853569502972608883712036108605928649725825116968288859727057951956529616278814285326759190739463650899445922319221531324607648534412627965834842529324275936101073747915301007805758907340918807360440448770558720311539601667315239684248487539967830405852172381981809344566061655612150310633795645566349457539775613935717815728190751847173723877753731342066364142668010877377295552129599529435123971935128534633185463474770007467964262110441986512125601027019511173239798244514581349583141285766657341584082921816661040182360431731812735238125939895464142710898552360970275346916775230254251885696028112381786968457454073545886944942776480438044533894167748891330078740829747246263069323400150734731639579127325849762479890708323511552872219764313700098031706806319405654253440951719475261167282979589932261920929543062640162750963768975549294506520481381106677380484872866930728916904583919969052908548108160184744706492641630126982572379996722369704346093621204117991847784198434244552537144128565212084377699343491608138757825114443912591656642197179249585025849500753844938248267788196670101708294402131905092316078994264190049711771665744693874253673280413091962524013117087219764904796354101996008530680179759553021676825520402883854333774197459180992098836564561697173743195887083369892688960190492206229275802993613445412573006459250435535167395993617852940021043384013399741590824341870914513203675539774720587336635880434041097183085476332859949597330210882865791327449341190197937043376113695384985417956240837849060975002474791634950871373140042817560032602423724142190528233798735429893375085028352947464641981839301939096121027869355495972117923969434580647791950056295509685830113342143570375925336915050778152847430162539676652169581709036004065533266931678819561523030382822016151963153287960940734512701824252692306171546521727481548883452647626229401349202531199785336362481926480848609024464024561001740103182152171183857656706092569411219924715624596543496353099044217790961684407400651435360265849918839903372248528759280097355704698768390478305738735251377043732570271697239644780265544593888426142480919616946423806598552631086743887585599004903425857762495117937438393272406343131735075017770931925743669272106424446056297670547597637832036304164279001658710082565353668877754321021145369839694771279760603208196761880842739189059954112626600646509813427218147528450900510757710555193404135645095603202479779077661237018688884527849477710824951734633020026889840231927716178382040185474479060004083273793438733270107832562789311242587305326201354011917007780451206910707779044469367302099641155355475014886359040000, - -268216156582672349484371280771054364360782148988828540034692188589657816103472258321966417797464522980485576361252915899636623267779845063684308392051999907208974365225066981847889927669273821067367101106055163289691091230526364303759348017737988785406945180703253344690707102292512160743812066962689234719135617981352000226089108659915470815074365041247618078064048632518035235040183279577778446194240858349520120781172251028003943883951926858396679745683922762569528486156799004656481022438031691631768276918526193578786524942646919571148552159975644522482441598452847349851265670747076456129879261092214338173893789469295865694913771643202692256913162637300914229566876276004102430452032124334114960446907979661611962748385677787731750459054978078865230632177775352101449542783056580932379551779261374258126598770033771761297104864874815233072804246199702445143039412607443487730376360058508245967604805481109973390806780156175464000397084062342502317193288629187086487609449717248482883857063564551880288987153694005488635344506825715827901331778704979040795349116458362844863579949148527354001013040390907498514724002598596249587343082869918121642356924765438074879835999087451462436302114739875882610978284039375073620313902759643487239827776413037639242357205289058224307074468935809353716746619388246560448850254729631885305226155409440740762927249192162027450745616892940564442097484456724229363261337725930277061369292335445074642221942341820919086603949398686692012270762350989969112555846613711892549514734347059512253839649154751791106697934037019104092848920751087644466097357072270535024499150216469074478112036390299279108418092412246722889002017151660434258795734853876095323820593995892238460314015430139788456688665315588079790293638996222640189862576187079934901755774934509082110968813920907368082485960044950582963205105184823682321171919049548681132444917738341020598043555912289723902384596226890108702784031505992182297167674200459780571681623555426952233012974779494801212079891208970238136810519773843533075546800998417506074242999239549868230245317827863908732285062758537359005878206884963747871178931893032004779776688076809615262671678203396313899186130822570808987672448970662823889384084106111659089908052878562458135393720330346204627366049507224258489932145861886174021771685521868938096742056402713391050316271454082201468618303076521028277230199669374455825126405914642026051330285074046383447784730216715851036664129416553641348896019541389110494287054747408265874341973136964284813614314867244649451529567358992031997923219899109034710329358767261227437713423444601584086998276514312178730536057056174973555562510453804721888357597422043304140647921189051872691836064929448085771687866560297184745970871173204452989250237049724325770879008166762185269639170629449638453861400007530553861552904213518142805141876795589832026794573977746045094318671995189948909312646708950427557722605138625957907864504130319583744026269513459562894861997103848880655642107768823822437191855126179081292358258781586913043842603219957910144504759808005814066826721015309066794679725847271139375242343209155549805234211914561112933976636301070861846041339240246221599630447560978293722663101917149302298444286977377689223242695444011504559852222952813703260989665992971878814949533722641371681680669827319682216936706826246084546047406324447663919779903685774591574857604256323743155516413023771543067752923516661586331518043404870843294226445206050776575957138596999283840627504475719850461459324752515332710111707841561414598617057863040537742257058765878339377527614127009915277047162105417187710468494371556951580785831603959472861194305848244763532608236316846642579778141393666412835527187488560959585821326084566733160373906462956431659974025006009696657100299555676284451456272773832681181513366571617040008005298998635081440861663366648128090543292885895662355918989526667053476959271210764708477312319452885293222018143809079669310798646570452306984948368425604382371932818116297335579381591452262332147151349074867396223932987827214687197927111907402184947633499031590397166595294968767739031841950112377633746608054937875525234057931529827395562960626684722261205912074060177521872656865436156898872781162943070052939448554111118748377317825562084302314555622762551683181500783050381748454462176074815258328766357719204083033135468315201575003778438353112385288676561639086368965712494519210292240597461653008112530919823960818163057426036127566822185348720732039773018011760025073205168537360529054566295390189031717318927114841052840511442698910730761509220066258899154752697389091449724101072910548038851884254091445404199129899693700070560180970303743644453986306103356153575036540464541114835720832080765149532677657553519353592853309916406095592862563475832774066157583435173929887925086200211144752098765593015810837665123749026772280476261225296644377026985494936231001690316423062053018235100505914627591723684694943643493695371409019919461932398554911199478520606681037536463484041995539918703903618583062374616771384697883881464821232952643712812755064626041124965234098499785299723764116320957722037581517617708245646886266075207206168777094956080354559449355921360185074253437204004362271073006865189264054165591036612257173251379123949543223487686968830304918579687589482714032207753762437018488651315230726759463472962227165624523669309268351238725186889313834103245211471715151831721343713280000, - -293418200613011330811119596608286827682248270371995390506000734031455872484625032533700083441200979815805488250023115461231438896138827381588016950727483131070651326007435572599740638864717721783762143102385817629206036836250136646273895316232263535134619461671697535070205924971853846094693368937378560113183969955312832547747125394568242409620720171888467725403759849603023603809146975029316656438241783312354209261449910861768555463847729359474577386446264212843987308425281043025930879809140609154818369984967243785016414215321500374139585723347224323628997828476261821852718836015022389012740417616755095000300976736598331855761172417444048791231343815671528324745612536727867386494386266410207162625675742018909503020757346530665869121483745434571122365649433575650981493887865821949211165419386401994993627704506597438550149767369427749054264023539373459040366552743212548878845105896258200278559354296988583160130840851230791909424883664420269931649531766154424254094457190998799263869874571630167623117731160296565108229845838028638776641487484067564484025603057367508756916110526239219321845091262220561795668245544266766046049406859739057788232522353199721109150724812788525463832004053607938621360285230856872095171078233053390609644803175557874956530074052447237261146803388394831451629431429665530540029483524688959081447082163903917305330605560848661842014894585508655752307199206062799275949000562123697564572829617996430243852615661733011402955977221907949719205313982899737655736100262728018846943712258453324574120343796913528385499708025051296710039655796618801744094421178925243854308094569271438566811364937947889938954374622920918854446201570516806410681786316425445532722688133288238954016722059393959322167053276524040042377655469161861793687755436113437025211181694028102194556081273593071360367525201870531403556251358907544369663287105770096691005445803516222070793802578082182757360269167743435456530698598757034326224456734368766394757766555459908052568252527357119782132633015162178991937770834646471610646326613779005173000124351697898485254712394112297892081080968147642446837796460553792093355090970810163128926333231511166198671935288311033825256103898517670243020173510440642411217247399536155774911476328075609845704100673311152663999076857652208171899377273036702135468568918090079717618374104685889134472553333279151470886577342387080926211693390362507994761364318886439395622414412982420792608326533025242616162510211081786782406873772741867166929728987429059781898306473333800687267655618131262681912181632471618464807593223996176471448129185843749800209625606844990089101788390304838577106103568075129082420686306147899552398746084535281642904671143032341388110459782462015039127580234326369235725385457229169355463668282833497665804103753180611350136325008217470111990139980565550527812845659841558779606252050648479770877076407189569026312340182593810724011608961805571309609547205670127115451190359068845028290570371593123074269663377674895080327611375504694218314847525108964306476830562486135450038332710081587485751609325421349325247406041402761776858070888527222011074201032368872423961296513534957799159126873667891874033986331918713189492911616624060090784878269234438671167878388949133858365868601681105545044784881040797724358300821220624175103502642285956321092915164108337469284882587694848148035996678724194686829565049531459308637953788156055006945750316144807006966360669959619282928870078813941199701271061992002935320920027457012670621748752404905948552661236146411612566986038569280820145410928156125632943664788130014356689506341190276924390848266221448715759224887295564782439946472755026380695714155559393355850859051046571131587138057167574359708318257802497767551064087720145106578314499108005125377660876063274895426210055688386871216709853121521924648285613884831442770242666373316419984130895942804791278465504234861547484265196734539301838095217239585160423977746473373468676308962093621340211553158078414959038026912784721797028003997455357451229064631575043206548700933376512261535112369489548342182571006591115225190381511091235639326768677919789945975255549185325862039852465339170946809910502215998547709412482736691972696652750136603809340682392709177463491120881322063318527293700484778873221247467952608438169252054694487057760882652632287309510672630887054972011061114873593461985795961797908027062917664061128574472553121884420725971037284983683917736329869311940277185962290844507401015953644023758602227976961872624826625593885399449983849371700744625665308323518848705754531670611659076981032780463798873282984826848853489230103468132546440014064448320643647899279929913629237026046233166653287323157536237753624554406714945238605143152313146309962194051616663357346957430610458938382237872555606474277352245923659124278581051226911262965130823586288601305271380320543059237806762473055000277710523871549644162859102837082716307625203204289141086137049496406771975866922833114559925778970229811195869796540379619628665505809377057724182388240550988257523258893244631990908032549238375975682725452789732199599092692463339394267680908296483566841984783222654662462037630428683904645119030716117427211085132085345966444225532799925469640765637341359390580205456305295994515685523214988031180864662078418328420505656338651120453420955514099060438179551049627026233684280388200215224827904520475522787068854606303466639179089182720000, - -300784995849241174446061401882684190876638147573639688285016931377432779887207488712340007051249641016373845933890535081516103471202168719396404912462873122812173347846575723385968835258569582271211266449200990709506710362851717555225701811247626468850480428472373765173257448232388145476238889707623027238254189604441930191852955489078586610675606397405158678303864866194822534420022769415708148041280129893403338016220844655918908183373481546704001423073782249018904801757220033856602198424714408924572085389225380048007514079375118025671826701334904742220222754131340725014905785818119738913667322560555823043165332604850230245781475140943075714317113326791654143174291762634655051389110941830270267160787062678887488404963583284143376419262261501255285326217190520597785760816418836669975137562881340005133394053732291081693133774171516445856712142002736248318473433551106408722310251288623839507618402073158750581833908796977246920405000856086705962453775471944505408829480475194931408597996912678397041946411881535393326070227490264784280071246319006725381633251574071552018212441488788381500194837881445828772869772041535729741743380690233536537423382672712883606475693709000701494701642465452830330141689657713158506432550750406571804522410230559467299912407326269531042499482070559295639386319083390093013052637107152135639569979207409078957245739948682978900441084458887415371651976862668364875972772773678891940524655274520304654421500097695177137188665154475629321492544291759979461959918897034434247568470045969886348046813243014042619393333464683264415905158007950567196581060705343234251613571230624270908408820559273519351760161143586596266640191505020329250744325869125729818603221929301893969283640106547031287514321377583276347710115427804293004198891029493026871955484401900437655637257602517841740709190119438963914817579401963451083285326927461923760933571340068587542408526653976812440938532813477699571285351666952786397967729421376514414386444340761386489771116260808452370299762777174511702343186664294556217016044106192307958630815169247269035017526409293129646567213477839758576181986248010191977206483711973525390446166841851188973097918415105947013462443643715051325536737782790038384237201170972942760512109015946339597936507639704300081619395749813794695186074897995247423872589633342603235050696923199068415774758589641773825342601405767726956752254898593340175059050343922236510575263281325486518384445233363927020902132327265606161008847528518359185507772490133049138033220407842196826332818030901199355826785110361836879584917700545599763538630786935798666381425937336201302455937883683265867219536074007919851928464345049759945746666597772238359260386978913360222322267849446538751077210435284936381649916363715007493205424507400769348157828818883144944213954983335799679383705263049453499933563376623674641345391803248255755469651749363978445307939143284359687970848596129104385359241387241329452398610105104555977799067984216652210216326286984985245434762603286928182121392872331605190543118661991444308427109892942744675032387528707676061132385337903344732851029203075257963868007535389105317786603657531510183247007783487850083747796125461700096273554645375275874630787192483314122540690312604385282992920815359868864048812404906812029010655154646093545439514922120092090588466429843547679296612284275758505820708455811287811774495693015955232906932918170225300998723575501626917486541511823043243398155448945465466515504842279872407598397564189111880636752268847263184009551701501337803387239822415919805759347759902247153140754026089332709814693914612698765085013232772280961970767791041325343494584508534423820206506284763107307141374246461029443068201432216281959439872330782308415538570240278400316485009247085104569911247303973125667256408534529292647618086891126034504631645363986803898210270658818064771847120752185186786124912203311542300042358128624174624223154255296141002267998509508789241872098637006442374061270830107693721645205180208871172344936249453865969764508112945061899335715808284133952778468886321010265883524948175071499560278634416668871430262552124844675814189426095111178143276372722442030569521568346558460149236468229704825023371406948679780160382999389613286138610570598051711125164012958664989218267786696104687965509582684591381643805015395540008375390637678887882134395512137149580127628938218887872120701258147575992061272454224621737332856289723199493400854518234513579917109972257141448752515952323377658165503144600580594899721571302236463070330922040835288263314968879939508681926385029350488690201206524497120150471489229662792044674595248118840408184595546861901084828442021113274248739559682115976973840452096415582759653529019521249209212298759144889690993483690728519176548482681326050776891757011071543453988426856010668777053271512807833610857248661220203444521526323770992752842606887732516908571715151004280586463490150840177797562023309654369002895229471766353917044708152126059877910708350920501921869473641713126440595647890822162473828251643684056711497373273025504986151932817444950452100358226144137879035042967421920025381833370248709153281936129547142495932441476603834485792603674206810803627032123634428244165115506736152756849749606155582031102896426735443184461213120779786569429200382962264976079459237025857000262810314100151819971833529415032085503040933985018852605721313280000, - -288665224385109083811301730473068703573452493511459426185287329156802946745949224579028907633956414680160082720488946921710810056414985421196206602184317824535516226700549489538405036049088363757067033149592348005266229891240968755336942780190715589106428185559933121542870507226946413217356556032532157904716851675878066093152695405287028881358938312687055947842327240242727132850436005888279866532389802102152941073186464216936451435976518404031412589148859654348257790887214973988574446614374137538491426531165803563361855133750107420195616918793726231137550462638309769407011334534144653370340711600068484018476797655327379871670821281934682724732084003324362030236080437184981813925159977843088181288320136397763913629740683342706304640473014691493423713944164882951800410856727124538733426820980487585152026503175519714761825792013605345001913305694030043840458421190531906658188192234815211991987916662618216659086665293978669774314707336400247702739808395007263464200028810373394269794723464332188867016581626528390547758190057894514582338102938125339977538480355422783064280218998379501580043111649197005893032838091341496801312551330142512816816199029540906849116002879143022816292020090952782439151217570596772090731239422234627764190562269745749557034569078070847489950420988711305204724736397581537753089052547713903896072555864652848574848234111379895071936353451766670501461710153295791815041096271782777561199087627041177430661779972819117926304542976388713354907690720869853499356106859765934595776909163524492153135751009671838481484160087515376960939938678941311935334514095664612523440549920632828755702527949820316722650824771934534756287109446861586593364822242513528585922753809365790517265744546250708162809620718907864236487583210960898090335468806988870991253488858851986946758658326368369657607137398020358490719179624946206156979864329693708458107603120004181749511941687246360634286987049747987780819849193036902171002404808783470902495744813280958389644967358797891108211076711522762778865701029654456307739901564698368074552886020440919408380573923571051072527826375753180185516346213915248119856916384846130065509666162557500961672012934889314369469657272885769668193357928078766623146693813698217080983579280912854586773491760916971326445256687484660179334982507564481198293434166391110689312979260660130114611693080788737581522069023407000888864497669906032332396293402838616020532551620217761542004188690786938127775186793802629170633293422379400313177433038465750490224912382714911259247374156169824150420947106906850111610514251921068627955741046915759297489800631161272512949198911869751021198652642555553919433061140928801512512778403344679795177414587241001996362632869088185595644666913503026771901407835703832769506075318757860660433177692140354779928040225142129513537427157331634424883463692895130210244978555606803542897235778279785589345079863080195133588438084520155489405036948487055699960850567751712476361607982825781278846267633141600336706109739318131967356229489148311951268640760281676919249463810636742293542303305435008843180744485245794880723189073422790661461429085878668766047524186617793785696947446139771447205683090311790452993257230225643643321845661542797313829738564066352566961033673116176972118017242588288170135424650431250250612958164125300895496121142824886621857297499283341092260615707204678276217606278137230613751306246025319619333641219926381507910629728884602591562428242402586258279115975833549423427083472281593011815437670621384811848208323055967682124057869015795353728605103790495158939000942351004501388657509207660742231406614494951360309635318782038138122107255795737815168971430132283855792608693892369392431359548737115220751361498892528517862375690288576287356492565854336938205984039228390605942323863541961918337177825082346937871752244262207396227847012875751395262989713504090768230934008844996873580891166772566126428892486257952194714417438602336148646163159398978255138985400550225970755035484065190073000859042061086959606989179430645620258402818574950167080948745274173226803841030968169176621575493190267244618951184442351966093532726256242873452717044882109196980689885788777985903183614833968138684206794482902213529240254227105015127469034244300702235118763711338264855414261976732782199929505336250523770751057546614407259261205056888672417758473841585430895662705885076478915926514835833996834906200410600279521367861425318129843905221077450845681618428446074593805015490952045663102080079467594122502761977199871879461538276634323490866164929280175251430865281977292200247038761075275906563132623849355417082630463228261520195203842543928048822971565462643344622663620780619692173856082409802185145351659463747041006939433005475662134179241927507222437529015518170128200488857246567626702134739301405694999349419705668547667558324060839810868604793779815805160268469491390282630183975174011336929856723457427896167800572989966748459063603534700187461473045039947069069193200744709992549058036727617608231850859053363648631168656816652366347770777408414473486661270450092946703196755844952744496568872688787217867867098052112438959067880808327102718185753803276395105944652150539138922734296114203651422086191363901901560630239114349160468801716954683810186285210451185009106938013847526303937385828353778141021860430073084075925818092371669155840000, - -259104865626421156848538116439935573376761694827693255038894743343901339128321494386631372729127381058333007201068016260764531414064261643777237800668889858448023279048486522561838841157987057026444818483454941557101825380693020897670263656193509510486216048762631986544905789228528504036722026616072328782711667157208628549692778206636771880731505200198417646754178234844453478921384714600570879367472082778714387157987552221977712318548664233199805893989682959246122740969626428833657515517596362541045964785537020394720521772080260833868620832311211736714179272798605323988751185398639050492579574000405891718755097483458037039783512972279271195769899154821121933172150252664594127576281394175977201806347674488931874641847082204162448200467164989079367109798626344803576854611988370970733183449429544563366664361632545463883736290037824849228715783389293637256049743854834931455519142971139219638919172170049616800760897868734681731544005977126364600072949262191701865119258402071905735604638068413207415463582190981150367114440579244961945203723584772962412303999744849713033454929034919485738814808460543058448870886941125064297776056018047290847482280128679207267084809596030605321393032353354460670054615841972466088386320319231401829000970680937582723074291972962523968929127362869696637553160533638442491382541379832310024394984180018282436404276921546968777244844820262079630711881397109553477250856866513761441463850694790637980933601596592211199223647062718168023006803802213017447985132913462302457970337674684650880623755713578177703575029136963634499633603353711141943646055410374827695473561242668539944501845948810746232050848325047848091071449961794947013366477003320635344278342416644076852653675702549686764661134387586679096711912934464287839147819070731397033204117270257005503503725794635081498295794818769153028017395427869587391937366097025084947311468929318391796955294046234872617799225882718457722543807810871330241169308082840063972241562479780153235397995686899333281108080152887243328289369558978842460579887016394393689132354695344417159811599592134164856740760425735998468906539353323038672170105518662549604901549942156863973931487575020465059067657864153801560927676462426573509783073000901402508368252676228302658992308548564859025167151985464433990718090320790668501779788378588586816826386755133811355492523155452030736292038506740831490412850978944256295308197622290257228555697690931477887010964490167798088614884793145896216233800560276628342046754415691452073308591073772123791713249996026633993899578387517013083729188899673716819290140426199071406344653615038014567021878396403404259768868474619627013553344195462627903249383530185070772185852442650347170722333115188315188238322420365342559037107681744851775495349865749315741081199421102519707037138582818213818897043164157822847723962968476426589299960831849594057240015706662261715334929016213150858165443853366434312535383978407820972785463476290844576957389389628740664142401102858005203919166000714427857220755701293667407216934626459985515424966873912401288859101090020116162175523499610047359461865255366915723020608127277546264647823075447970216566301494601921026992324642659878955718858936322651157991072990266390510654508544511187677905613791445199164908449130711718409608724410386478516226078575017238726525477922054267218220889454227911840718840497369130664600574002627140948374910535413517286738860830050765142332469667897764315744061386938546339143487453333599796352334818012522163596855969837063149370662577682812031381346566246386340641119572744847133700781465997740406442025025037307815832580967506479623548498494512167597139930532392340421166515888484107262355257268685015563860564611900457076123500213269743394795588342632860165420654259916584192532860748970508007022948709173388594336423535102655712076581309099914087670181059327327147475301091765387013554265936878945523637569561212283885928200161228035186751203230453544490814367139271352639299502082003127311407063551138639360335828655146134223426627043628251191833005557868605042130369169802944682473743440445363595982713998328042526285630274016715414406333644011008069828261476160046707652730287435017318766975802895009007751730020606997427514883492398287391721356499847155829143938551623962471054541225688894076152307051257662507992648809437197344265456003677175708867335368883817254980406492011299212620783689621794768240780727267098713065232986813056838528243072499507161966059271826760094574184681624414084575393056009358180574858582497990290969784009974058220037695430381031415900268846744452440140117429204382839833882190418500971441209933595721872678362064009496477273427376734026407554623942288386165159012941743182204427420798184081090321231442908825188495176451498331600151013054334358192272253915360587662058248310939048978353498413169146633865517359890927183530707906166187746079477560170347718755294231529513829599161931598696624599389324793646455517958580755743441143659318637226119202710417900962017470335137607221399958684603556945558522454290042664624354379624077186948864154579036262275411389551704335408160897338193868532188184035513552242412286895972823279443451653289666481379657554395335921030422031652745865377356476494694399451984204851422024475575683359219649327464410901419034033647959532718983369739837586208819007979520000, - -217291916616764882879121626699497369280809390486374457032838236425924845992110696534936981543106840876687681490367186338405291574904433956757818919698540177088428076265566760103918876489004411672434693794047309356397214212113545915046016890431648666201594828785498172708377398394753005601000383811343550542575234408500144596676844406608665482127822397985508959667731021935762193844039402791863595126260953631017681392512737427639963679830899137155081653263699133972216648220100428448492166905333220452771512946439555725528878888650413899349478195541681544426535538992419173639445704092965589645694448345938322675721576655955706680332530703287026481926325137146971623773591917583614827020770647338846815925083176119557265150812679200425849957924348667265442421492449737925924448832106944540007761040580850304565805202589840122333330891461933045586163370167193036413600728909500429189396251911934543520550481075815691600714310953357454976960185841846371947087516639712906590540141623715122094102237667404926628207260141498977592266664058128145329838530902435525087079687358310161907620900574026543284493994831989912078140692303772344136818732460138411381290366295396764342063933956189156807073607340555393046704506485257986449573809169231403979219033993443867181216948615936773589404849288530517809252561936110528530055345837961017766813735137313311504094051764021579193939339804960883955222011135042634120021975696818149854737548276399697102009243572902407480068785790158047333321465726274904069208711135175998924741140938703938923615280078176018172821923666149657303044742516171763017098372101377730118702832994743393843601306254528962525345642274041501965793070011221294174678616886209547464919135035128537378790912858214729266805852648014517578770527238174834364011265657237059189607097114401801498019811426644416605414934293660866404432466224922328394907662198616344788976722647157429089298688792454278165326618222827425389204485000994623306752249168561108152822817357099763285766193861406473223225010918021981121332200573937802150102748365676086366848565771229470942260711786367782323679414435725454385013559661450230676482093354013607139504404511391500795839250005012366958253272994294325863366335867560427251208206929524478671424814412769087642900405318224415546422640779534696036345543987390543099233122176769067041602741844802167601247554868445078824429005946415936893113637573823010232006045456546132490934591402066750173185051067142327151085114491578377424486127308012662284587296958213418605623608649563522756645271852966429869120525943655901956097447531934878598307478774927091603363346563176091910709008798886599833599461452534166317484544494430888605332178036226976858126410154190857958270900741951389897654370509570682024313550648766617266686471577690868331604669929840616910195306872429656016669373331769171342177318764121937631400916078812222210376933516262708780443817879934712153546183876365010103544703412847193426377900093201427899139092115703795935465367006388222470865863789337750412107222741749148867867402212995901762844059037084147819652513871450798494379926030069195275660840388044199965723094515024852242511304871578001463724178762168920112015073396996691967918437061113248311185715455513112170921058700999984738720913508218863665642269832935187193034965145204012595239057596135496804837486309326950749790203937226337560884566624343984844756468633446216830552422130768937194082313475877799568427874809717196015873588727902544729178543918033625029192679094275739422845165968045133471428027855276651114579206118453150365496825570376093803303553496604095039689254811700936425142805134113837202492324377806996453597865076361615649490338617362891363885493774410896103805203227613766674489530050438732880412233680624578378813944792040304060387069502385186690993801345475591722016892956848004993697620790138007950383053832036499683395594048954530676319032872157179128772816887654532979046264705978565850353653746460525994914154244132270191822143944623225269257128560822517560927481914467283381105284011153190778032380944427718503677122556564296269064928917572624845048969147220662706631522530465216660515460999023639966693259125801072032234219272423968394175876016556852738904859949067033987270046082412370143084706025561085597866881330282189455831930624620168334980795528952553227835860904495347414844014051193290373072638681766441310132699919696968924841638764262006895144199390528929022816188250224734979859036357163759616867945802651045737315529699373597884583911110808668764085393382578572906205028241641749145232636286836585582082750154066025263201518701413375970840305800258816676033438322211385071554566687608437503879889887026642964408082627849116345335277270411869040579544617612356853405540382139391937398156858661270773044714674531887306471965353406551747295780023316474655146176046969478231964109685809534422708829036194726385519895964072714378684928589010202716443961564503023051100832184777227250126312601835514046719905635144372226659607705377556162018208979112282466533723056659238091727640829414643048283363825325235433859351725432091815613401732125107847002940196106381330938279867681353982034376983676260176321113018823700893363140426323043591110426492867632820915740434596467698794417570922303346534475560329600664261066825245017784132595477381120000, - -170063789519336922305046011420705075666301234332999701822724646048459704962189398108154567644776418566172649940086358574575037899719700708817249271686753687846724359909708843253765778892336497544589791579101990451731101880726036499394880595097608407417936025348583338298696784736998080390216132815895324602843560437870784632929526203545654770467868344668866824113312096210114387955195221723496851035596882194375109033245995757402567426202221919775443088283437265502796704274491139677766456887214531513882190690699851552170196919860520296755721176452102275892215082250742419429649176775059219961724698771076194186699591779832397549853664051341347728191433046880224564310884836832692910804575881661105569302779280530577937893607558495430244157607082541967606796049058156223478410624098701685118056453803719763084536652933868396789348032812337264255090181783464511750244222378715173374025521265169206824417257983714580416797620468512998904198169807966619364818145904238138640543816045125725567283735863999324491016635211992859644485115090376172718469782657611604709756450246022667417972136875959115265008152926807149020022951825850990745412222280771449178684859217766946360320697848344887232032575167597303696803857033377854595061622254145923306331824058608096194218215107924629556680202004465696321607046876469403461327759495538266581639939710871521797067680777530600049334140138125181646306559315066665595914710178788979113312078232021628319235090535273262113457390101952047737251473831429074645990113233496649623497290387341564737297367074987357571677483227293809661213410709420624474521024760149928602494465489257190559444335528604526901303138547038977515555641131466779172780519754184370105513313143951484528596531535327216758831742478151199840695820334685688535483670780062535074030179555788656147868432531774683704034219298505955994330370678025657125236982522738393854940761797634604214609283253170545728085520461881755551584495612789155088781759661815756670083560666924671860361337537437150447434806499461587573060007161038563346834137903413630351488745498761743342385657962342380827611465437786633630533133383813596658094025378924946595184450692617070302386591151846838166444099894803455493477200379135840755830035051710482767612161347774953366417148169212579645324928734757471116552351886406096747770965525437416067504226168150516613428892297907249203783082302737722417471189045224141650278782007289693001875730328579932451410951740515799310892646114541587625188904554820042947479591098961676382654672549177866039807792245291310830084280258687671284665332036757344561868683438310709392669392957643302813354441894234103905820865218239399955607794649708419307134414019524935156645424496585228728903976553975327553400620036338660054551582456141491093771245538952520566521443508558846748832084051786475470221858848167255710116732603288952593966219912477603069404480408510912977999975641104779010068448970289105721472458534128080508230673040742848060839581699877349245556134132731392341442001625322498743052641076193354768081747879830998528442430505421567921219502962226380382492111975364911244428814017106291473688240854512346114199111549632303347717428043408999094675213799577806934172728818616652778977601846677499941807250821554480598073805035786465073347646850734403886857685664985055425195478919181545110297920301108334089104958565474136017695888624002612554074157931796132768229996340180795367862814935465707808433191548612433191562834562706090475311972570112355513379812688331115985940571837383612198874728979100486771592161773160182892765824431718542175602524906107815297176587878452290659588652155351175965123238757025336898435592713962516716689310240593040534194967814253023844140684822279321678183645815636046335143697410411587286304000857345941173013112615266909098297450870087870550743797686841180716837045196614616626866707252598523712044662096350040774925233001116202751453337123924278493434917787645037678577176447123403119178831703308780291167973300116112906387170517716713354589290949405482800281517690833171515332531283146070845382024849743223688526548986672043015557139274163804460275578920686010210240123457711941523395293469977752608368654079407801893708894240999342627119532154821838429858330403690674732001572813147090767521526575520406703269949913605685847546387136812437016313331454343535355210733170257797453640324673263002896974348565733189693568623967031204261266383894744536463491164104508243217417783488157744709802788847365143220054465859530415894929013409664146235157030363806588773596136976204216251421088423251620224195985819885349378305180360802435353561039851653063940720441865840911469300598832816664820250240485196558720899481256565344800275734959100712643889537275138095381044292268226979491834014849552779771095148183128665891584239696393023059620431683087490337819636482697612771371911018848080592603305778733565965316662777487541836336034445153960503319536638465510823115585132534879594861779343864754833065068543117300346120108960107105967202829893549283713305495249610628989780595749618430235979737717065694592487603742964747589207842544497497977091697718327337883193143514787427017742553072672106035672970493426389384392454627704234078387484061028961806064539509416718339683540530742466835628445661252288512000000, - -124068522067960624769778038150947361287424972463020763700070056629925413783548903288141150133381606679898446644207417395114898786117789402415706837933816353973374499489781259611549439289950988848759447543116743701340049143063925727125604656472952244945728162829334529713354849468102614433876263010515719343977952058289545479708292975504706943066544846005399213460759884704047636693023313199036405307361000433891343330850126365231448819804205174639711985355137578944125695306179031893348990155525413484369744185241603416232093746682358632205356667488709652911030344956055126715831532167252025450114112698369147170086884421409797802338253672945541342947262555492076878660572330801897601633448948234017877257995006234069212236780066659086290643302686639508069069810596758636583480251947768612501734732087132664457612972660281176971662421107616738203523522832632526064922523090214620318540861167148157950499873698164968359252985612847530890989873513374003623672534217163066491194642744686417877941645944814796771183011973048121986968281960061293017677970572718377550589701345715584600255699395294212438887201403484132578379501641763725715965465986361549216309217726742397945733754813206070509147118938466042374766623909651054936188240613370379719912807972840246270190438751384465464992771935602306219590383481582953830631354136168637385465446582110073205346070337012023916379190600052566016464307966470149297874266238193257801576596489233443430634074439047979361516152306274415396753803431655951496357604016388076491829942503716720767800083646084122348728885929735836683035340481875799315239499299111458811926402266398979034803008838083296035038704467290376899338864209482488094409970382637843351258560786962920189383660081107263798012313257959516283811377166775003182801101731669683634427513513564839300127216189200144814906916780400640505272547720810277194848642640959791995128233950464155026304246744302423353274797370450906615124696298836045419167319594854853345542697792409354690068108185487014911668971982556849745481350124662556053778147887862907602564589781966303569816642876714815987234959562682296294424986700555695195982458078567393198539001021380960269273414179239927308327967410033773267710198425006648489168964810463641825529060234026128730643482281667322183554129518174891598478848930938249697706739249264855517990716890138917245947453630971494993880470835207627966941336426642939517594102844005817802011585956921011562827425370192868943179129035917484218427392354037801585092051872870517460378685428227161829822150362803229543735874496150438981061243037980211306419232539647445096012546132315277724885608732512650978935053459582999500114384481961329069724502282028465807546660382327556514889497757522061588640844815890126821684493505184510904184192402006834267591062452350622692723926021009618115079474976676294410302765705340333748165212615612697606426585350609396503245839093173364027802248825676693523636166461128134743798541916115120613582884274440061900633040232262452629084191528084872834029976859856101714220637513245490581292439511064481117962708955414021322146023735720756820324218968865576879719497509196910098938397532711134069205380523751928814598018673974106745237999177385808603227719640684644499795251154805472431369480075147750759731862033138670303180623847281175513425678844619155717985412176673884840245433309368167558574865346206108212009796855532428190784682147706933278524945865735237524107065689418506500789696069423875123749812859672410923759091823281521555355716666983849908738548247180581416053227562897401216450078497467031888151041254386739721693688594054803204926109833073725730808069645570719874434115035439978026871893773805414724807387790871767000144726965967325935558546487225714657034879599324014869563378559347552623493440765056252179208880454752536722578479625756019842727457832881898987910223636254594433345227579874173590062516355386672192243566369487893793711092277753534653005171119293550092877641662391309676110508551084191779331490871765161368931969136852622634145649548397504628236831907578576899410223728451778923597044419228553661443700221685405048967607113549990961151088048421224427874117396834701291609916450650319186995610187650023809961060822441911827840985413749813404435506008874546660261253503523494383664944632233658850049043496930955108558177361298060284480947206658883245609500803009755904333936531203996574648737776717201172870805025332741720204785347854430228755042997757319384736674772272427293695231176320569440843775548786768672294989808058235170150450965141685817016225203064099443677648086674440706925971865970699675122759734086738104969087591493945423590583423322555658110261769516222424043877326797935623102092307057905771986533701478121047278984607638351365985468527451854263430276555956231509812939505992285439843200881751463151589027214503250110212060531932691416191931933634458328642983586794248435666495569561871324657145296752896360826166678015121201087505695389963649191941320549338370817790980053657817501262450680247517066807323921974348143315124291194710056525960882540147301281772065245392906057863372751858059453550331326487091870249042326623755905169135498098984587488775285815897413827729087875988947833649185564675911841653711043307765760000, - -84263612247555779203508011925886300862983063716190447130107907009153718326798305185773731577666377228429862426208348607318414534893813465340624150239888190659900357535651827730622775368007875089375786097471679967675601888324844190492492085042955156877971373037418246148508404521172925022330278516199606929694837373437731811810030212711439157321633951523974799301377236838460279364227918980805234383251810275627406795240474354248675184323121558776312062665287530773793615036319883372279556063359526647901236375599505928445277009435321309369058016983067659331074916736331376231542987362916651828719857116349994373970912682304525402839388068374319451348924731080840103615430419640725403797390315140309145091846093850139054632961227731960579410741834549613878284594317837018306844493000961557160723284530219459559789440161235616184725123973386474493452568201520929148198671030324772548185477595548993644191923936724802638539249358364785887795771346222830476347094587314052387635336626095621178919359606792820337048733068852903885337668070942182562973155399782275883301384784527167644349699252902604126751775605095206783277412727738190442204947937229754934262568214189576917190466082031571332321566476969025040218883086332840266251273236196930266368714627295635909308941009734314257946389643170856086921886769919011689698541727833883335770591924565869167078276396716906228940081331893442355272412057677122813976472694619018394138331678932468291501929222243836723490674891510030740204214690737856543876053064108250020836111754303770581144785690635079934676150352432691708208530077214512770182521107970475072580464719462332762549641289656647552837364103159992470639673664159571567594783011378758180739243067651456015800973424442460324950662705956398402691934337343656582981066100159678320632227518427814804842588365716984722360273555637119786032763347801595775775611977486887832796233210772279153988635096530238815902642415694109732882910873501875672925389843124706960146085704426471530467848892417154138525965672545855116481613967158464357671013083840748701754316950090784762098391179416729582122306794074901083461534533391930027902971579141489170971062467514830499485869956218555930861036643221707933610483295680849910623755126670460019300510837833959858988104705931555937606994784813441539034397993536436068701002865297841111281420539508958058949546536005941741654684932215593534970808314709920021950750828690164411675442015345468603615142989525325941480020465231789640774069441160852001527277791424085842533661247388061223611321670201130604554473552395389870879885856193752025115750331045460736629697721645612488330621430630049450652773217935963723935281892541544410816385594756432436603747110301237059004516067978006636251402951573063955208413129428330281302794489991244408628104517108210648042202809542976106363194037318745835983771452039303106961417771648962733970730346971018784045375164767911766936840400579629856530448395833140213618846095565619743693781592190760171515836275997257417600725058869347156857101781099630861976489373875706103495588453141943936371035057979821362018335676696854499943598006727515087425313376616186017823432476324883836164821603158855947026474301529340136556688835257260808018584392131709450887832463755977752076646307384810960451601250641335815037946644863045321347450661711674641751267489984355212297246118001005395353809112641851494394328941233340093322382909109428662928069728127751949522455057478533282525384648103303330609507314395715463160963284285391687915189842291117273833034235108362134176588557563925212135387974051326275936399360243259936292934686713894518892106454885048491726054359535936279215329166193024856328624153802077785915060489534518323358934977837350138024955673392903489766118747183663850109446069865698337356838500865533607482827627539060900586904892140147727560475272798225528020929633846361598696669633444630400125441564270208629406418384169138918629172180359087974562427297248814132763165931005988970191190865782183595195315149304910448799399847538291412492593023540418039007477476779009131400059500607467628860480584596688686656050686232236486730518306918475305987139213200938841886256548129785054997948512958043782297495557620742309613090012969933255448205580241889709206168633009442101225347505463253480593054390933009109666272162024840725945962116308152125837703906261006954346853993195678211124384541374391545223762566432700780691148223148090323389330778095648924919202675132784099543027687411395681142647698875619237419088497733215947962730141873318593831267338584966672531533203171581491973686761446567657673196830328220065786305072476643888908833791808490034353444892787347021526912374516171405554804796826856976203812818395513939870605306637095683742110937125256673355575944697059533948814547167762797516647666858237173744543622817303520149886290634460608140012167124955037227547497082038370099768028641854052640620857339045086191336303211923588361614557839783633568909358987297073381669261782898235188638222531871437660803722480740224836396189021626337671447619907496439415980083319225817178036297847581519356522726465907419894016314067261053097491060025302504419140449496818600824037058579843664916612789240736079383318788833280000, - -53205722122935447726339539770901349127981928949392854107046738433808944663096545442650493270504831187126904068110846255008379305983883365890794653312855954872976248850909586383194626261386027822685109993562125351353726415315255794611155721914176644218811224778248796689356116615705002716998602612546573222593280751237476288321881878397933542382692102825026559236529404403430050463118078391253355352111783806777926029017533940840645392213752423649356398364367267277653001773307896657540733171631339308034369816752798107621186922501563776049451580279986434813763648453657844900407096865605082307316979540354303049812808428131390706644247186105579235729096416321448411810982783638051021284398367730626078634804178490818637791608774102194925411798977869990431066955940911369592691948622104337126939017064397367647434296184784928143392546220045963251527336030443127131450534219799393411133324591398782547859859649169929413454631253276667206440745822952966009179373059951643128393164099398906006056887350317507926563727662729794736220611325345657236559448806406707514063256759816146645583135982633358961810859759083279032816374773129205211095807326617091091950585289628150328443855467298069953375330036004766154328589387468077717199517767760785407050922024090616527127055989663489049491883523561455132326070496663596126870810097001458522440130592089209577764190296245149830219312570348435134783561321649207368621087026946964589927053791438622364865586150294389834417184426895847227232809280379428209394126427272636411149649422686872509638721803764027557498877322156982965552992777202229765516444112170287398084608976937199607991320110093226138026910227021289512206300927318026582162653161378531285806868347398946651404415508972673875075249156621315704600306157207126812362726463848349636603141754224989866171536813531226102352590950429341115301167826129565539719999928199533073937540601197612575959433895469012300303137396306809892833730037515751488151203610986686645009011950699111318982085975965925205031702154057709988977435683440861393750541766128607848075947725829965245029705294659727251382803654463635706032584634256950075978918352193383417875355000674333747987202747453611691593434962164457203922944313370693653981064934125412808784244250832511465716036356740559197359237433328318542430025729236936221474845939559412807004022760000418983113562198542075837976514260206961942420727943348744354629762246722014765261589896813028081022919802829475008103355302964264632866110195071515888224820834296782258168639768545803252646911912559206487713535441506429513976408160778015259147327168932773330179421104125954912443932645227876850082409404945515606939608085241920565635189478494215041847347645486347314939649489108446403510773902087079955324545720296811227083590319071962903870181947194835657709111902350891390551753146279076670318856508562139943256830777214665635108068881785550339956687093521830971426631814631358897186445712400613786219612654824440912211239529834678059006029975222430106335741001389421483874450956545762532845881779020402684426813623507286828474304349091793234020862886231632550602817369596312876334679917665992363031846387033831943422829984184634164469600662719710999407574926038107075749097875438003356751868251582182354799899901663595589063958085510464665327479215112552051950791838357217381735996782593026057363386439184227825992991892198395165818071033897518129125929760444259264137358384963709664915394918907337948097078887304785216601528620931279685107679716951037525991627825146450140113088801128955714429607346191606999165077693506560002420737997220660377134242099109908559122859549987352338555004566471786793766388189532426761987036690305395408121870183253908566215974943225617122283888727738251486632533755810088619485403395672262798501450188550616616718537674825815127925703183775237129809799715082527775776718480348830215100377641175588125212406048317585694907517549121907209020622878215618411279883928756066359203105676444762252820405260142883229001511791411916219695998094374189841426447009641468702516869194691003417204288638594979538594567189943077669184174126363831788623555880224921156251829425439447946074337442099998321674988541983287919098108011884777119808006925765747470828141740481168420347213993709239640344691611833076913721570429964541705507962318305816055263615566847185036974931131212139491505909568717409617022855377950425036862047608043426874991578619115247912387525425047055497832164213669022253203710876540448903242350065458863417110525795684768468476492714697349592697006733501197114094166841199929215916427980605575300618295078418249473110564066513805799529753508081818444806038804220919881286425335214260932073116260233829730501657854235857341978768762817886343830142703733790809207875255688811394575608354846375473510450445296126852932527823514128287916225636542297745012022323158577045540690370683687582329991790831557802503033393600560411754046517473765905694947165661029800236283400025678376138438020214938193458789387158538757021824139067504836500823165124552537950079274280992485005405365094223796562253079574395999186616182765675444184379300937615713735598995051541801440235042661905117146996272081959649280000, - -31188086140440199279826608195060873581804198500620319806797162329823581134512784281154744060003269761504643459960119603437585070923375802861835727293656901182156679130759630722496107778782143722724863150217949128228720230037396254521970361034551805019712986737105579724616192640257118867773855582752199349095492874607637143334169079277960132243971793387898872755573500744613178512134204667635142057667252569167713967407674746235843287885796408123469498530938905841377175599052757932690931697953594791400906046013038353139188424971209249581200313377128198756125637335454666586334841507566023117808767643821514319310249357765547595990415109728328088239467643642597210445871293152183627017910017110000500649675362268317820804699602486122235327448818595828328977041068197481470622284222846422872868835199479123312806040313004911749727047845617116966432166196975919810789213226652493480275839073449498138712192528398000634057657953326812084614353471392711074620600243857163484424692293873532264457047340088851513017182624811476178490868333950319550161180950951441258459641472816495704021358777011409552385137627853942497104248687137505970170089961061609200529731162267882786604476577924292405326896294493676371408374792886761227761743401490745357898007813488338329693389280333588249951800801288697711395892254836813413605228657480873201399805812934479784158321796383518619024497825487022685663069827769432284342876158735833958485310913263405736410982749507615796376203250540564498954253432172016168463035359139295121426940386614395904219413368215673792621797531834106156882496022112025481875975387048795338170615513435087958566328624449624061442437722345435852336444956461160813939812954346028221921200741027473182227297630031194034597252063116026673666731168039824466698367013799254942060536228934841192282540868035401861492882508060889687798844952054126908830890637631476243166478970981251468991526575635913921669897569491875503756565818369256643330240126469684599547008302249002783081796074655464818010556648498312040815853286156583212321544830809199545798380826957684189165611448916776092084557738952908316068778292053167193568714925276123729966277535958957367344236181407225662402007105401632001673551947661836946201727489715207557956404183511926490878254361724792621048041652449452773697449323332314780532177199767716809634861842655323432331736745613569196176787403727409171675966897165716606965829960935540418238516994147587491753722855664318874748625564919501204298495126130138795018135348248892172319428298897364751945277813858593415068782719193213280756574004528525389194762455085301766268252571968046714757926309750513245163297626735220260263919656740692548752027007831685631581059220117897105108408633446082898411090790965766820723662697968052137860117329872749236765434999305432088682560529127926508423087971433361285461008946550006374639452887552114027875051707764053008264460142423248327999861022189059297561967950181782333320831135938542954327347118045901979605136026643788046102684260414515396635507027922096921728400201688314087876010746454780316448895900663550598625125211015298342127676262960117958454880027916301342852013758016737781402014080479624860838869059162823493729081809136243322062987485805483532111599621509022608931828725467219654629928529883589074365015672362626588203369524374511587168307190912510789790661144967868262453896580085989559933656455339105659536527802841490497134537668115028468905601695787418654886439485014186217671378318703222842339291002971950600262751021446800133787980493552066776622872709757382543504708033496792705833338416212072530842032934473036539480231263951910855869413351008749233312033083858937117475619268260110294828794980995882789744918552822128685139172175956055881505786428978083602953828006338024538208968302542500865835604973732739666357962956316108663390607033928510129253190468010058239811293738227408124234118014082513634143181247505786732374060218184127968424959191430043471966231238364977414338210497346112741629230099438670424278242162719906736027954573463331208496391603337214208559280053371598110802919980396822741233758047537581877702549950450542960690903674707450864857134332039486570913981751679185244370961187683682795769288013301497320166773698307849060022058956098616405157576603552416993169845502704711099714716828228246614697645733788578294093379633318033619338449103182258966983793013455234439884637329858698881606866385616205564921157435359141624949200233241111743631681635147850556308989389599860574155775231905708066949390082036509392121767550913193947217694638282600416080619495324529073042847038572035022709271999945052146282340144406636141455397301053283616776996292694227405645630498181383973378277895259443539919919200942845856933795765761540335109021037292663538549249184014028115268229737569841762279562734877759790408526220310335894955780432680681652957068864642154830995201866509303713010797321557705282176792212476182976398794643066597856813996085985830091655481093486262830225746286595491433242744939179462759245880798960542324894408819331483095221501366515663424112443977533831385856596497277316046373861345928172091262005284113856940369510400000, - -16945776601958433043612994363562172956544391513486482301555483513609132780456072084329296075273698507584852567898213486569022697897940829920750220172384903095602945637434961763115117730797779094224114104201098254995840189402384655189260945673376122340284545738157899460566795190118166376209780391626085394705210878290248242222017895195858490900758770913939685236855784903295507823816061359445469423786636433840679302431607330260266879775993120080338904428314141981420732202246055492947058878935528862822185349301274583270638269013577040771265680973090619287800333550370488266040704096591949933612428673676364740035280085170548990946572609328896800672283374295170815439610026911053504544362070588266139391056679835916209931579443183703032597205974391800627152877248929601438060976281738116703115422781455490264984161931850965400086992815098848134809866962771471381028318467129512413938564804066868864684946989274726565913706238044891659708883701819777923885984762620359445540651475754236872009193345217080033204757518747722520266619785858019534887112251480648835118036243386077592063760048335830545935161535662734709663991971432959424551717390996752901560186181432367863788177075157123040317146511951339204380100125428228418814193696343490354797259603935717254754252009475702849825370060544026600889245804376390223669405309123754011083929125848069102855544610012715863675578374318289632333743674790426914175076535512142781532541415160744690414178496539886170991026565493823160542409334023615369166083732618720693881743902277947116428145687430404393219490501151593468405111399728909238258863202685587393940258846789096599475802908597190417510377535513358137477713716105427366749606624921069657822061836140578182232599294472898306711033869562485581144749204489971478534537978937716021193337845154679373192901183786768119840782779287204198195788442939736510689799358323405969897797267415585342746402491850268372676188370798972113162822053586405113946306394570819928078678316667138575006378299768863420531098619479883536797204783967848218677516807025127552488543727600766944246921394230724559830245028208737876863199031153367126045504341645919998904129273904724602348884982434934847354003219653265588784389613672761234692203697708918093091337709131784517051989080541445106497209608725874760993187169533351651694191265274270180073835373951467596142574942010185107787096871945720653939921137362826101956526479633054719513119197172338525107619715682212915780686566728571797357642737034620714802465397143188975776283415774144356288600977975249522143942941760034551453232426615705820556610065913820506559382526708793634138304819165572186081485514752016582266635100560183081337874520325179267954392897316128713678025879980614434725894305166064517763550962931992346981895753708271902535848031177231262195411476484999180278637157044562315812377672146717583765082398066517899310534577521692072698760167222173853386327424687911932965872466526379870643860263463903023628929288135260247048144573513612251487791905747063731013040379898879699881022773717858689818437169138697543643190531763200774176412550189697416612392686383340973497157705752139560267555221570337284748860621372151402591814449788826806197449609201110684932369196625426560954108721420157300610222450527923723899997143763122624239197145167414748349886053060088044751203667739878708833612777697400560686903098756367866173395165706919479593246086261119430564229109313281628884728120022572664155079086534213859911646505650417649711068638625814801940888193104391074130795401444384642449348201056287852576909535543359463731492236491511644204771220950725937280455474367807847734268335875697242875158518680367198932934934802096368979614176256444057638782138634985574820888336095350459519154825861797886172819252806843219711513394037475440367699416271474964110872923812506944724862067237701249965793687164480806496532547181569762517055141628382405676582638695171096422979725506711835975524300597401314243240322026265189895491497483661614883653433799006177161873582452509622566259163815696520600221391660859176061682206372591977925937204073801424603130931216586673378025246536601704402075868024184326649097559906152341190096733424079772204905234195796170399583228864198586088037541111644325713136177974484489176099110270615166882673599260116237189986691920492984489615536659030497226436712616952856974120188394410760824974775496254600501858122638306468841140488153013467098258242164763933353804534345579290891003529624685348392565207187936423208492687404805314376070827222256849180505065403118150426781049063282253454835626613480364257938225692989485930609554800355564869712770642024131907556416975417437572767045074505253273306810285803985598003179826561635865762114471754446373406077498097984349686620856778976099427976527088015397328383102670904785703659140984266282121214938612765984905344878686057281053944496761733164502588425972929291490722246964516187799360140506498498805864170231449940215728458850581603253083498538422280199209082036550557225294475363771511498790369756964898096336690500812206784359887485659568682979318222947944987896942718206838853368545280000, - -8520415356921724155676641338019972666911789544663814454131477894411522234892956600687126038955692718449098714666376211241680952861427730751867080824012212967142453171143655840209607266351998427235023064834850483406391806146448851221479204454830089972380301757037301608554555759193910210139491636074876447753047776122893964599777202562963249617952461786795791522365287895968577408936563314979634728563353741449797129276851681228645952067373813936529161048718768365569237752644435559515532333633993992017057087019822947032559390367078762500448715448427583118493916967662271129698615156152438007714501336847254504060074541497912215746161768188695260247156391542983215028069171406665251021519345483828496446944080085249229993623863577054784893615034577798977028137222903723419114048915231800084908917788401668440377308558836249672797945858548961406869698573450833663574581721810164575185870771140167817083093172465042300294953527438907754964920511665488046010454116883489239425090912465900247246134570549248675180114633503258249050161316126144772867116716945012607110338126618469558770980492614300364204680273129823827329709183123665953400382880670033515037998780880075383615504139265887279850146841186024978138991699911340067087934328073322278425485957234567911503491438079523677017824937038798941764442908782686581432335353734110860658813383732121238810524113109772073192570086196478216322448978500106279558526919841904355945705187886117461354992611140404859403799376424796072624951393383419252280629328901662992293784152375517150254063080996636614911161709384351583030723665989748671048991894320238228076349088304956157330779034271077212815248513063093380552109994901870728924772424871910503662261250612254939656201559692932265716961887133722768016750804624780158400559075013239987691866099361306537199892588209128221154544899043121628576119321879865204177190562051856346169554084628487239729921963313839614471053068170702670635770081147106583260813218992618990130127659355603118554940324938845795899035225927253214700069055093316383590094135161562905268751639419211575473663276169179700595058752770030969754465873206837808323156060573309206794694844689465518321204494806023720655298439337545782556567715580133070226458607974490033255398436692529791619427882217971761214810565638936521103290570702851152637953211311524920688957598154490058355999535207965410497809868267995833930369687077658489280803739977853242757276102772921465412093243015193622921640317159295197140730600239809905086057629584867626531899630599280413318496553626672539121939581039905641709715878581232301253497677021395151844463603915725770265816733770918262953562082651736946395666447156486500109467261083166211052231504892417142046954263034810679443273847840509225163068834567837931689533561070133564512780639658335180579520903482020348118691929033627454068587518196942366666109811737689308871414632482123825991498846277741485343272899543366225398836592085240168118715072985223963069915880320744462295659568857277274760079244441164713083760277930099090382746517693398631559026185111210545008271968415106157871465291590589095233321044028857714095959611601580698464808285038424097299177036162442967656461430606316869892843821209862557303380438500636105624940183574275641393622070443096753137998146254540704923161482624802870378729672134776064752079429310184898112954481151914603052607991490980221708127123289417450479516750633460870284182219539395059627354689563596927311018960030325537159006648325102075636820734773397211082778500083034029329671361460624714882077441316207381154655062522758688639335481302921372131250630819981325884009761053968496406153194745421936350125886051442012675747439471940785677921095866032221627576476769161423162817301798357767021752812430238010433121310754385912347304263429891395812949910362956627238865304643953365728061759218714182755422680815820176557231923795131870323110635155231122331715120812617425114877620468901505975082365246203858939896830738613047228762768961227336655264712957494023613129303825058573228386020661491784895387579606973108578475939569491983852771983145558101150824077535317209566167435217660164756589718967756075919338845748245070805512638010297185275329020330574167882670654896562041142361393622341167977649026887138992421765507133279372719247872156962869587215728501699166147758186478097040231441776532816261452084628282379476478803358848345781234356265634295063295403152466920496500415534829070946843649005216819777973472285984282660279385473763749643453921169930400439562049477531823827782153606275532993412614274992546632683320514095221459093461229855762212000749471474736739824840361139883916976740594502779257421149930413517685610942130639867913980935823122718246354488803675431466676367892859862768435614807837429890970678074626710857739745810986084891808718728079247366784100592769730865575690349602445443547145614915633386121466918667575140478185615655915430495668037185614221354684981581555554858596788651881705824572565550109948852288625046895532370199883166098378412756777341776503354159407565269468921696099305961480665279197201878220800000, - -3957488651330198960208579174220701761180259457603337460758326926659189561832711493264667652825480417441263914209361567122773615239416375288253903557731375926866850127455389861948788647045656891681579902891857888876243994444218899390748046612855857662350416733279194312650448486823254810093927750534362957560620605443220815396627265727265946019392950045904288755416151742898969824375585768374480410165987487507527873353521368829648924402309946393623031369320255147040724314367606019390364033149888108342584065594842139979955573182907679090977085399958066791584176981769557194773651744369441539702936542505913479401717594491995773810812936123243531451290189246327148627456571640644488300922666395187698943392307639612164644198254536615895478916925805162876843701943787626076252139935812756241987831773325085160070955437499098106126263785439654070251826408471280900429906079674003378927541357161677411005569326025310333502216096194242845332662643825828565914598292184124350140424630718700254649198531220540708353536856672527527616725488882484636502851629173420257336943551485588570458713016130830494151880790300708704012996758851822613870498967584736694145477371097110929392541576116334489127789230726537720700775505136617371764830483694600849443323266075565107640494820603264260717932981274625415060279865660840165743641915927361822198286837036566697519119441462362647094594024310501963509644174800082279301104896775014757721551282313000251445630265923916421367780956121671440266182821361869504758524206136876955891672134688677214556031038785316919551875368516647992568075995743462728248819797479100366013303841913248302835428472434794356079455308102425020929359401991922636292783109074498154359606527701320583777346398221297907959787214059190954518169419138714486936301569266418754224086870573310936424251439316546969103653609632614127916721095245993038172830407108408213226638674662355844204870835597590982835269210388716440548374522008878219000226312190472193094155974832053571163718480972126850023169353493163654467041188707048948812481907397148227312078175705366606242255304670294316675878165173777440838512024030565882761563649204615782979576256052762290893451182770606574350234744133740338630780810017277210336297073984186711913275519719103435136747375952786649841096255289344184653288956592967952218737557659266179772734493399044214571944550907516789958532130519696579702660271718115944205202531547121707322899433111796283841338799408988664811380832249975702297976906269858723705823728539109421980960918103409175266453854574090608788505586513500862359849246916714361176142669215031344500326562145247620580361119400038588852040904971256745534454104512636816380936399240725137408025240091198133684094603052046257743823732002252123832220081609193468384603222477116900523802996595667432146181919433782594251652451413219163487875592750916778932346871327769721020162564489469761940849620795828599303235236111238437880044139795747414898286222584633690865561871197465083296387566623222821392888685814397502302431757407841854369596327930823329782341185041419217014803045910829852093030407337983752686207102002744900412530246576370211360509878602777397831671620688152251375572756158584851630999400828751570668554451585579075776223488395757388286042452618504751933198356540369514033069251604964376713863311261813422475745344146733036125376474142541550621723601332364537374144145130749279942154231338983316772592325931434429586741144983403617320736580787681095438023682733435283923285557384909380312218284786399022056730087585234826495338268371703126170441471081317753692081030850127341244727619854701394441597442984191922023929854093369779599826302878973714736082903629739905657727061107926971162996921049072743567858939080380945934798591334877985837679669244021739458672951850929838305269253202115961188236448941125111381479567164895403158208653785940500336634720439417579863400020053928603064906102658144370477178458636151308645278885283131810316274379788569200929169245592162387398557094916990137083406641741928351428928339558453503619042343082681098061254423082614505509537644717065095295012543452877896875188113971341783545224894140512248052938495329463223635116674243372522474485706949676626122323402761012023423201428296531437420955862879672406683916989998133837299018424353387809361406623672349816953912361872905556311816665137988206751734244499527467445683066981223085050220517668207238045482873354729843547980881906271026478860080616614632967570724135009146757941109097893550339171656513002493168982772893087705803951361074214069345125867501877899973324646088818306127714279000125614209784976135559820803181572571053734096154710675877347316728962056653264393620708343532266661091720471104111767070097829014493681193025597578887689191550225942037075381182857740126022960772793656596606290873445745243985345962043493784583979178300629384154354553725666404170889518691482307930860425293191290326897710056534037449305601691501452787512038927525366996500805770235651391956070804438375204410609049672628533388371804204310337099514260528111707750400000, - -1694782560281180555644354914953644235226128695569969515856084908345586406450557348615008128710981150952343206393634934426089033361441200211028128161107123647986710028478879769360622098574927606649569155746618534444616115044981585673228940673120133156109844844735046265007935955857131113416753245740974184037103363338200186273611925415009247646442500222814403786361827676171596504328680227710886910692123118520866681511789839946786391510263490509461785252048931340681043992860981888336430438443733105754704115924638530807593873086509951167826452303474707132184959757380651785305684070253661600551629749253579776136924029534773007573783607704770670545330022291244673096329832306099290160317455633805516387705932715243321464383895001539817926308489003038568659892191793172155589463475382094920832592103143959502387140126187494322447416984547578841257270462553996002933039306539981403332636177385534480158530956656697728665868724945119408835929104862207865829568530289289230224204183796223530591742803353114039962371295168323535548472108185989639483665617434778288931417926598721004767219096104281411674925005042347210091181287261646293150070807570846156899371390558113406776070544100377703207312098182305298164534866231699532927382131313891001709922865812397195186614224691865228878453739422992275862242934995972769741218018197130794381999341810669163074116595707938576150772998179003009930008541457197033269890291184947364923568857763934544693844412802440718984761080923821622032590013571451788868429613789613749217313573031800909222893665444901325052792668018750722945540843645522761742599008384182376561022930482659602498538423304033438885264734145466502523489759621234760153220223699993538544932916147285395590190291411709412417157708326968437817615023934610746346092957655099951233059318739299640082981439314066992113471404050222586348384170019164521085372576338346816242524907879932001824919708148745510345015497617658166030453811728632980730003595716183595555210980136300748819519829971644840737790926992770311363078275760467061931328002156024250569328452882678532696169337710085794862268339880246368729308757287479361403223621533812836936393206599320226175053346702895932761505999026238790520883575172207808323318181437791252294524986537439405780403469310061906071130668127705190542160890558872136740037507765248099134114686853346488621967187681167215039019951353696323903292646168941003236459906042315281592455092976747995558185757735530638904298570471278843540659751473863493368727303270545379314439044411604695763930712585708042817689163645471610088822514784985433945678534591497516844815726558883072202241151161104880286978715831981238552737062183320913655640137341935333138609063168177830547646971637283746456536267725548928574892398055528809496864726384498536383387530444562926033287009313249044521607473728324742046332081449702159324508310641778075719058479987106415133419886723109803205227016930639845772597369609354852791422933428990090996155293594129896192286347631090901663616796005878576008282141826893168169851864832283869023040322091665973301892135572052132165218432003871301025494687588630044234329813762763065049355935982234432285315652739055913039008529611104999832255232615489357407193609835089438519402037988651356524078576740910531425052056611468327129278569077469344322654716019188132929509209835732064999216908002848838005267637915666595636179593902162900600905326467787239928363738529478708558772637142034997559021687381412705452676291076476488555073301274218768309109743329971687780035130796940623043735040772080058297685112549837374036267455663559343096940356122829664837349361505254331257467781446762944803873501233856875732785747087946125761173673113229899255518966197415100468574818054784726662832211587618081003193912239463458045335019165310246057017098290620373406981690874276172936908732246502030850965354255569345358632281881611931028227410616868827772845801299050649613883256575332838019892526594990409169323937210400652484984923462846211835850808623384778312576098141055226793239549794433142348072724133204175027572607097224383052994738618360939013722449819649599717054591402982307908997429535683563211914708709342681782482245646455923716580433312834690372431843438208684774045437646093722276275271800775906840645190169818474204294264944706625603108713234055456461779000899661887030274384684344909103820626710323737041188239338560685280683644138220538452485505605985686673342575419240868860724187414369544459436196103498485556926638704890237637981227963248414904224359206728936761917255731026412325074855575566929625205891716564523647350994263926137400752451912374444106801090381858151914308928568224166789124827725742504733314488455821779476382204535192931815405426165468357160395926821705595816332382073789934325624069915216800699348719846222549837548852131576202824890980015316804883638879070707174761413716095266753223184629819979747306819542959173165045164783872212303499034368021744830238913364885644240036426900968399628373578069458637477328204474410050216924752642048000000, - -667812258689859698638339324783124349176234517556070016985435991786094233408563701178442946196896027697936259728224477195806341684961912375914996228558689606103007291006597810642432720492771838295120015465577150569449301172153776716850733608304424467234855945241037382232527358981165509272551398798818074074840610589944507354910115921147530391709399692933773136922132621604974229494963999031084130717213079175532970394971533762156877402482010678760770476885372659097707225564855022746477412728657776170224035429591143038381731096800708065658859317097361597917424811338277855037438417669009756044457920144171846725666258860468316200868848230583181462570480259085313945565351895066765714728803293125714946694314864511438594570037001546058437497998523518512543449924247277129071331808392361205238094560447116950765751515345668580287877869702902741472500972564704468217428806374862861768968858048931992496625169857563274599693094930406763308206124370836920315193029473967058451166016657539813246989800736490521313967578210133221297098000785141595714901732398321810400824302860767560741969455389477811307137226342056816205815288404170449883491761646196223973133776555897435334072612988192677038778364816096843771062987945427424619347879630198028411503090363436357777853264000715856543644133327359679692956654028296984816838548656646904306428035411382123568849107083682909527881160599176442825760044333693595357811158341551380654605973124882093468126740758883454832855509428728311456635523123026946745691242430817364326990760323608650338059650910314250844353484146675942179844238328568889806608446634915757986522035355145634379966900783253723385041769950060615094587015480199041660132180108887457581830593205929570402067514569765393741616738828444103876779658419082782957001189682242951257154649718045694257125080950996130071338431557502292705285264510445576523528948259926494678657474286082558065818691599063938973715462912654084261420467591281885995078327181232033038553957356313116466751199879832098968110706755425740157797695890245624200001335549876043283014891489186500663936748112806678513712611432680504477370803950872179311720950770463527520365741634217903418701631698848874348087093196593800620695569542198904118970461270005352955814220486585068515309326843387412901517715682702747968359095476203579349009985895947002970446592133548809660704128391501183655143263278837553965357719809207382088623130588373247198985325379119190838556580564064000099205479635814461973830204014503978820374029526507622759580446899828920725693861589815976182050209779531625084477210735106997041627810055981798481468823098898784239367254436299831068476307121647400620174293448467373429035256203258061444410705422921660579694758263732745916064474645844246893842302273629293029702227020054481154484269697216651787802614353624158626627284264427262876545902000325259606582288522620860506830576643967143282651834036381029453836866173020831625099795877987274560268118798463030690534114202342683050872868523522037313031647099569772579513907794626478638431129367997295524227656433569761450265532876296624049025975585271924047679311987534059997442279623617493278537311655521691755816652876854422601358848143982852894397114014033730556586166030071984427519489679145545724229376665614284472206246773992973964036506315615176990250856325876397191037165245789242305996202018999268194799805003074812869366308747497275286153861877170918467753590426420077972938973437934618612564509241133681136507002520098587627476639599640253954075878303175120830235248892731558757830259050320633456432728022607639266404048219666096726355317354304347129152790000328085098451000138733191777738146216925313996392815606756830935441812005090877212180324347159746837402700791281218201948060999734264727685992390666112967623229531754305900903250097149639533036013481596798960229474228313526494594188569762694704440085156030647417188611937073185450457907782927933252532393629303773850870386895388917844095955282341644394950251755680514839962536066002504072668514322565219601553889396765742924579712232925652979075620457255261096159610272912277408833599009384355327969750239552758928932683447865907069696182097378314630973074293133507316077761064520937247362068596730616370833026946655921414444853721099156567640523018069045497081094951932840824250862242720355501423551879457481905734234024467000904757375469061614503517554739739816562858721463142891690505496148679968091414009238386703479710636360113043252492118189105247493958802779938139625029023134532635441086411139578100550371483584177045301102608008991725153896982200353225837391913338352247031869015654655338373938630015732089526129555994285519459844443063562888018620185648063640607414178062361631662930497592275320261964418242139425503688714198853696062240232759057583058444118969579270758815063030062621361058153862666099931578564877701067257383175517863582753754358126336782411424970065197443996960981856457278935950827143391867685370072648373428493098327877064742680661351147367301120000, - -241588787901127543543519273560041574449757170189553722592083679345227947196717674646023810914425780898430679792561069622952031580394185768507979020781191899695258831492196891246989575675089729200248128804377098077789243242432572491174921715774728532780244704287978222411936945629409505768007336300639703826241226451180786048789878099117392212905654545746007392236326343614408446296027702893849544993223249534539628072981611706128640887952355328185036534614852973235837228809149948713424834723339140861665694976702783762972129392719459513441199916953089357438514722984464272124416521275688519608575926427570192805449510481438050142318577711242056817861360457350726508860504407119520077951244969956284174380590319650372229747424148046797093936005066608741623851828508317828730199305742066624251665160334011383949593267898956255371161551380152838253310974059712902827802356831909249747454275879674810911074050119165271138423351958597125952387632861616286982635338309745778043149418010741881003492436306360482882406427922060080311269443041323912793741703249420018628789732310586164052348022659801406689781450512554548766056301049933677724692395568633666027695351730982674228279406492743283464822883261526457713332022950642869360574060923573688932350341860016570393854346053286197186578446980169885906098755643675748234480875032350994890105271382343257426657384315865990286977216144268180054052143759885002790403564065020296447716778933529995436983499301857543575809581149351554790309871462695490816269482100210135534905655447123494768469684740653400308061937697730401999668275325673153481890964867228046727555072482175071274235306486807569283841686572688904104761932428214562219298864261876305647588192590841951838127537793032033250307127663084087092256415444004139686269890996337589650081637198803535985451005752202792500961541389197260228714600933593192117933870320011182962312648522729634507229895872126751807495644793252786255241548766007901633772470722012307420638621051974968948436667294944052077795547182885449140851110543791002200672471273019978078884301282484675109012619941067638735733776280165893970729027162426239113989240844104782709324295232076695160093277750174312186718557349565656745837589321386623791310311231930541913435082930236221975797973054071850095491266951875923522039866913603620153774158932043753738220486391167254110415125466139532981048781187498161043405752157838479873843413866129174863035580659962819901203935790399688435725131125366521419463521701493499050797377147384331786706866432102973590151181849044463866320023637789094398935883517277580909365128414384442195471604782666196227569086379667302203812412602763325404885131916677036450923825243039107860633526224817190317602075825755674909060941049321527177233201012616106689477241088976271418543187514120393141932387718429892694889351691134905419023030570948945406766523837302901571631397804015431726677596300886564866461887722431778288144615566760413614187197695041527142955827396047262403321789331188236447615247128333340178038887654997445813522832378589401008545892004179640364393634636651230397366895065206800112785150521720365208815923101891776142684183698047023482368117325239019255405352167740245840099438802416812706910054178691426857593350263437764857674716179143120073598229776367635844532351291622090261139847818855374696780008751519279519668970967599600260260245972315751971866165857685192595251911689336077298899281869501013007138160957965581028818827920045943237139830393467497159782876937596622664666529142607416254444000721057285556890549865537944579189742355389207673727517981096691359296150414640431806689382258246872144405050670951707168312811036085040341829995129612006018435948117883123732699826766441651722698470129199961951456560767283913530757751970133172504324197983750615039977603247881948121311044166422599258929449014797460611775461149868435128431212602821292548333670713630394836753769215333025273673355411725217298524185204239446894312320800822418824773928071907850873105920670207799845280642350013862916724410107116989650100666187077071314956371370776157787107994466208612979209325897208852575560174664065775302712440623101859974289507795774069962017921638586985688753861635538914453464101875339600917756598659988942563982472684702167534359238058353020717066755735040815908771597251268452424715803640195312395995197685569021011927497592829443211560062108315064304446105238718171347271688994030030342881308849699488485775531533955428097557209259884642841437202762728892930546650070790769934590988179838975351664311156055402439804966060234403340699630921707823696341396912779884008315682920719926281915501261867847479243949623438880792818314872117988922533945586480629869097793975295857154793114409871692578414109323301704541869727972600880225097495930663394176828728825881466106162044013823260776518946576867946025439847784080005879280283667318807414219912707929101853962815108853332045959428839072929108667527930192950834685370727237073565122560000, - -80044233750111787420089146543690453053349073643488998891435028840094995407955551619081888098684297408488283993965339160730920526074544685423395243198573988957840660449222436249059016609272491625104628427486572772811719470025240878080168721154297346118442591046121154384911712296575213989417559838499262272471567624885048618724094746455394842292271717515537392718922747903248796669270482303797468845248636097795759410484885292701728938163113013355897596640926104727314956094323265194205124685052549656349528391191151951431156011940149887173828044528420491318146478060488781658191577906997109386612924564996453206195101970069822740675685611311481166740004795127265330779024602493546814671076272690390615074811991115010381568943881365428432332340395644822900667355825287961784621072126432882444595707798135882204572710078745913151209404200761222740757466339405263000052257776422667082160204509501032644450947127124683420065258991920502242632943918970983699916382482831445594632170085414618133574712339854722855957316665873248023002300350368580224880470611326400725218389070137068213928245142228651522719283109390696382414875002850911953165188939175993618491533997809755014843680629850055172060231461844307815173579158898298532503248982618276550725783258362578307240972574324666440242329220268737737940563821715300144421152886486945877039964429443618976820414966656717505865648863026834358065053943672920513972406361674312954658087810327081545322316250896139242129660645034462273876724963201374173554609358432502068292780171931834508242493583868864110168259977307355279768458696639440474949490146447356787999085173310734340965792473458218157786104263554994934331768820113113221760318049617687468868082819476471782866817701881551513974903118108328697415046935947736918479807685487586902227263187498212970096216566639099037393472911578498662101597855525363020554947628160846710598380422324612738262064329965623296700194187643882667187833748925206188755411909338752835030620092014552281369560469861696039393614817607760061547277505095444830330717251128979108893038313597575496971143657909557817917624224236670334368460594572964855183559646968629342036169297725369103994020039337503573079281018483829194923988110761438253236111455986858883514675899439054190544923794254930986390638266186598964909434559312051027060397896693920899312517458415347415242367035258405192580384227034832422839900457518479979233225122022340684644449173034104809031495688852920497129562085787942965891464852670087422884162614270746870757199710406541897688333105055720527941963333800112679929463558645414003241359017664683455418708484437822561057016211899144344872554203479516968361198439608322166520846448498781154401046557360584739231473873295772450565322864604907192158529085507486870025692090386900786207885050187793017022598662277749256298332379573342501281009169396545742052190986533777507663683457910269901903817022018915610651913323649711209896231049791848070186911571041060472820836157467805597956414030880540617112183866038101703932536336179891568877717059043534971612948541236572041402613282587673217071175562282779962262152785420898109272247118484646653197768658890930185001288825999436679214353712460527176670576337077263979682790543748871462627548638357718637699552846046278460446928562659616945509677376814823345524590135587743403176892880642706845389816768449124886117927301748493719169956122417430373850397137114002590720344853583200160171251872379393780584099264901537410975725089234751733803607762205066530127533057212251879507288955260350841538220615163524963199455765841131648979994084992736229580034467490488142499002107542697803458488072702050519700265798659363736279715861782341654807306759008216933231009304296014533819063126556981943618981959955200673025632466324962642908583074271687865595066337759523651153615951747903595942432485635635927132804017481364193633268132639348389715298502340186781349282268522559763638968349355924138215670380386151689775716361203523888011755237511565828957765897865534534207013331096856669189971018403239644121467863746172725350387491083683329237985472221241623887774241712717335461670072830465818705814574920224530196082372221166270672507566499720946457856777770260048986758850327289059359897355490734734103303520998295837959734471640111400842672072164737832288812178355314717603660637042651908718505830267310675130764264315423539916693721991159519879198050346812839570743492952880224322388543032599826598275796563495949405740896130284657112308505057689423477022920444425999402804254159462206182786885949076732057630566429130801947041326705266895744519567402280090681697126260229772532516981080672403002126408417322130998010477212080459456170174752623715071751215811867094264266227348717516455850810354365368357333551168401442328563326531263890167120197763342858751338205309219969655044516954011274868436114488152378601637609687180210218119580726535964373175676713576547662707790578818547274282434560000, - -24224832994166333224986829576696120316822100084349740232029970254433286118792628176464961078911319208112519768497026650382325934668738563254374299036267548299758099014535489899692877955363360391354963614707677482894470657982614116544968837081615224894086966390496819858918407514278860537203663055465819083285055829477062150206646696074533402975764284772982203895198419432465957651950319264016526788377665365832264977787550763483294549303966412047333861241321985122396506308405788253306035256311340327851120548434384744731536856631522873762289192129073617322037840603973310486916105033812302264781665888599506075079089121640275268414910711470573180874871050331378975176163229539985603746594997911472555321451183701182828904663089108470066379314542434169863639919046739173287182624089700325690322146342467706645633164347114936110895327206482160942622944588024462868725519577069562473891711754804739873286198539671182688356836235406483913305449360448126722676312474004687022274008820341124670192968985963531788817929353149661106496810825308659239950216382712029271756841276515209214294010251956513503608929077905278662666584351273385724943897747966054789602950242960758862469336256869833029227138720757731994769745188565588615384910924157670499603184402059858209113563449532642077836390119702008971692976571866297516041071142572888679077412367961287218193638101264209876779443010579659550991197115802916897071814933433650588305771788574839985267868316726289928542095917438432983128626432270363998039165399328773373361425064921497672066243953191625650259721478135748352657086516702493860076624502574713256021434173409205612935031157293915345307419776950308744242445055999343426468430702547071831794987934548867993343917134187361696828821706646920086813790791590707294042410928551258085984177537700672624775262042976502031561136958240971654544762534997441917971348262462058635945407643909824467120575969835938975932453707648453183290872242865302725676908797023009021036188253788617625573593755483358789114240780994712787009985356345764686464155578220515035452445711940943944056380644346439858113394500212490600778727669472198020066734139134105680392870058656339055065913003075530137231446274711082397561961980144734806831734831209030147339449221174630875731079530412244303543391935703144713950398123989864675192882923988318847056676850310224798399770275340501310747479403663090249325270432014024239118073083642923090604495034949238831966261945711460653098413803290581207026596513827005113530498361246183204118309557633494413696984036243345738444389159447798151217608575244551858630878662218871690362687642612341619964031891168076693108661517440447952507588471088819584506000606628822850632962283191868484949828914716693188341963156873837338467109220417326332411841426366791454220744033189554664019785320034636185275668819919522698217284795962119590677400319335826270121633803467560029659349761533063530484424312432937602967521507195734182939488517525997167201923569824577012884383471770471781470579265422400868519498065048096931664785800623921856393398101757351482539548959639889083488241694121987573809195638790188110747525767587323898208863627531264449206503962585788440552935257924812656483852420174754849250894697478065498898346163922841692704972230973454272084785696313665961918303356814749327256504702745647894828082260792325357627281983869711457520174179953190303263559454962390577937700382333402406196527485765818964951424267342821678030696100550744301294860214788306778355615811673791900853883799570721024204513634664740111608465376476441810151368656741791708333383329034657607362425027956235307970501428788823446307757909506088189027096382667757444729444272794730346309576629557295126683104571937100308085194805067657815500958020751668428897071321717251887957862519693008977615054424288957275396181599403283838255455544596657365800660622106127164442913608776347110625054786932055006901142642751134825522086623194275101233637027744490138033601316565597837905245726561384117293208926389132255987519552112076343251725215064389278590480408921545742200465492020359846864700929955040819416772310505632603649380844484638176978723602290197192924591047597839859835474089456729764537530344304555543663779268963339795515125396944928876317271814512582431458314505306084427796466451977056693856839287042281253690313604994663888682166794219754868864009304801014379568377442316733203441305939996745240857362698093746117325972800351225241388249310925351946066338035096804417163175839949855254405039589869780379657742703555075118486129647462781895206995421341441029766126952158075481343762594868061191995506820693985489124475225976146352007294939055287472898715652095797425675969890218350870577145446942881859030240543930539202428420054122426271981165547623867882134068680331524617406266807186683142752803047058548656158151068684694227181423423431236806034895393457684930851876234538242869384017745773854720000, - -6677192472595817930503958751615821476730635261303269202190742653886775004989310827546143206191335641110719001925742465740747630331417343078649794498939712703480276954767582737769420870188509915940146526531349325912725041332743979085539842415697248534511230299191342743042114389783864718389658877150125601889750624282042507693959362448344378788013953087632251018599914920096017951189276633675666907107060115648307360519394007812691762585324883137411328904969815587728294045971590277489306062059934721550851447081023084664838118255406072461421096579227725882461902993237131707936853384012837146973242724465528747612708385586659081152773052793149994760638740535513603953837526126258567115378599191618308658767268868400581083181117162540713605940250568304902018691817950908835781737695107687624336005449195653145842191011978621950966880393843923751611764691480490672709583199574449482433493803802025615711542364934200299462510219455033738990331877878617683380298521886803637495008508377133160109322103957602154572760915011149105287685576487534080274084547649988868378477677673510470781062659222323150225537815016157494399832886441076839227751965689445897491785795605955992434805493089188701750221635055010500456061895788475132931862985135131687237832082385104202432272276821409423677867816481168004446370078895851614187205064915954636245809951879922369078246540939158708912721660605477339242457117731397900668109136051851147125877419907470077110447067234507390812922113019380609974886495872286891115153260252885030872272338528306721240109732817456911546106210525097919209450894387955978923816603994793160618657869771274027885892278005637921787151885682909828663508502594162148327702856712693932801784974399955213972502605924571082852434699235428879364364990489367166855367425581692222642400866024724370382272799851140041146839419231926138493492054982526296250067575086957148250509526783826423657919861952640933879224444095113583691580555664081407298715406526062620606539592017998950753691816481955226277565657341950215234926990956167315113997668500287130659264721635301055768696365636904617697007716374972172610624550199860090625412439615455374516513549519857656068705223444339398500961107218710247997474171713829407642904044619761413701092673966612913874308678663211692952031856553873761249544354458071440754210611020433275830386694894462355262942151068970295279730151237769396812620960294982112581539009249616463597360351892869867410896242394256645424387326199670830696899751271102828524265759809988062110674210470797554465337983894145044892270867061793932820705132980042065480274480353660509071727239011834662236549134810517229038551350335868905923185251240966836974669052962758306209695967854782374106200724392236189028980525798970540068782470663663546821703121434646940673066255276138993468739643356078639516345670695752854605065014295722651254454431041581383036613573723996043733885441967493824990464717479984097396425566144322723418634555010473970565727243137522865443301378964806380714356098046377360549560534600075497942837747556409692768882678140286968146453590096705682087212455688074681257825047489405802668753421852005084948405007566308056842613327230001328300317822228777067838567914533113322418178517344937001909443866138114046518105087665554600881361450090901748752412268720140174820744546452852749473079871942200959861135967353845131564458313930883598243225038627811443686575168951414776265139666529283193426622018174306323902977005693044153107249686378301168014839701436250267548274669623181581776345303437219552467541757231396460982290401947957402894952667888904982164825343179515332605218830442091866092976327387311494321841899297577947413753742575447934342930160980461942162515006970945529240965857739428598343751453088158619727325979430553651341337795292257121063009154817544390500241430897900637904066411597407332445018253364878413002805342703888609229707155288225128663493098323733644771553952626915673398338356014452752026841462361387998265956276324751985998424222036698048783087638432480292204430635384818928713811485621396943288842520242179850956153860684372642379466673184038758682355618023451779060619489632767035032733832768968660884503360751058169064175082596856740224629513404309821194517645591562139314001854838741079447676340668860166735662370206800313109649788217744416550593670965635578694744906908142716960304233415109773941910832765621624323124706461472836120284519198629056641270888017976607191500946678947051372554045186059612025527302344134835201629202184330087002659476869450909285807263847302637597521272349691789360435642127514532191676254327213534741492744511436523333575060670383355091716495592481767795547259401034477769427020015243043275300156332338625557976040258684083674133893213454788295378921687956912367872039048449429811743056888091571251768466090858798373355563038556156454819225872920495453672548223118726922240000, - -1670736849425401870425622400292985764216716472845997704086992018081735611503944427861772110692971370342820478144436962351814937923061449853516645360067104494989314157386508158773207398839943215991411346129603853109829287482788685117056449418873050215574083028415157577114475401499422916951305557113728263124073980032123895473305254162433484503498273886825912372298209509685148891675673950879908815417988092462072738365917259912690562794875310949942457355744779843905348969386013132054285845226564918165904693166272698211705987556942343810621381097416801068143090318290570224488218766543949591634749877330890219662954831891480180927093530127779738384059746194189968725052229066740171251506919371242987237516283244521785227286798803499791842141777820066139571121469402285121269947122218408835961247185852630584223075042286578992212361491064005029362336972580966957745077298315422605036963641222040162055921223719932675381399019256939330389927316797240055337696930739951724828032006176906811542085273250175284245807027141155400790376923677164788391529594298207413802566602558660676515985155723981899657904197981122045681107667390045939736667768759676887495855790003850065787319981998121383184669524153318177820778997310804563833215800856743363835340837678819697438289422204339887420255166946163144021451799715118091751414518804315833613997110557165655965987978958942342372194496316061399898066850391033642912905859586099093567434190614564875082177130092248663520470759225106574195890291421240864325802433763541465479285328295906094533963476834023529311937746683640931981199823198836816015331878678857566640542202962754612003295801254496354622295639491251435108103020464645143608492119781768962536805222254051989179954105931656298205115849117505031120549094129828251082105223399477588539642243669630428549914438526425887437039631828752613109630088775698741053257178635790444435716977799937281571579337746358244960574695315588349598599936859265258017843933275297717650097378879482435408139810794483245008877270360000644108704725278711197657656441727596842461030219062493600811099641520056108714380729357432270051047875280999730502124504543870290958095739582661985435684742920116691712057909830040886305707422579406225141105801503880458986905566876799988295071145319834657547083816745353207362340399533319263186536481557034448516414397899183071396575166695180475107752225945645178540442813600913842482330374857029258572732992621906102987893283853085309265666244262240977393922597809365501920138000516561870976076521100943563972969624195288196325661083309132427409225254737224657524331266170915015675179691767214338831098768226367384023375506558178457046389089264129542482321138495326811979240072969157227030322668213385628701571227177135966320554518857869753299188535631201262510614810441143778304556455570188818039241080683669289364171460556144192153293622889267850104655335498606150422312080532968240860336510216115164170917689259820755771507394655743434055598224995014311522182435774545656044785667820983768572289351722955079971002426083122336920023068121593709285111237154082363307666999913209156187013552080661605688822711083714648235985586300184107340883092839118546548957626975286975471159895606600859403049497167282556044211672871166276788657178880278082733990582453375010751036659275953190704589385069201257333937259660171751537764746051247576158805913205415146849182544266579560891473890126456660185204608085967890866753146570947125906898475194468516099214214290182725113598509907892854499001856695070994590697546662494911681127023080490950822734610172949156711763552120634694494222289502527757590704815273368776621106279645796420717667582538666628777055895223539704542262526985484053219987921212335409501901854383253948725844867225724319383381528496405158881949412126182133859924440991097554820967579897353331844186696686933447059746934848510860035766439032607386604331956495784164981722899888869883632906830917013943975205321046980805160917605647991262345685730164355803820674890017343249057075169085749225889132633809376243801791638967012624545927494348511688882716312404829603920530429062338894790828867168105052173100010971938725023909390089368775864513176057710752120337633879340937041379971487599801276963850041074452882605809198689038953259530189002317433554889395800333935906288329477468426950683246214092116778628502301316962080995828941415103645218489510982215290600422504018366944182056811907667905407426821119020478380503342481537792621179815278810405007295389383992102885726717449729729944937090468596532584058206279429487775103382971422547406956621359431284635661531490614782467704582738133769604744492257141677100536920752967368490149816641347340020176117896208482390623313113786650263451427648440211799782816828104050379640548658123898380232903522528266878650797062278065987425501408522929898262829155520138444800000, - -378098032541743688119636541427446386487532081232269759525538921842900225954817194535323324676793052613100799454780493853611364395306124605081397959318238663274857835374705783867748752393945621423644276040410874548715950628808447967915587144490748419546515428297137845104272642235989502545581062929374407591418784127417202478860201918173165484657674433553111285384446245006479107337087072763290100462878791316467502539935771056541085541484383828561304728062179468724019618131978799825330659341425899054568831766385708051453617997404822808501654869422888927737640982605891895633978224390479670147176783384784135454941860813330860269275368310437329238586629015842674275144243510946452535884873494337091332480736743908207439527125939772936351482951113962265787337564096110120096541557490753127528053080767224100126319031784784739194920567084374673559663451476216136496313234266013031365723090713982616293914129390368621845489821799869900233738977307172123278698411096707748098711328955978283246315851991595189756933455407715822771256474319132475749532598333073580631683109336493776809465593081011058927328704720363732102858555990658211141952343035994142495658480755216812669347497180975305794288917410748171279638888870869534771055041983120245853007386082062707503487046737676803456679654357407720747584763613023647371727471609446564268420887760937042764857790866881148685098929434507161845679622152180973129776593856465608024775788552506334051221555630714826550551272322561633125645571587198021635932232042114631940687363605856073546671285560023820221327942969928925075285753182567248276753978961706343041064773488211961697622902121272587452780135849906768081842435113361085897450581355643563552323243827761019647626641759397637584429826839539126683072110662516025347204941335573800454999363708548250420510387627123688450289308306364163717574943224995118770707368435239223824738382438148148094948031696002535196930679522196574821082945833650377940962352046689699910575727643767255123519627666044182280114092500700298414343282521164626422053448482203205109863779797734947045649897307424362406149934863296399436946015047588731849367046881078765007967364962840809851907233742173425828620996313870326616797436802276231768415310544156040967341675440120038501390277149443702384143492045653369886728447259614076486298639354219373297941644060759390784201910108768063430385455670233978003211886399384095570768215917815719192858524045706986705898066519773075924312912278498584165679949190122615095140204215580465222870931066558196971447517554436757470662130808125300830701244651358361667307863678782468753850052205702228092417559647144712196766435633585231968611719850239299755843389670408854209124030022975766391548821699939397665201269955650992088184099072452748229813380670819247344454377792019737077963998855560837292530382575535096488540564915721036067645991029053604498017117138280987963431227665288872156898977653774880367777813582117350716635376985490861079762003446968173379615519802656198141966966407815517408596195265307783761753359107849181484644966594340514431387784481708665483994697377042130772417405976115039842392787366900762683700489757865363977120646135792749022701616828160467203261087477104327929006015269061897909893783474792297676969378145761669329460563757426717025946106055763120618987749960940103758717752267774445054737040106200661915145173017108701902193976142010555307045440001775392479675152034400065241542883897582198146047438802337323011692965024161810031787819193577607470738311552797496611004750284475138683272321539627972248573655760538727645050114899270756682838179179870276232559810602831742073428196545934181797133956537095372083095613033764744016205889970045886911590857915665046933490212017043804019671123359075284885651710613913748129197629209338486185070505478999566389596310535569675139744346431513131386593783834780262040087647151042963826968512489257984270152829750869108252739615875043134842029569850783068606915727985870675549119252527526031266047052796410790029078222434073084847330082937511129440172654409918038151678120114208901074535045396600795664970218519229514201344674997563058707531283515639726864194520203111344528377651558120862418579635368722551070285892394908665457021888785039170694736780267739943044916467310947407151339297042382752250385601514093265854973205979857976528871623429950941192806961753131145706154118865620892735965579696004080140428569977205464501619932995721540691729385645256545977020974188336698460010047929852556483275013719566046441289533838960673899851440213820079310444307016596707294037189262997517335179777651578754008841369856369566868639215198527583503413687360684029673301906961765510589526373627580351366687520766704154137806163431264161234241779126249562069848632228253425105736218242377200135006756991011711229990373351751680000, - -77066611345943150579237036313615037847779517504666771715814904895833187240315144970647001478415753727626314114664269004661400529703626287098822778584107711971736832722599341550254975335882030623853722069240258064181159498669908437093849345052322001083378701394510466675447107052897962875144575437157944392272891677763708800366624765835898852600794690958608654517986592615628624542719160090713656385415788327594068386774136829463702866355544465580840369642343593297096467805662511584284537737147358995863775346013536082585930420738485691588263801726001752040503899360507139236997401787432626000406813519701921834708066172876311932691650888386208453934766747047774670745049036176220288957927137523656351051960351124567300158338626822597291637149628194062119093365922687172354030961616597245518303489479068269942381435317076586448186332392166452368079543822312317504893089326749295607415636875642101420915262045017771427996211350929307030607768294699725297298724488371918131785092599817695839776712255733508740574037863631541124187983915715265567703275055198242352343837745013842238208049318137937821993012115787093779598838912835967881213425175156669011530839976848974051839169272009814807126171888631046458606307796473050420083433168803032706090344323540982485663978437901669226770227350668726278730587213960223387203062392832757888081297555978941000401678927516173502395573800789049778144607730399293674355866184712428941310855813235474914196511858696917685460412007550133456575678293023760023836051087823883260010046441995048556999878154852526331970967052407212000732206151183700264879128348071554137860134805587281941602928902126349528671481525055295834973011144874681305836928828047873860789719095035163348108155160612156582603906082747438104587009959700946355908646011895842356505742649742491535532368497594240601551130673568975812456463988104572253770071066645900613106273217338040311553717714377717480342577694081389064001112441587322508512756524692465688984584111647708080506253959830833063412527238807216319377004338849577827535645252738124078988010268031879758807704763636176317027023453080770970069051374289921392779317453161527757830679900521769561588231656647650522175345854707287548879843895380201028312198769549455140996557179926957144576228380820889917475629766458000738588701714952098131918028978578723870421647081778747769203141437621456332288671795849128294221525993057832304329579357381701433812085583895475487085410546583557583363067880340024479789088944663454575779691094638910818682953967648597761245044893069679399401748475576698525501351592285712329097342998974801450474862571318038628903062232229278640069862681449658891397446127834067787847827105135071602237308767127202539091458680799809807197744570125776414779407780908235976314117949028185746639336770781412379891805408753132967364974972504889295131885120086990530925055789782852269186986432888799891346369959133748969356311171658339766057738240684569583512481835994185942414425201078474323055971199664517039448536988887523391213115580192884380714636909343025342679453076885874075701260015768064115763221377630457613618987159417327297185099239110128362712447935342241444041307074928872206413918359529421820806183746104970514194426814012900953554520598855440608201977651498634079028925613059949715308866732207555608270386804063878716660369568833505430972498869478310342464451830286765404992864198879314888171294047931957409470534001246430434020677293312275288529076716999327454330702129026009700463435160341665848694949248020535880817041712113958246515388255331570759118601925800508045942831158177045640074842662823971934972782333036657201759097057943139188860354136180503483736410057633171233645276599926474152581209455511012950394333042162535609111964858702588379057366233823149545825095116253917146680226895927899720299543893901513336671778048199934312883104121504371018817129399457187667220243182113260562027614153005234932381271492627872171221037617241142222753819897632757983754611105489581397906525958889314397081402952745015234311539995203950357730942832252548982822755266604938563684156690568626170958656087539185038998795256638682939419471691901350408992755872638851841465413155928578570010287250492836322121099792012589615449296259181560104847799202922933541630633143786044423781215065540175743788872481577569043830030735887573064852394627699431949748396043657904065833929347763116053005588105182290795792544774678110550415100535368375700520722394704468637175747111355517358247453483430446106561521483987224466494528091720110250131126508403086171348629574864673650029396884153501685560324250452941254025278523620906539230460048626497516083202917939466534737691259683155796470047101919628095283892528451594155753812734506531703621169853162116225539972784676066302863684791569733386240000, - -14080120076987428349616462948998906024209899536229045889974643930939305079158953930109099865866788922802921577156356511805757551040263398294709712266055920457812200115258091732048876104663089028443949566032850849597651803441632264006077788596833187844698667858487796830738649700534541351388059227759503142109276622083253879428785376569514285889179686049485098132141635469882077284322253839497153083628484576925455728772879998660679121570226837150562701021087002978450426189148159476670907399930820841008565603997762510382040175400414308560148441809790609770196371231758269972200862819880290928021270316331087324000013804614928018663708440076001310263318568836480328580644129228009353525144427825389086908307048926056440067210623971352343217120802990494423423334097955903840196505859114924575961289634112158326999218327025690328159525107058859227612203621843156872530589043836780572655641424546796865754812052670434583672347189615667374060664983016046097460876287744453819445939449841489633148843318054500976535626805249486573459827888255205894847678358302802703973447308487136597309397657913647622165650568724710555549792062866648807894292677693910785329449445880360701537123588067756160515356503910875839018210433593747674052350440942357824858526203229047378179295554827440649647500339876310898814714157207882939892635190842494663660953223712257793896628593469632058999821746355388546872631068143901529081833271719229051726639479876153977044634608815023918203913984818295187930543502378546903664031094139342865387176487666727349269472987503874416063422707911496575087847202300460332555939294029223456000571422339476269482054938570791801878510543326486010056514264515326431150794885585424310440298613221217266621220032914299293921622353032650949200492907901063247397704567214954566849101393088383428175989974180943594773815973628311739215494881862743021161076803148091393868110435367787687581621043669401546636408304954295670871023862611680002031162206249243152269905515397194455628429964657259622331303564324243568590275871295540106933069925793147567013434199591134074596548340373734723343720506245297625102555231624863694846066637164356670241250884129522805978551363521735030078206700665976327968611356660602264616282886144132264550636636431507379279680095093333575071961386001553448716306265269813277961117722574279554437405580406470861267654901912883230140683865349897478594475763991103046657158101827943137144118894719591917738448972770231607285706971882467835551554844529234976869381695086908167509562636225350755973616880117080823450580561282172700253588724220991453014883521598639997494781653968423765893835708052946845721598118618402337737395849276818078212575564348227497130625196537065375740442483924905814850536562343394309395052043360156138784831189033216258699781182599562479037680587021398737710703499567944571793045756925526400797434953933648077209391188728306330011085141421111774662066026634065036951229880582379950449050552146672723493771959199059524094835416113596779642791217563906023289356996689238999842454917924840833631541439484721358047088189489669448976031294278222935563656126775417936558623772292622875785612739441789024450655509847546798272290262038956863755949867186356826666549687764532214056567674562217622065571209409886019334278519348412974114066488206079520770465974450729357892061820382584138495392152225251433541700396975646036522099467259443063205387372289237501194155925833484390355392041099841216518565816198628331446361035666405184404552268024199878259915557019473558744745732594441243808356848686509407500863951655245207155243529500535188677637154028720052586979648573158995893284527671770792865175516980415673046929215927775627651516370592005058059843130454644461153743147566451342619499424332041669997374549732239494444161201220594873001720334839033112410477502438424198822608067739499363109039790674407120615807396358993153867692498275551443994664106588321855519925285641149485073421639361453423042850325861646280658425602399424762249890144342275481806938761267016557407473670283550973970371060237429451484533959147344032872790621509317931915812364369127559998660551829750538131028574865979388281605006215744121794191628554868505871431458086675242700238872483244386074335812178391644830402958733093291587370210813573422209745328195089655285904344534232963783338007264836014633622598050999273287575676890440243501857167629971219747653049103678012925767823978046956338060180881550887450743471238477143186512421147570597320154292174542608143401827917658635354259392149947261683182816629084111803390221448021885644056679112929329581942795916033631390515323467430782942664777869198418409228561100663364401416294287376332573189169408111179110730807101296008778646044782028406527158202574688808337408000000, - -2292964474862152408419325856519525247032842067478554053713005941116925926498674873297072686658591366285787753948881239746326739656882689113622106219717340312038699837676604091746634046937588898037804845594135415365499453730891307443881454439399246668338590690580567756583650315799743508686997454495673935122836674911246123848248614404541690003788573731027776489633189961410737871995109719435970812472985584325583964576224686631508854791820616668530182581322673113086112819754664427978253300040028516914268764536739381499963823680239716869296213638392315569961020688781062222778447093327116368455133411512023251971613147928521623266504817772226855516232564756165654853680503802318684936911253273476676669434210559448180516799957985237860343134674942054011906743405078026279827516358810326899341237925209425449514631892505781357278790656743446717703547851387223038440089301116020222926312765879759033473794158986001307680628075193359408201872579973041311588049782337603761761661489507816466133974062064901490941302756672781068121571673975484568782811926925143055914164818403584256813008328108040920905367560613029269608244608334663972989869265141433158674839839789569315057205172231473350053015027392303065868119981361993164800594312797219829225140782168603516987068805506364749658854152570304994555295321797768610962001142851908937276465800278186476337257585216997725399099479974929153294800438581394171335682933804733461971268477797005908806716352275938278534156403840945131930770061338071038283533628545370598416051823501433970757016268109426911016366516749343503450739190974264052359002761207166107333391640897897155577740723257081030800126061197336669205751747352500009377538449800360741259785553238410718282852135806832363360249611964803084393598904109288505096005150342982360962100477907976305145363560219398911007262361194311603109189001544914926179586649998392637768014337415058511413400729296583736610929117991415667766203199881393962419144711310982072554753720253198220833894301230865000453359639774372302201112192220328785514475112842612499324331835793818787648388083103956907099733708639596204352580860229385415708565355331647347909744762505700028699651918187569179046870505937379507692972611188055489327014811815956415504166629144900469939367238567144184912246434445119163019531018707587325038953305794380026327895502413105632403222772392148263627387284688726254545156032755076992484025084376441348596073653937290827493878559877721967788252638810667365036940884742891020962415076200051393838485968823183266486443813677058796851089060313467001020182336846045495409251018639474400101949968846154059149035378403581465562077734440434548962677765873643303135067327326520724101912436024028294855981406832641228899800471635380497040643794467123025860909867291101141684419951208951865157592611629737787230798262612362968085332501000850108647131201500515141978568822011549886368493022043312377807006002431237247377526600678745609221815441184346378720794380011885632339551537411465502955695308704747678055899431339187986024799471201652125973276562042204783797660347033027404634851516013911993290701292349324021051262231897330427994081551418998465793909917987014499281556166497464749106347732745500057894827892233205135615897260025705533279234712370617456151358377773661827808600644143814595521353310963955987901679130047724884323190120413903875837383696062727770647660327658968020568563772718702977982635727591893636363302627806117083788021566056750415313776551616222027204556737572800156728875454195297485671707871510111618245930149327898193633585945450273860712143560191264767680844423845813888589871944523002960850622272969323714359766903292488648164407263980117385745328045466320960103007907438807199076878986639301556498648567607630394317234536443787387339846947778456848344407715146081965426242612718734874195024569534957691470838900344466558852018960010511863288542632969761054441202327208940171649861484350044676018229266915078854446551801750870624132937494737264730325508005246921052361837789555794197881148795703866101226792984199339522979139020454617328369335193056244163895532251339333867962360098402306474755159999774137876929566634756312138227498708458402556045728097323292250323517719339273598593331172700593427872419772948952010598285626370825681598347795650282719389858379308926262415047516136879591892531663411038929934222291564749555764442597222953321493410520666368016342391661309039645848486430684499405425109418994956116437928790950888888623552833233511382601713280883156301055433633218604121338591393103204225633651658322011730186323256628513942734243155053492015270697733515938622456299148215574434044666315645077222374576118231588788703238963696419955643723582344700706424964366991360000, - -330656974510020946068429261143385579989017469685217286741680744909615694934610501287263400111225310458004521679451076100907187214751244531287864633110540289851510883269423456018553084792984509760556939639815874574783725508712754278702574351228419275557209804962447461683734821400809593308989825123668160510435077342405831877549881503202359798398647349984312368810006599606080741872369879812839247145498622251253848343383617227941623475761355518986430989154585913308223504842607012148601506634459274258108450867144846730897277908937670686126347381308597253918933925119888081892643295554877312861386465965720565870813846548832421878696536238909160600504132036827891550817820319795985591232654813088866591797894264600542846196743373383376718953178183369165407951129491828338909222506586174113121260404769638119408156724422169875411466308148360607748057331180762736039046260537625595449424695476574872506869568588807106989527050310445850236058611495452752437810667890700873543096363129295992855452451873703507160197615974287428340359226615985112035577775710219114526494578197573244604754954316455570680208406762971596807761987043840600044447528279591316084337554842081715865760738091701902100849551243979533567314670563382213044551161219022799692723687704273146929679744233997686019481101462852179323478312405338153689786272920143478546803672688748367453580921652537300730642375869797778778292757769220432477416199491395099888887334234855430924713101604061567132272211818384184080617296983204906943738508599138364720013075878984119230546737253035376702982994266851485643081646708347896916909911645420052107128732055650419803032765389104388793145123956735492210151604381575908105857079544260493622691305011318400027044155249460189009936333929654979876620697667175404825952939385994506238418792865153645578537847937370160690336811753257187814521919231383676033664690137497960533250863832823237662524381168581589868009412521258655257526121834881181026614381127544317967869919290978109862275621634887855219272056482445408520224340887653059514885675051140747971756247549949231062102829048617967830340361230149491662152511558056041901000773405817336095277646316919112571898106803867915290154193306625828703894353324314166551203302330350227632646099230479741505572446133171677409603528783120183857859692052825426367267932388859084341421710875402611500240678977605169356750940378776999284070908405335214186859592736056263447937016570212037289843030257367343757503906221556914393202697075545454724101420328643197609615335737898146787815857030748400436245950590685762115097276126182269077632580482733614293156958851260958297122448547923910734272390019970960065781336355274998636781730649063312483966799712127576459178407462438161232781146932120208284792486234223324458507117935339634604519260502580316633700420691587743895803224957761484349737085609960141767667220231736632284890536935936608671602007682803629307730906583281675204490315873208524957967178557447545569042462911265241194870869024184305411849157695904746211389045684022099208757424826048904194810372711126711663511991771846674331692200680566975738475677442934234358931040818072998164427150746615650911949470695770029617790523965680568702171415250796886044358480658621635889137346142206607821206301118962531163670763740933563997556281812823895470086672143588334789243461878077764966368235980720221327490325980237659367906662269964225659540423617891254525820161170837405346477507176411421717297065080321878824551764793463612695187005478672830016073510123938497665395501033395719027100171517615749325072571236854371755948399802242582195106972567551000406382035511617949865028288278395936055739459515667709206026990058351161223455635443291964940488069012779878713805817173312349889387817972449548885462152922056736761737254878515142610734427492172390452431167962480026231088877192071038711004194681350597400334767864405030449981386265495970678983242428945514019947511088727679073595343709984783220252940482288144888717069963516865512588315061225669366286029072268794822263383652565772629267608523441195092517941353591821841668181221551981981419772634314727748309681334133550426319238568378946956847982048782938334683081768866971293239399309087924059499795956619310228757848687919156967264519662794758388202210426696610741122766274022403578706312385130163236237764698194309003941927911640717253390692821723910597104981993005294650292127486132595013956656717798542444824741766595652092177989455758337458951929375769692602251364773318113036454912817678786281310613827308166034525892655789326790589751150514768777110255592602461940950729336571717369990566791892809997714103581561844823560730865908996212208061021624353943193687742281154560000, - -41891136058786844526997216163891756974097030569836088390342790729559032942629920117811833497052726299922036557260808920223345235680638393247560649329561141079453274836858224889452555261318275744267738452976475312270400620130438235043107228696723526425980224616934056780988697421571163644439592084610505771892729234823732260995291417756356030529953870464642476870609439981403123468523650850043568024694995536533496846280678051167793140784521704567062262171312871983928579590018303083623152682391326185855183919009174040899936224355128901373544307901278470330626961804708737631816284051445000346824346980507427222338544526683772991826943076505005571354725767378470703521378136611503792617825980973416401741993630312940989647914545814163787730452291470842122674071594849989073990879126722779697763923907404203536380766210698317798801742145651421887722654198911257140621334385169292612873813016834106948865680825472240231527428482618608495172841565701536297461291166661640863209539155691278937272932677077824401213564474591929093311390739748500924907185698386595911651658901635638037214117225269250276195226166781667859600936753144075463286302745576656381838169424555555081072198938484177655715073510634001866411953204210522774769548780206847342518685149885136011683926980686954539986587225931068760718705609837265079848854992891257668113754244039987926723960644750388084146887143798862628931679416330477111167121741454893815419145621836118383393494469243536865274204514219379057186859642275695400095422131471412562766935999226951646564464023794504112687752189637795668925095911425986977223787709293284172414472899536464658341310381227346334440183974790011133887439956417151980609691240803375087183829818530552542890798283851571385921816953102560599640296520096437320406610783800342056856204951498657162861981062747992302418956891827200338561544150973391236655912166960170874372731210933159223327149570713156901329068372040818151734318320921747595596707031562806524884418717470989710820177610336672440038083438164797710825127611359679619139753829822163146648923494668899015898742790427971329364493521518293930664011348008121970423242806321571966416695730377228152373340531113928836540417108399972833453219674676820433308371222408447915228142577724276127314969879192848343517118141026211970713646389015209537583313245702497404711602620245479158387587388165406983027809750190271956456157232082310001504734336620769686640137916625137877408696399158724713644759689222891920556898108175597402127171902136644933803390389822945481845684698776581641384989548454014927190865680990127666933334695983016840954054331073575094836002962287627862960100335949257430097672483862717441765317698305764859884722287511442955510803121264457210175654351080996850244995345514452497538634000622755712724918861721889691078881194839798407147174442855080086293517936610700608717040747005903206616584286391809968911820239963274030198108356664894176168306704543115347615804444159434878372847668250198269196227727625239779219665637307282033809883178206290241149815065801592429386276927404531350915187701019136265664399175785330121782555258050135488378754164874928398801997567343741452863344361185078689468700690774367899272926349954817996640184867848943231171692998714645082003920159762398629583686229058783530539286931515989952329551134753897113199510465448344344551617318240610863305610986699099031516222652973549328724821122131348813668557975705727605704823009832154822548766685664613222967337300865460681968852139252488852399037493636383991202232797035116670024548386200838177398094161704330923764061347253211678997479438554213145843706903596257302331206607453832403185395559617970555643908565905305354792777068512811008433343560614693901500693968134917207853653521580826185176802658799798847210019059233414196857974412105444869610422706449374741154339055302148435602539916318344990373161617668100963803058470675518925052443169636987288343138672620763406303180785029039057987304821618990115176983577419734117445875160092229567220390458337229340875960893982060622089687117402850700904926454960579801002162679241606461612906821723159206180752254924583061664267545770845810212241984034545965029374739284917011411942614620517437271679581705075551758710904209863337344037915724796453911190675154458033831863991945053444518457261996291895575830635438884759232305594931844988622347485187262739766928373144636851112229129814927548476158905823506942136800398876031719541806239189059375321629003024514687156121253885462481750411524143480166344858196943511074889227911976173429244044141988576082652553903100336858231817479200252849279405357314130097893033911132901122521980913784352155893760000, - -4618035796666991812294135537606259595330504580664503547915790687705783961048975139301186686006916031250387192084876339802835519682878241126127169668769792798586133486056945301514882576286257395623897053984127890464526908242177462594393332102347548780544285664883324941881879219122573684825004854180481315990158200158037729618334296156144131604055377422062480048922700512626074410889577920120981175421395560006480560382851495416330311607114317797645765729735910755085604218815907322101859970110777794788956101772250862659563542164760950318826146084082578462456858893227746335694021780563384134687216005570591981721539792301086399751986412027985424829682583343086004441854132368779170657839741930892908563577841355912394327908911074403915934779930068467112818403832078518588471649886974313639334850893168852471713328122102588174226617448396166133233948575296459632963125089940692285870798443823478728108526684627143120843096216742204498540036361216014758384537412483179201366640804262991865394811072245464320999942042126414780204535462081443655769835954559983695779511000193416795863418266008600152761436412149739743003210698035074130821698877950387693773639171083614416579245315777676481592615669910540610739008810992596248476408228392034392262485372931286343286678750377316596278430092244137153375217909477941637571980789806791318690292447417895200343547471654683278860725509399034062099763865364714966089474839795339422621234949727345636769147785799365938884299868246198681352876617248045020155989819482573345031283934071866615153919662199021498293898518243698770572175858962098102487120616874779525698044086359805768234002416643215968553231984328045078551162304421866239359999393821431645951351007369634370288473733139627392241952195717692440195917315359760124927076807504209739230298396476372870749793581193223214862980278525149289283063700880700527136963416865842462498910231940362771591451610954652813136997020749070081562559422840619781561720738851036246392178270260984952732478763419845016524931515051733065402388801507951765080638547857267954964222964387709699123467821533794080070942798221658749609915508878730864520967932104952361164879750574599180909137449101118918723351217864921050438885540915310350444697828419579647282768168920417407167830720530507721665104340440054995922156962247709669906935727849647292572914560364961699673182993367763020797312466221522598152760780951554701057570305688506686783366424600179272458347506241085478248624606030552485422353532797643581650584100388076635540803859981434616511276842058894588321723167672243390506563857506021360520092040934764231945461767689732059007091828115605119685535461673574650723889992188906167281791102718589751236992941989033350968194981104816132947061391807132786095455735017611220304404278376260512302883587212622824164242362126110821366873400092649570303426468211735396416666440200123795363166033541829018046977772138258711401609716194291174144847650833123830929251855513361279793936521927397530658281227026466453731263575252023230601049112174914122677098262602692533211219134313955467427806731693551171889741869617792620219415965237814822458616658436267523427802734093710589673043656689548084459718819060707116008117037775579066208581383686314389538086173743106536769909206371405257063359495961155464512108871495280285330953388977803974378075961147014859903061046620155294861753649367115995216029654009675254140503813460731253583057786032469409276177759488627116766644415550240427906097772140224306008271360971231934416259335688758307247221925922083192606073799885098037430539752586919655283098269064370345051372727014344131862505761234834831854402291807534677652201881125687720889177429666577598974628323947910406688065700008195122187521492570872283007626724037184204752717895419685078536580907048748110984314358677693285801170228183895357414821220235512550650753394512230888472875235806553051225998224739953409107318708312638540874890114821417135651744858830167910000810312580533510931255616526112642499642233453741440115732686290258756023417100878135731415352796304955940816795547069627279219912435966800458228801534427095673872510301447059111682914831818204721378916605530980018604891014342679942684447370091058287031603653175334713870191190083434920436656217637990844624741826511244004864584811865791554215507404141797177647363123770590037922202395145367480607805580633861487851615606241133552829761982707121542600715964216020373390716009671872878630952497074016396820006905782704016404884192590301272502982895577819755047376620059015599422681221974646886226061589254038659129598655666591774187966195184879714560932589222753389685894021120000, - -437714368006763964182229556868472835302551619270115245929194884335622059894340257986849373506510448620981526262363960448321197864540011470246621458936670952518354118414848317444098073326867291902465122721873231231613441315092499986256847109409187635000207665239569659754471596271055959186248121849364030466469128919254974187376049862163824423193365569158391140886422356183517156607663591196472198605566815095498210221615287035575893863016158882798914165884154865545306082540474389161708236670451413282946641014573465657152492170260129516142870431781097332103028949156600599702581082198018111956269146958284342153583850485027418068303223881865801542034448142722846131456990517692720095073386220286610081311748780714015269431197233320311833384687215802450914816607545876360004842045573394778566858948128403602737758078169735989834903597968616102602734142378135183913691659518924897993166804445731479886205127661174002643864883157663959379205412415888053366809357385042284284141030884062049307725157918616864254866637347692103942005145352084676900687230308057199931895948085984597019850461050317713045997142567674409897445063327697250426234044075629411479383038298265757892992456469777235256112252183020040552331036689561580543232024335610170027053427976603471525937595814755015372248722638917389134830427419796777819981554709210352077273455492710005424240588057004025059482990793657261292290743560809012330646117691365636994012249185897961853613436038893428374745653339847644027959061339388673329418603358802732783215730626133762292441607970327940212499512966702009337311387883117165110004388645381562993261266189365870049677220242471454995691354657643222384176468494898551483584862233514149801808857230032330942140934416548709381309005289299527257844979909754641925538310512557822173054680816131832766398890763296232297041187789674238009977599610568708626157850410216619750715293108606840195746007865201184599010725680236787583417642774773035689936721778094582126416299721526515892803093817804774136902510024838813943103083459989301710014780035009050158494856043845196271318128891392400554569794214073557365082607303129447038380230051025774701291696207422853023882834483292839337781760448356530254556477481220691761108800316616487308931944080715608957240200760579828790159580832477488279358957162199712486629222546895958797454633706272462441539579313329344723901782756890236908141662642274713218724055002605287716675185726962692499664303395707471037505214752200043482789634287398761321671139792780413770027631530710437988181893201362077613747481468687628640736677367013250196885004282912128746538179199755274497030144191116871478696976194388757806440089724302820610741019805939821745730829651898963275442443853357997657021419061427042204027252941683042848944891307348080427262970140986779368380534270516298392445832568593291550903573869663260732082285511447894389290129553924368167556438184307501583314736289657076226522655274215589837468594277807479170272998604748780757074265164040915496173204995241729212128117386917546554671463992276672983992678704990496604642904567774185925242455798516655028722912558239018814145705582551739140879137047188226496730843262879749500680507507904127532599725721012578318769008261383193898090250834520361048240311418658978585617114000985594695212078186534247416265764616591535086093672078854521368203707379398447825836288071099337071556809750786284361375264974113735958189113314132557545828363000698803209848944473880561487212230264797843747644926658152598924759070279112051952309787606832285259242067110235003897898366332889034351351663976159969663571263933974893312542281094022664181347448653648610371165757906013131807437623355599270046415455954693114854867454384673906584308527754917029292991542807540361807793615404925559133981663199479396847511644562351008799544300409385381580151706892845909381474830411145610905760512335252249506746847965432636826151016526720593160508686062473130985677156952206062574774703715719076084793195486213738087887491674873520754353957463945554674306060411344174750665069264545647592587174879101459054344606681653080321531057625117420590752968317405024132961412666193868249559449138901862580015352816383085601229105005418637794152337938382173504589026029164259237964753410862287694854069818471925288622457627021810893617872660941311036171881194220310689991569983517197426326859428675156689278821960128256823867620843206685650063446503527699583886402802617265292545355564925382598759277813291754394094657531804198038607894908148020494312048928262377309804621102991073612255971310256595811461065561347276088336081863311360000, - -35131424294819054272213986193336408605399611964038851071573952718600515825216044013817397252511044232368087425433914806410359388759573857656356608595552998755939213094692629562578498167835489208723330097709965971505191835691154540126981331504875973080446985203659299139208900143231214570641251989259832155181626556897887477806779240387760636619091775118054506608620897867714547194649624092875605640048234923154182563408534060808984677489552294941005966578328719733723868758246078376955082522696586043763921479866327877006813043416652677549556068586281498506387981490677615837980254691998746818544733782044361328461294964441884072931144166990736548705784443601386514447604970174519975825874542963971535078934840076258982105744470800234580823345193962732631777850954141988972186120833166849089621939201811178955502101614048632979944247803318259643457252576868534085495999149404470729531276608900223304069408602561070438236438773367075526034917442231444983008370424545278270750619049113633053081359643576129675951683768977629479729869744992589837035886212948677521870251161037637639607949427393608419351054351717511930074799659553144965672652961381602205444751255946881567224998886646885944555743600414013643938632346178261354801421110660244192966982963726628677569126958445563376119702373295097967891825326791681785060732825162011697253230703783490965584165540285205041830680014378618809357751480415193558108025052506116931437630706188475258551062683920159707743270723796932743920246476012538728049008033871892147354374007573844810028988222258663766937172529088992307184117178931304461045314320103241698850072272121383765794754458870532271580298901629647000801705802580871608652751007919698566323833264795367870297359897928398734285685446110802797381694725415109160010278418190145292136324868077843686649570129631179922860239594913774964418368103574213776162948181156762486139691791016568716005682570984106190483776976333249950614753167353833888818372790720928544976720713849212892016962153631852063447392089267882587240356781285754972458918041007280354164581754484647566525214665082696523894045485945197982729556963750615702494985138669577621655638060519251193472096011788685335404614079760555766471537365676785651172655234426908871673346800433449959737760139018019319948464834153907499165553659160713719837330044618524586831325501957250886783081383464140190535244251837436947612067960624353631275046846716790870147630388748110629576982303853646662908084414120904452623606830365700966974589258458154312160917029689412131045902155245508506541763439020135300160722727594525069198856261192937037145921056246807443676182352616986910499239965981987585711839699585968467404781195366674456737863250938085608863955823346090743372673383142805377178435679316781308582377148708856291535287188781243504121410392710975061691783475009993890368933069365869566678948139607775403140194576835717172357048490065579191010690011325007443263017104313208928267004594581172127318165140549961543964480704195809721039815793147713302279185536622753511978112665670491934625231797848672205094511200952575875225065100580883745634883211361298229106174496279187079071825583861746173949189888788232734370429867574907770774771457419293759020218998579154082881991515717507831410989310017864901921962323741859138070829034376865803040090768146491609399105661495086757976342023690758391581403415617337085621795358857077660326642925342752215209774864714052428192062643315986145938326360847889800583676414994085106794998270227460401352276632255044838327062977194351779505662089005578999115255530594088003613271047808124457640648695446113646524859503848550231750111620151476781217969842053852136530917226515071098703439326636077306712880674955660793517561808257150571778403193446503883825453704377288624065316718881530621679698660949116387795028461314379055786232073394675019642547578010152135743716523300022273074418522538747320644922355304842830773796893396092299495000211769119851251787751238344912936526990688805263347806643667781438584465599912529060114897111264493186025015328333721572283463297322423692747285859974881632438584698808253050683504348166263065942658237303675942731269834800438781347948435040715927648434949172974894358908238380921885586819881588518941601965430098308336027429725140047013945777753533625688536210256779363666327272517754527876608152049623607363215448233008404622003905111094339152937780682559976435459083083523020097246879355176671781672237623290213654704263235533452515506732216437524698590966696137317502995868406364562732315277578039470369326622433599123619840000, - -2340120663194976718811192464445143633483603367357896286671615900538758961302240908824672698362487792824611164830125073383799073949111332956518852328665677347760773655039097876537325517850634941112412493214328305579301215036693416118687021185297336961024778111195709260519882863082353005848212347177466989815863826631319157013249725035391503638458206867878901556168794355715272543317941788724568619005335134904418659680846807884079660698560061043149856390403969496487815316830007539007685520773804470911787399873784507382517790674669331180246222376132183285902592462109575495003511044939748567541759025912579856506220989250019730164013267682099196428677927236812704093922269128398788863514589297623021453953914633367815951593536322911151689166979972030822023648941692222234406867193856781842980918637791288437061014738576762573758871758713307375186880936612336538405150558225490374248755995351711028664997442737663349889415857257928097904519754482261421290217568649381043525972351076883786689483729860940529266753218147600615204551867118125122343346857795043128276952777690422379742489033710847895615643350638338648737084656146972747339527183414635028952243249389491875516281024102962098958549019993373025495686031038157239227002059323968485532538721688540836802614652375576400204196043689908165655694165185284404705150455091183034323407945681947447153784417600383931961010390070586153596684011313938235646063576924259084171108145340127265351096118643778057317579826707226866038462583782942305618663773359167954184271913843286633216917974832011145486511840684721511243165618842669757620369268463511199944721494222399071104092054335922761396053335422928536513312809739551223962414922016756616318438533066888949901959097348152850868344665158423858915167671637044807482394010880213388357513919092124067625675052597071500938920188986781179495771231513985182422374378294588617907571892271151732033213439337994135090405529757628702446735543257477793120547822979218316543384957181677240032321068726005160883171328003104142439564761805255555828073538077453712735618435899814049277589467987135908159099084894347362783200843140100624172164031610414374918638379911564919026116165880265124812655860617882298227021704238865187705540199368654611790335002437363096935458528921159770849935651515712056885112752834771622959384150952713447762289440604683081016256662000772667078146509091327099526461927919714743445660515768664176761732145379758895149358503999818504774656612085875566248258738493143567318706099885353653401965692254324897942007210816283673068007435529766123539164507355338983117460875378722489451191825767879371179663752927867912977473909311112815849220959052664200305194541988802098623502791455607576900542380516115887619154302400205849329078936667219186301026807359200289710346520951345654556283767338513179479277085762436038160094399664424137546875666910532989981446821659128566085987858669845703479210598695034159112939996700994163195102752805316114362704073576705499596262721037833156084783176994713080146159792209451998047761375326639268260734372085633025564612926839279956983478154390300248022499695615846847841186105560313688708482671588201747394505396615855127486564213669567257463057201832218868580078737494983952070163772289953937696954958794354795412988075127855796932275405125795089696613636547492801756899716216593356915308630069502624088546988432605200787949152317754801039471341928356536983142976866148915063558397216090869019325064226136905169514602069740549425931009159185562695553267487329895515848341484640723446854407088488939056396924273865768552586355822710825741989946371105368643392067552116264345170584445089568333231050907036825417782461914156724053578517689674703921148140204992898092158905820733624823096910591323439719070827917166148785607745557342626285624395438539874697223586476454728844184607587760988608574673777372207667987505764544257477062388070619593962151423135719812965283989115148934519775090118776941373328071235532676610198232862242541457854029126300388740806485257023043625844808102718734800431646260208998949746556824664980683919186698071754329826545776174405531817855697705765018613769256810549730996892144610948076677531357529191914457506712452132160500677564816569443418154303921655635994800550644215882862348338841929233717506049379213465389110443410498725257839299429506092676839734114621758591969477479855424829366797099902424942922594479381696590227384742365391892523152913467280019916415138010847907009653989422281116719601115857888904575649889697983283136983074200438702080000, - -125837987653308121744274502473584268678928845055444052483500588476005223323549835965718276640211827290381392995037331489179981866108763327671381902265472030061629754225882154419500063628565694549121173121090311687768925476446252976183590196862828906956215661254420808514667715130959984975473135710319119282755378462734981892650224878480847902365124022081698996455690446242200828544185015534306090815073555787988168649787962589526075171325158457422960793727089896026348877733639362863753032325826889675071915057770866954444120549247911706598024760932954826336481732223872961010944638631905513058310705334440633468879029019771143430830566121905803006918099182393739454615496441148950184374376921501952874055929284279246268093182175042342806952112992082742747300066548730114566763293522096668307602853779863207614353401713293659678606755716289102862174190518485077096981396927724058132921964239550061238834649536428760793560033725573195587021368302969685633762626298297059445182169174187507479519341570380732928409757072209985622920414573594506375609023058647051892922657914070782129845896032358693309663455811562427931639515569675667328067371530760115306138110836292702823945524176439264486283894990947064606418830448576136954231516691416084166400945862759771942879388527399322009372381507475147830932927768763085269627233539545988075137272946395436584807787984379996987158460935729893417349863588782372313765653459609959909864874382559032583264782328867194332378477605324568538036615168593964712326762884852013487935938181196563075287576652962673373557139523660146593322999498737602475600095024455563420627659607615092118274872218528718793232782073827126751259103697018279600052558096542482518862458273154976697492352507202028537489853385293221407190698853484887017931727826353544164094875341738285066796043566155401754520251077774246470884192069563206847118441579463088146893959794196365896067524871847598007188685617991172034553976719136861160692751756092708605430192570376582439956336529290851823612202486253818102295266548339149978013452357622527342893214607178990211353220706627399542056047139389349565762130105630011857396438579619108843162881922696839563719198069551241046465907552295461610756758763500122735827205361751677569262618401816244558134497478653412331818102398243785684261454693849932266624228068516207846154772942235037996226408454856643014665527451880308728785312921904113054618403795716648202006515895271340889597910130127926381028145878483357510422080474038684562632041171194128954217509579057173835341493209694516140852766431004055880044049965392959256838955285196761077221509403524907486205761779493267267619129466230462205564214696644996492809192762809069243867490456626976325845391767784925336323344609620389052317897262816312976074024192307855859661684777568339858429181858546611464558784338754785456116569217979220059544235603934562961087345911323022630931578757380376082467549268276276046315975288999921150571712662025521226307427124066771165426923155259030395232871028466513253259053007948919576597137030979261443474979108303788963887508449015213596008850223747592541337634881703413080395639038792179023755057788251126534566014513546369317776253637129799702216417493443870077991249442017541811198013879973691152800996371477596252792362923399360806057511658246903368761032712530234350243096127734033592409399394284895683976884198465177329696650981137310678700672259393253908120177314592533734462978597727646390650245001973949165189507074961423474004215071580161130547639579408494006225255802424256923514374406065149995399402904129764010442860699302769513185339913801038504602746465263209752671351496236381783908163590447624486133837728671372448381037754817293916755701835375037860862268486076868750832989532311465123604306305055173390294424693133388072046090914278940978900691236910976824415509607553045865592358150083264182756214603632702085578328725667798568931465676479587492786682453816491940478868816975884028696402655261540194194276883193414947669319962239656039124065115402990321125140722886283804993869079432642222305507923298036350219262915994298481816864785726276931599561902836558462508646423202300646094097558108322457285554480198426236802021265991324316685561879535908741933895152596341240183310320454354159928777257448051623397050072396526847629604695697570389219310548839434960653297056312379708777601519456246135359058223936786898617218658953077447708620974106616450627325061269798088462024472330987809685200190109835079166924121640205407944808857600000, - -5247121258129219372786810094294436351980433974222838557621496838911874490716180778332102605288374246177416911676137607359719717245732067019734397861858880354398333375343215517430128768287728413774057376788046381749233152617823194958740969630089576258440617419182202235678650081554325677249508028752618626591717717372126366598233978082895971077989667663506338331299798496897838888467561332737091912222290335899122338078119464142700178185245314094856463450798171031309146911012145357317219016275743257069917571522912069501273751199056907784853210350064211244096644612087516160663049001246126308163361134030693109196054133364620485415574671836725973943900515717077052447262824086874960772312743340866072759373198872648570444621015304079435718940627588184963706498674693500571522701836439605813570550707000179370967746276073374548134447590905477142607667203698664324708609821536760382377576463835545232731426915317003259193282909603861496697225997960630073062842279892449026672580995294392002210359851475684064102951944060168828186871188961716220815631908427995978254511115503769662595756483638715660438330453938088399146090776199657419616130093367521307033568697268982684031941034122294192897936994949579809374393128868072021442290095851117155441069975112036958459973543514316389083853006941892841745449364115383672946248999131065975705190063606574786708316413699862949200031678581135237586154347003629534385068066149251655958578613913207380038561703294398646258369856117203889812477028949249620605781083121786622346032773289193559521681361422115386278607751981653029397493249902781881707413631204777714634801326036989209053910429190808921615295910388590423781372935429535896218258603367922768875687303450150222452966169807707487637662097527360100568643657509463624506225699377480533706112746686564374778122770363685383055431386064644638509140468385664408126560549568258539581040529484577695023129435773931965227322027070086682689793253169761175171275862017095019991149204646383859281891163949218888164171182356935877132635567602467854470809204585701489747539613071116166006124132060637506066651624972156346806112532426318587688849279096599451262827589546428839354324414722151350059277283594121525257684657718246091205098312761572704916696513010945940246223530684870626515963566822937044553942520600890082021433486507461248169987664924246486665569113155060721021329884557656296793631348602716925917286572422496497970211619607185222045078068779855065291802781164660338877474119836245090215136779646652813374184353445148409677583561132789353288856034384981449846609797515794568180585162447039113301708058165859955921690566684667164470833051103893050202560725075224926348483235480373041050135874978621209022132233712821936268819939809317234938836543457544254058802689673557927457363874146611171891458853874741671457655556811723333567539317015334552320765711611615477598960553685468989213526517890112570102738569005457218716836628568871611610264580241560109138301051207755404564385241273192817563501362246606838260144534590351743722949447091036208186356217582236892907723080052064368207403896139414261247966056967005809903655658337541822311158837969171620110101773990559228083805775297944885308286477549635105602623689374136468107133012368003254126626945355466997918352117391961577348602226875515764291518298876698361117276467733069868981760731504844782530337196121862785319689946350809800301556988142672455112845923181714177936046127522857477692029650312113142766733309494156031333850205567780004686607115523749335371935629053927705954300147955581436163174210514300382701939016445407031822990180756901387398595175158887511407767619144664378706639824135223691472054712337838635794431002864718411890143642888227432549470669677766622702607606184443810047094861120664620066402345685989732856459388516745131729205826636832032755930554241980273733884829930600106756127830592833596297754853153199608241480518265891627543814064020349331205884673738081117488957828417020684195980757698001985093508249540330622677792578946879745540002874657106798458344828832775494377006168896363963289430346708872800570592495378419163595628008448793542575987563910653909680720494641378118743584647604540430992415562050977066191800642446497669371041049177832651279566823683493887477394856635028868359251589578647585835334183091362602318927145291556974197951233863793910158001970074689722131455907243159107965994487845165507385973912857051835240951737667984985445689188941738276119590891830640640000, - -159138568189893643162525258417837246142595165590869508735749506627806634550247613507995312242933416283876240729335708807006872917356121585886720640282840201204074112083827789611198802676944987798850882315868744048957387573793476619669081946167187375364323145324185547621884276510183460796326952695385275391384277037200665988561189748027568109581379421453082960347432021549328558838529272250956993882225751690022770724000644599572299945847966064008446105215256535559258560410067960753116055299117227377892248794970821742228119202800463497467200208921347688361526394761029768992640105476597252481469837618806680655895820432354489404278419572311877749307441589017974372525655609469981080754350051255359304868555426253720106374449017524012455091674853434368236078903813338013551141361082162606482055038762834520028668713680044256334303776465828844456268246630947054732433659402641446894227826811597680462223627931552102447126975939702042729424629094233836844758930025514088698734041597768353987452403760293024029269833234607561117393823355031292530773917466355264737383604808383488776408143651703647142401881360023945091731862395114370144131111978006058843860622119995692268031472686083728941662576780003885556997511488860397398628525818612333064369204462296264083097215660624008986689643725395315166535928254288414535071154730376402347055987724712280769997001603984792686592879485618858141883964027776369048044104804297097886580843770621701300944477268573680226459301328508588271973411514105541646376599803224460340619464307932574436185785893881987098874021220929228361476404159474812358318551699588643814026995974212947850289248418151407959097400248175265638858394891833984447659655104449389755854027365767757811734099465010824034866250796542143293752048609362289847913599998706345088879501988643256853756906603300628231189010786389966017663911019678085454500636939784627966556370608757218007367846601696189841560688917465607430693544977009465308481412034582869691529361446650607360732102883828009708697463593488394911617779543492721119043105977545684829504649172143850135523430444591733902525911295393548480317580998147969995185563533094133396713934468170013846329490441024584029364510275373861801398360833456774634283987686596162291832994893677338824840963674897810184173637588427476323362799351650762617338360273871566385027992895373273330959202565822381440864334696196210444246353827879248279220784518381099261556232120441656468502603287915201437495006202732971189648909469686791470084402002449392052841911270404657572405428498515644494206814654030167145098411232624224385697179673456234754672747155001892893918517023650988136666570360718647416760141629039990967988605101004640976749296541810431171019701861747033617214709072899670741853394196652048455356548372904284990367132692743462449584254416832751050953266209189265295952626210609351543601188119578981140588947268792339013434176789129069252329391796786399140779755445088180021457320567740872555616252137541434591723140095541895713220776154333874075486925966593797531884238523135565802005307745376608897409875709415976321696072827470083797493340416591009757302301737909769411515073721821871351621331175786897478666470068354683364316818699672082653897893881409802859326534464725631600733699839755885384921281735631777618424344913765442205783827432947992458065890363209308467523754803298804385948236068669946079612312168111110504233889797123508320027951651030471579156802416771686872034663359816422770319889049257729643298162885459479990295587053645558600726259939550727134743321728565595150884821037627904791751398453225902334086814943267806299282880002573786106317530932901595006023802645803664651311302541799587855090837652637405311513552322512549011563807009253706616887271669363335373273875859029980317268003144265266204904872093724307560831844419421787120462128511715419545221619599514837268584778070635968018726878148285268504799414469930280636570057505436255944804252416177858119265079965788547012562743928918846578809956441487159684808792765740445404155438858845995541879488053582077782605537388081358560136906267551298240745718244820739832661220114038131421936535236940371958715298995767856786742360683653148531275692897794080766901463528005805408316126864698006633410108373192997017733057653720424560407072198876341400896059922357807023824136849609391754068077194362885582081777694554551174526569073915186516551993160761943050608457122614371598003098326841258147840000, - -3122218718970468705033027679469125650887483548612236698284199857680619113737902098802550545851400522617081400163008633622015188335167054225677591181502562141651292272434033653886112616910268225599874570378686952659253482913375621253672642613014117857506281301187889785524584440239092245297096487105249575096989552892081352965424766262458052960704029226641939288468971436067392654171703491718654079604590895608815808124505671366175163213515888374818072876894160184428436854684366574352263441035268278264194718021552183522497660690506394074637443320541163055098258070204511524369205714750939843276781927799053700143562328563999804672657231412409121733712006668437476280065498357651414277120414150130103301617828043947685561519874053597574056786230807446527111113630372197681856933703907298704141167647265375874272569731699312730898782321915004861285005159711056279645285663683401838594937065814141878667514497940187375760538683026209151311054576991012751908417591018692463898519858467638577536866069017095628181423418141191793961054490259993048849333306324319759647948883749211908578320590662477048403534216976123166726999967404732516856652133126347597004328200060961776769985585444443872254651919986193427599504780883517810599216122339263824037657478770782358443127842347128524773889940750512791745914376312683722769016150680020909906818019259071984750263928208914565738987715138768713805755109178837946222271572191190575976556509129084526463513367764994522369903945892991163575678394866692592493167925057357593915851382994976345131993602838559844696434024181967277629169678187315572370945823882591665026700917987996857140597657883085638246364713613150289661536605958368110624670081772068386624825393482866901721112398508878376133720343530532791779038886829324050260190632069168176981533238822524750116751427526732015695058579227840432440384114154151677532066235233459297767152530973638395702715081734043183882103842274375614864274334959646149989433461986226193097154138819650787064764136500188877717673693777623203798165746684539489537898586621199507432280313076501272620789039394325161561294781703942760815479727426466407813993589764965665350626244967493648021534482795138673963676929974822391432290376775065612614548295192552305958728742477436822859127762298589331998677442531510728249896890590541642595205806120272401354413253122203060530201839877877819562193544202891855039803982711882201932343129896873950957212189538383523457863155984125440732551003504661559214966615369445184484969494532565348493454967467419321559549604588179441841148490851151390252728469669102857025274474201023102891888874230218043450143157415718618433035940712060968278246408368011161218644235977950236177652139899291972560502355559466961468386654725276848255339543311616480560596167430186144975869909107675091420096440303271017019725787544991661542064056154199600104165321508638168875629607819697110379377395529942738105074650884046795752107046811122034813599422541350157983373705082060896347372695225167096266632727043897512277492114974141982806415688064096575411442722017188979757212417329359332059766051223269714521775855733453672248651082226225439121583868077694023776966708494978647720266718485953436985875450502095286119053462354790817402801645291619774984379805617878321400187086250810817037218038217569144577060910281250719120139812634863688727983308260668408733768463416160787537841540479344990084860821538794517743366042600694688993162812163991548661132174160539418180353054872314245655092653108016743800782593052442123281631228862153604749651357015222828514526359224150081195351651640295634629327488460490728074263652436326923500513866280706702593647073165280336323361626639851782351355103998526207442023598761664752643811707203363413571019722847342093142266295752930563244609653277924695049461648240217796431970909356649744994785607266652247972774431964941099343206374795442592893795150821218205214515991565731792312183900816191498575493010110846827090126432277586283613123659675327820589597695242571792936824929656242606095248189359710858625495146670890456930178118409616177479445733915235197710393869593640127322937805703137883970410016735991620740695564416932913011899376632193712304676703455748274983637805570597972971073188724910602440899441993747300378916105810676759947258321240245073877999767539900517128394284355198375008868145297159110611111369404081663325491275845686948525218920151054854756761600000, - -29736446366029735375533740251451545790516784292740551051516282364216227911033549173047074696733342178247433760302914737295529734897764125995526411341157633920916473331648864351427633667233899131795322486273344819893565960072037194559679050866025297250402079942657586882297290413765395276309030295144087079633004573530272803208268275779073122412643581738894548248683183846957746221968075238033033316729696186661902851954878425963712537980630334401840069426428411641896362208979137162375730392066707474156256317096777828146775891213672856520879242656229927607465323642045930789622422059666476749885715918321477785802647830518931612480270790591149830088429791738805246232435105776600821420488452968843633194336073688785547583736602505578309993799263265653186377887352441164664776814079988509065380963631333234270661743624229296131974630386503056053309143904538766851181106619099906114152378852987393415071972628128232894657040807159385181346033795152705364800201697485948330355426758167659690799942079152524892281389727995935341850101784515561345449465305605293571583403262807779050820556001657415845485521941971057857181372168237754436984795830098880139564945863358701122134650143195849489494731398981085671052565499461773306570007529061037999481061464688946856113187898089178595535443359952371321151186333669925445221645449588517318137462764382111212514748705409495039375887843626130855172378058986711680513494666241484757844027295142054908571626537245837752364038251692788361189718097798304098475945662924894414742387338324474150012082629089958437786612408165506232812075758421077469468614370092668461186410779881501861597759349710070365513556959921567448069597468251696626006737231751062302748399879115428721294904337477467500398018133415955129801331076435680216650487287894740555269335603753472207671772128825020712391876223495315947415131152738443866924411605272581657761768102747326381622014802714137610956041726607023525949384855482309417351294913934098926980706865477016118905190400414358958869021958495300837656685778982693718327583375042309535539407400092070280118963239142823569191992416158763573266102396260440117635177867549462853161786546964647636066788724717961014632436284605968261391217203542653413419928198930136698857425787754171167417935638300909058834069482274690779832877763119819413280580121628833418284713453794716218251038195374681646269278464849188899648831310753319055810828481145293695393480193461405462073516823394470716083468542070932776204611157543785432659866839069336218113873771901959415344617760511518913922006741466336609372152894627859964818207769051347532953682895930931992483081328847398993118780393364696990062907736515047653181687993929917961028120636433808001520466736542855099812752066936442091299134951655976536090494645769158013850470527815097123740215547898202047936225181306518091455970734029156565177264033025849323259659914508814865081434417237989555378907961412376207763448128177011330095684434905020156684147770493996634035675042665402757146781616914190785324804647271989527770833369270621764949192944481447311138806675372367685996985675037400338081161602386868294912769212852266126000621591775167856891405906660030800095488401861527260103164558601366231170347551192469219776476033865558969372515445658775001816746378360907684422672570687160448730276992349382223939957947955823549897492703737461771790921904620304327933461693113735248838054230933481298273609732443161103422996546876752683112028589309190289299134945981129315873433237410095889803572839417376779841336608149796429493735847359638158393610119423068805861233507308659104271546014281658608903464257761639861702970367342537578009832532425340947815388425867798976952200364698230885101406957906779911045714774957429218735886089070010519537452991621447425083530830857914831998003016787636708998712016183351530253426312508913653922126919567250124559788916305091749063924513580139471116496569063118558024763594100032801510891091426724803321678440852392989992840487159568689532151261225191586958195427941147883364367177361084755639905058373043400494589488702936421028587469443714276284711281702800158538795943924703879694459274071681897801951166610229987874973360318688222498261829349423014286143395164271677414365118552560545349943098922413715596940026379757333198074201171726887983553802542247242220552355279613056028852077226356707913076128554675016638807408640000, -] - - -def certLtLo3218Lit : List Int := [84417307591125931297302547494928895865267766871790350890176769268647190854822023557093798056134943288284159721644619584430677393248679681849967952945148414313350800749475189600953921914234908035278978916179068562909363861650925244095327095143157339439702021738993376354779538292924437699981571257777305399340278796727289551597991231790269093014427013660977860378342321804290390251890611480816734551907432732820004458868436301722606222868793637435794621604240750155709452219929067391005482054441731290541510726086345222991580512061010867206977377255068335061971449939393538412346565828910627847292728218232989438326371802011778580815779895199704887386238892777417120245836139839601028930898161905937538096100398155480091392145749219497803754685331340696380737152066438070473952757335764964650309399283638878967109789154109732389511612836370569073230473097360597238654027711674987574068659386645252129062292015401308887152148480118023237936373886285898118039650376132907114198071373723125951198544478574433333977843404603121677454237784736187319553728186281750939640697091506750645477462053777535690808677504143659576127456939719650572058601485368527447012786369497298718442343252349040462198017591658820549875614958425064768352788197041343385622635942231789431067782760108693211053501524676882503724730048108850655060760901367076878289584780434243304008867957952876895011491054035425629109408750394919805162063785554847688333841213126823601517154724161281066205035972208700667002413660991851519199750539783346202349669467727728019056054892645679672335199983361882880055851169675709000687242684607073748641070923373181292514273442824008510286419786099306186982146885537060904438779650038182537928838041048064843494876618141640290659133647724184629454589027624039785245007621013006090710256354011351846649605180820901492953318358698591170605177053813821594212538563093701741611387194494558835850496611535782468338552679887162203827300434821611205451803560526646068118170281746712403951444652682510300180296396735000698904674942292265933695029082667418129161963771767082181401201191189871125640823116445553028346485934852604312745713632176455138155915796267133690929071261693235889561451555985531758901169248231549864383874643359528755353909609032226951002489965693526834443948298394488459239237843938041283090490007119378012214551588843450478319376236505299491602733911026208521774643522929180030501997380542471542433359119327879935572573863645360891993959358757138843730582093564032432656912673026876110081311707849141275323581393378637068371330281433490978290330822907709625956269830906926558153452843068055128407479966545311335244564948810803866786423088272380599987045635931466968372829106979307851755639776726164685044249980827677788703984959480032905162349284491585991013715670666950897416192954420489498372068970471552423140205572053322458238548438031328765456083076820987803266996572730213473393979634830189343006326631767978181809938237683610319005270445696363029289822225583960444080518672834234448506815304227417048595100501989256890103716395939384885213188506781991646146906914813972427479305234932372627546638883747010436085041832269703801881334369038216289397853932797328438543067060887665547686466483580942019310213343270726578549980598553746751073565872967515125265786071022032744890592469646444182071690679089862956613811971952850716472827226146809581503173875505176570607836560671318762789248304871156252757914558729173250925912567690705961040893520933825546565774574445038657064265155131315907475358946024493466473422917176987460612637247452677951849944638914929275151901645905078548512111129925659633386982533439410325604440450836577274826137368589561856836826528981116496827377706796999565285369265228407577024656203524919220220511440023127961230146059128983906016586387995983736441193998701333103556344640343127561759984198191145681254512202100899281778731272391015496856635431302691017830346216092792970705457356106612063419061250423744195818527816468904023336871743632707840205016671942945848424757890764925475437849147770370602681836224920158136553313863586650566902741151804002840371381404740163158377953116157474353994323660875336963148467689839716494495664549795942236942433767238877763422885372113592049000696057319015453394747048907182534995598379189514550047424102022819704405587056020914158029448841320260934367472290870411542980783509759129996113582520491257972544108841980418996150740882587329866145813240304306473704966751045659769321297327637007858236977588984088965006355172472413794091754710766486244265794751056465007943783434617943420810349572321882540686917490230563463871794333770146974307776350016910342181410081669743571653843055047843459893767248732499074302104189016529773138658924889558130629999108008322040361583178747618765369129706402408670290065888459714431502296777251355959801348977689974293842816641933654720227313886031070620540636578656430401375238373760511316468384747668724846168661364762426356593095021617529599953457197163065984167163286623437175275180936451401874311709914843979413420184027160778547579197440999170778658427453051343273123835862388820122155051920548186438429653858107450678063471167453672482715997114270728748733646237373252592552892291534929110338395585999360674904907824585714233375417294246227859371166551410289378314300364439158874374919248279203532756549957833455241579891334719252467243641008002016254704568635993552946311109400708748252945091122184855253805118532235272660939125940771290012807233167558704276578125242435752560928252183230455870035095806435523766190727527382326549351407772226380479940043727883212141010240653223790466506108340425203099133703618848722025251908908184238934642957723432963999298069732798927351887756370102161287309670124396952274979078334207705567450787385400691287931585507385787422340355515804551871808609223170096928653284451727372061406096439801808898327359655742703516019290686556053099867433269910947891868006146329311359910755872292872036371789065969941013623352198060973885830090920150965130428685161540759225979636569039393163063898375833692934802923409380448788654682655139660707469952389480691829097607197596735618766468227050015427904761011316227027333258938097067170204004782521071169702095090746578376221468241108956308148964209393172930343814025427633119297589532853721231227033385710100888936488740070813754100419824399015689664138323187660946143822408263091773633029185455124894395826687066730320950960937626503535870488318331869169161778747966430069597240940467910443303899520919791382066602704288601950317874606247046933826904029336212575976301159202728766365213061127927774470669777078212622950450380309333352724800110708537467140287259449551143303083922801054572263792278932869785068956372658118953432843931111390518785475813512875176571981521869859666677857290286620895607428336404994810122811906795231666485853001458273868495070777567571767157472058169694801297559616932788438267113020792430449510076684545495387600966177025257568180567147065117740228633426549902651320745329014662117491478709257740420054369856854135006701593387020788378483655590321215185070358867239641344099805351547756373128415381320521252151329128135154632036998799601539007765334855433130179767804282209519900432659148288508109038596068376571163365583477964114154766888705347189195938472474116260481120396280082154742569582038366014723546116509791031813390477955357435269334825062532370755231526868204225000044507147822785004485114347394440278293372166170608166585283944933503792639107513657674623113385203293980334641869242652227131370203259703440682896854587638157535915295078811558722308193799487993832715778799182358854456624976285885786576282841356780635139838150191112020136013457411367293244602705742325136778601819514952014901985374657147081360741479167415069087417299454277478102171062929785136996173468831929208192091123757309405310628781363647092806912351549777626022454210506676570077238061963685884208450354303150132918819866713088905980178936022206759711485943663602497423168661691433385776950159026391314983669776609219869642648760526200062074261397780396095842875389479034218267094955755171673846740673765908100318445459080455218974853104079397875229589597789462804659214050175021945398758726768205037030265520594575084871028162212061784577109810491120304247115272529671075820635598829144794903616982625724427924881918936615959179494258928634634127228873153043354411197070929120186321171718408136911070287361869826257251417533109924628906259566964232164099829244668762926818727493826655006010643530334282972723781655261476778975379744901489713864874052732637710413786936430086733078668425715033400899988958077364510666430376113756277719054172600237035414347549490454663450132581807105558050790805386079484069273463949403137325425097372869306202864661361703994405703489104950083137587702399743494471674164430277091201476155589513554852333808343529577097714837684985785617216247634577676653221539514953404505129254452762932726070788640921191990031954140683613929606844330868514467624927443666457433813263279157961726930867093483480151061894096464412168073225639668691342218672056083830869150256452774115746488444154263858768240592754108022560905189996220006234660939387769822820392048527758634889776323615107350959409608179817174622343927717637242134127731735859043607905696048017102598846043568115002769567528795979951204387901262965824210509291246114961532612553261933306158712814261800151525111310443692372606501452080680866067390057640640413774701174089986581199689731300106381857794415695054957845884489193125002661065710142677295166355334102553770945946217800144657281992183844359311503237112537085799913200906005050385477375532387830081753711051051562209822638291162531094554182090632235266217596419405980123645035927078445092575274469670725803083749076649661325419047734549093562903401251808713534183108833241818931745144639051869324302397779825966126579468911050883321747427709754123746870990208071016293839753047333962350519237575722611392433428083286352432673587200000000000000000000000000000000000, - 2976772629667398844627841083015576856467896124123850069092460541187822945564135204323464602661983853210699049858114873020296000057001287810787502290380987889383209213536362082949784687509054068917944378616572368781393636574124177432786588734785659315413930776575042231316176844612905549389821324014450678643901200712732965885176361686821719105860590083726615921650676972713445462007827998325681825959961480455100332660168557381856086608250618969033581315290955213763750542310734867959312817961923590497933779410829152088402568330237143893956626499387009899785332216486732093004320048086600169946874167044380218547828779079209762693641586626497268850664649412583896835464657919170308919389872867711796643251021763228003206304698290132910802238507880451254169055552283049878697535490189483245223351597877469065804340964491963825993326058865039293529451485609553428660957684358790156000885677406665017528064473242643054960130178428004549955084689883286014579620074488222877988159719223574234882279615950039064411256141840449919605174513126873830142620180713703230721829584680918036998763667643314812554676397934376778605076157870994516516847053647761499781561158490865660713241484103639084695642829721860550122529319413838324448445583215804265939344803943247318581914463343010914186564123618184452290955093821286556249495652707399112802151357025226194609779612008578850384613617729184832509325494725320545933035114500295434417507510295663650261870765356251259631561551419268737425093689587135142946432876278905588666609812199970867317198146550964863728053159351685462599718023100864031212235340671511630086800780771467565848170761509775440727642633890533473452989930672583362308958958671137266094671597053026694363426318128165438093978166953194206000625620068776077405363642080274502769123220809303601665315408547498127899575279226077477722994692305989274212390308835349495075195801582676014128052498124203843086683908446281113144854768447202504532118983971672418595818175652045286020489319531967808273529580856090214943307394123855171074538300265802849310506968343266034239572636758754219503324887576284345504973861200575155873463716723298644257987808147195466922928527513975674638139740708494320993026746795935967236679220055001085082090683937870475911378651247131736190611375338429477778633558602633413756557120368225840708082749500914336644527851219592610626634362625922547290521771046555627185686423725045869286860655185278143214205199857954123621512114311292918764195551539960211204935520247793476408365863836764631209715109135929290212094030681024462087707404012922680830235279679986950145407517619790504654909791301656902150056349126233477720893757450796191839075803068248277381291519384143312232472206755627793457483390558723698342853986130275575710780886525995344923576528408873107312055815231676414141713468660683397029259971870312109566722078741155387420721277878442695013327738000837539088899907299243866746692774340371680758578011965315584632853433516601086181593452392684870705720692298010214490243977218779386333807596287735791538008239545940425659615047350901148423525829847990790594330271555339087567827755056794507889875880893448739025771712536805285751574161236128690291804572278953819685594990681106591814157658901618811220861606171440217335808484653982720640839120987900096495233459984387740094985615475160655076934908677027365008434260959306957492104500739475041479023825444373986090030168806500166463419840728195980049797039672710605668218502866181879278703058422700560638605510019033392135522027796856314700909856568444897207158235227500473094737864387905379155510459798702717315622101850956167605818246944724528461242961150871556082988353540087778948205925062336014571435540100049226634724382053180837905954788238906354526555697435344432260103447815073728340945373364187697539042119744205317207754679560095154542552423815498364963335689675078377614857934953381274253584973803973322754004669532076466262135176832823422767730374677086969614609631233919374442630500045177365814287695893087488206704240775004865762866459508384710593786918265283663090824713092533200838750007610049156634548615781507668686908226757879933275276142720951494108301170125100483853926375437735801244597419293538907822206685474146049698682076842556757381488913492779718346759660261201916029160205808418781333138094694822276504399011054701794601840957731440270095165013623681346752001606719382495246468300636857290964219085547084653984263246440360428997498223372129489144201429500006822829307935844566749624136560777297035762614799971170658907479875124583665982318848315654745459052701120754099082085541878816659742748051174482521374885071329536465710214287254692564514137147269016542606652258899697753880951572697986200971749251906267637005033160653080718635030236614200457353638838853564334389049589324469506229468662973514591496592714760358955776333193832042515248952597821718847690752319035826567428926820203402153627837402018109195820972769995369129130088368595999664595368939125536603133224299115936070419044922070709375715597897838660043939020363051138340650634691149096981833372799789895201337415051590173959043526477404622206561739250902955935823275909455008786189170085921150448920304519262385740026958191159074794082120885527897384222066648364630085556269940361857148338812452630036495022865775367624767133448027366888778234972432462936855405277440579539167290137583353682265856406758869208730229798720632479321843802068339893357473600101707601723520569843175774813866888743580648244108015071457749983863604176683988566859364503462357905775156174917122892514336582632205844211336735704991964611946613767148426045099192557671023734381916903438868786709566204582946435519866246410779714490487127875979803203372263526150654172308926894554127425366747077395350509138169377779765711171525873058254066894279810250328206909456575438959239148258453568584467457768731280358070641345607089909473526885556293031140520418178078635689924514163161566410103762699672313688496770187834884673170489340392090333391935336708111502601262163229308461422560450996646926085269863874802125133251305907679007204048258003034678375062842898020581747839715618047399619354460253495648348865591911358875440349593994730085999703748399927483229070386108550152128924988595365972064246757094440863165536401650080514056205998857870090019976616802435176909212422835759557037612866073003558063848665789250966939745720841770591082852438036689354899396388254466662014477880621005158153527240373562481030896243422660114085243066869971802643436122882266333802373379809186343395261317622902949733482281090328819006674396861644585468471823933511375741923114306443023464768870868165729604270205826418636257691456185669445711780116821499302755418825169862406828928112103809745130322120545221526617469109227523489310700971272074358661829837123271824671246940077247414500596219259480139114830258875736205236687633571613651979024951139703202432454590384920271075469475011283013954132385226566717939778405374393582802970116905608635222149575955109221209477487195349417588538912490451396884065408101562653206734072505937335864139020636971246466687651268710650313897880068532581460892224567553243832418076025046405211890839380010191773320268688136808879952639897711710201313639364202830789614631350557119849314521483034038197408383210352498204585231184669362767252524829121951508740860189128612477326565520413817910487128452709110648393790648389909012763413326868618225847078460338181396733077078190764776860522246672785081199945653982482157136448660368532654116941033694053932571704959178499051910877189239965017456563837374578963713231859490028583830408110278477135151946626135068762664077998111698641086962406710735837983115704371234193180190445982579698825592906539357704204874624612399487136251168471626421342079442578312088518044878516742249825564336233948650157121171305733455620448444950832854907301535309313882876935342103079196853037707615226691439260007869739372939310697731335201524620728852713242228210898821799807492343909140212335783978718797103010117082982834771611166286887971847113599523091657908010724862890146699689724984785656610972226383228270988740712281163739612591930881415247319921213742659335235397158694793531143262810646279893905688506826699208356542664952592827617746495304853725463875834787295544826033429486895622066625455368186928480642296712574680893836593936717672478099365374471201815595139907365324181701780096979773165994812931233898805913622966812936794558758720096616930606450372551828577484626152055728844048944546726587194422365716593270227649222585509869989560075559870344242973263531082984005273527262333361665024116141572091577532680919023090993951609803881130906164624002772229797041141290465007954341858331148806906694019598433455985867883631207854283959258709455888490735094284171379243582413444689986262916296395237263921555750128848638565164188953780652682310877804402698358674779854072836342381941018220916257370325941790512024524595358674669693564317167772487224770683578891690183652926312496450282551375106967407991131955500483658249852827597370019338613552005236418525576678087526923495949351873088075683402270852686295377195776832456292368240835387204893403049767416261585944380512482178074087704769748883473579691517529022346366977999827570572233602611450089897665714051873139932704677942028885662274545746822117997691127918815369616315343462649985563352982480451967756668033182942290185092146950381617433617627447528874150302094415685286002539893996315535454677061943655051242214285013633612225444750751869757437514924769983162460547015060654386836635964304882026627050466154726730130162377431446045819136531680427436273880035417951249561472818419277287665960616801108957939700137052472301525104542247748334743793369528102779983764819752733352950243325555488535667745999765695333205330825848385023329429299531828885162898373045031318382389731681453714899077966825656373139268047031221479379213462663173116427073586703584097582691866519160223922185748627426351415415846448794051457398473450586112, - 51026691563511715396700671337671324421223295456358677622786030810168238891080424121720911612890028011152250789703268915158127917191196710556947372714063692801650561830403358004303376189566475382504390285110624950555763315160522149408710047987723929928161775292887493477912033774560834136323465874548215339063113305947062864032363620927195432077378640227060158611536710492487575087844019698353141584720611493499725310552413431888640218665961311580016021011708281036946614777396048824709705377349925761009039834501767744811240295897606584228080034989203630743725834710321293142456666450882127978034479126486025259872221064406797383978336844690216353399895068874042892857930663854585628386910628498804217610098316944409439438855801789845367722538858502992523150588237684001061705131651666304360755893148755085710069383352828269722146602992249087926607296999655517236464711645947724659559817002019964231969166003012803148816430227867966969729771271828171812594188251884434756038320844605259326250735162629462389117981065944302111687831698629804146566343292612934662407134687129920886405221935798127013093180763294577273612316466627288991598973572439671932993172094212047739019200633372938297854884413336453244701050117061634388334032157654056841436317536599787003410022164074834942960573672640245444233466143380607499462091762883727125378323527749315887227018512834952303303384412593529940834911797558542186612907642587232607539441207853200639358708886399971774331346585382988403810331693491786242663171747388941698224864535949868150391756872751094294507154395717695283586709097911811224493099679422252652028332882214080669623601515405890530545551747784288085093603560135971670717250154538371976016850494291784995138469134792019183268232399370490493201031635350096907893358482043300699745875618591490962865867922189444987856753576195534233334121545209314589412530290846134976833043476285743995029662707217342344850462173731227889655192838078972774371022628115632265369842398753181002412850381038068539794573505807990894912576933601042366568314512735932483932237022808683634013604503504123273095376823102166220901281511077154624236481819179242540249754108562847022500694855306965329428878767619213324928090896995185570738905754773880711506620771719226572433832270808387722957149886781113649446441026905141969641812536003125995820320909414120422501252664022210552073776430462653724432489657392488803404534661071940535452485949825771731670815589220308354521503138417735473923640067629603697683069370992622258728697033981502340683438925600863506815312560520609300887880749243138363186738075705176582613174168019674127351109445503029246458344531590816338028775317436846628057941720114041452821361018638060746295935947903924271703874047146093845672009913896399525539256905762651532781672390509277626502245413750019404660985170828796592212678016798064039287300401055279319009275172721485566545021691192505415803184232390857775668199267903910057250103651498768165962667360129894459744624741162278676162581213846776416317479521086547947466476523906625100881721732101682708006724925615132742899678387655898063758945962374811134745874285177645883047147957768517309103307443373669998788513382053743785561702756048231953540278762470097085748577486092036602506208951860367869828736524983487252932680151319410737049492976107791814991075969978063063133399568911074687331824600697473553766337414344041370022298788945220528544932464322555900954861552652291311241982070187413681749660003523751119660240414565613512493473752074291293936842962185946911046576268459054846257427849995699514526080711309578118292822347858603645892228616630552576161782391901823815999605003854053738844203537698832038436375522926121360658923211436022614709997652099687490333592968660361846784768720643601651809666032038524623002336041574239172637335347684580222472183754352901794360640325263501876259918780962275551956811360583289716599271869469647235094917656531830358148784593663759265196077740106781495227490656098729549174262807174341908063873976294272990695946829794778683044067168927074004635149412417799035096520966847202254879223012340600960073441331828577383433425725196468049174775856924632599896565089651694825753708825506922545624741413787891853252231019689677051634574352484944488710318851306266216457318459011346533694474380087743643797437354465976380022567619650545939421413353883204052141577028692971668118993914983026648358003463177826760947410448851428531635514260955109257324420574399567767325204406207318980932783082712164928063650568572870074813235318001320546362706070676437074291919112016209762679782748771555924014454464668326344925455267308205258945389932324711813940455924410515809547788850131087047520231740979731013700406189969237635700099077301883178687909066015714166073556575124440735982512623039782319875423522582595693682567131341509348646566619337009130552615563130442399304817827440433919010023734911029998667763897792478993558684704716905955569269346522745087243854398453253530875911585693482934619392846389095650328337617608616414931945831143252272202680904014636561805061896643786356233569427893164797675794856729620674417772667644312021556311503615757496991572478143870789885997914446933828593041742493741384997812965521445514889512264392596272009386199575590356499013514124996928118068867754266567833202924392555189214301082864862799664706136052039241715410206565386687396788895606296817873248042854056564487474482867436631071641720823892820254256543748800740073396792304751110837695369553369692116668542883011295526106565085043779456333160140022842852201903140515906855384910906087645113407519535504199883935292975190838183545889135534065198341304120906884536755142019525756291104000841053281570118539764690919432485822835288898601293379494886829873671554009361359185119264784203939845201084073395738599150577040637337531131703382092082338822332194066072783886899854046111939153751476029027579780686546286154719422100912032902533085413703068589901384591561475503888660964387194947710060748406598045741112727163782215207020207456227356228395090055893410971062378322466685067471798833422898808770961438959941586382899473056316830868922210464021644752089974673948083448269881279864088441044598878342686931872357731505855790383377086274567788391390138251823486127740827876123037437498503854459232092894273592856029970032833401739403976016187010257825080747451515555466066784152731269464439920126760918081983629905092850741851770495893620920703535161364398688618642586941161954405958311278473569024479249507338931562884352808179781676351762144756317325168590194936081178594724267132162351596465433844757833955711750784692454755113314997803418061075578361663968118800167251385083257121152763183083835927489547935508393990801755546245093474944196460780439464690352722566576603817708480558008914224637527956302715572621109679708934962108984752949349207644406463549401301258145275243271583679028772898098931369710581075935379891618108938567989833256208026141307459260929874338170982384413249566380634221156941809007103444922697793083718463150979913219360327779268982820306964023794123188453928649771460899452827624012193058020831140224953042634275211278445397233413221413429362216584134127090129153770381536103085318813172253822752628107693386925340897356391514567795526966025685711494185930465628409117325305097917162071891486201105342670970929539569344171996852169604949381750668840777766288875616619667117068352400923043990018054027884448681820590879805760469171820926165595791620398707911375500699921766377875936241284938991088329793938652310391305521417855988860629339045847296978633914591532564778244628985218947944171868669587948754595087723387656561011861696695621848087039633150194233994969190761117452600239642639365641837246033528992391811289561843156380231069654903390189318782502323820967382478714993825021717479006526838730386098103214130736892741858845481905974118531874736677408772417460886115033980045010477102624110934577197109345747890261827322422574778180905038213545931307020514631228053645451628547432414599529139144423449006276436692359860206758018288469965815618315399788414253827913284677123216975717718650806350826906775203563071375799475252996339664803220236862211780309272537627675745090155449486918783937355786613681514510238948531810395511166112211988408974663890061022859565680879286862792409487128013160021182169812071349506678961570668813062180797767109555211621960808168219795354044141573847719315274785108721199382773935909568976847671099583735356113564059988137870840669308556809222898821025548143897553746743032468963953123987324903809205469696431035975330861914050674564298049105974600935405335726198166038863110647598665371673951785498122450512467906311877232867946142479147863199754298815110403521992511720838525369101345986649510843757407005354088691951801541315668735269953790281625151581386853988070929806472126645591257079495177304543723043437171118421370689092552271668516080886169643345104777052634248870287205033933256248296786522582838678035879150700150750721264022739190245071214127659092560486032770993640596027652597157770622722274693056551757645027939732730720536611749655688041379530658823088290684517777290991942733305008566637363826066398545121865168048889089650972994101082639515094498853277663592827550749385827294298902240461083722820540064689294566659352715788936488665541554862990569562909645158243878436458254409339044027981815165132790352015538472320370550936511510889847766823072116625142414387670576247356192470131085694337157117438459941766079221821529330669644984588719293090364817572099446301944723151808162948864119225442883343881890021078243756848552361590805018249689528629999979121193202299620622084828435347048372767033190523545708550963102338711630141280833328715505595200275861244489877761896765254853903526816662940575167070408141804126792226682170482947129429580058307237850627059499280969099702709768592158044907408581536601960864152848336241013830082524309916892658167961351948138597324360542517145000747081530343424, - 566640088059069747413995026335238881539556909131690010348218097297990635879898772867185428912305585317197863967701871611807091974328038299166897207690796048357280275459103080204538682313105214875237269586675568984234599354043526695151352107204921247074491879306037886294064409598250749715971163200846636094855442486766569460451905109579119457307147238302524949857041725985807154727375921690182929375296417158310384313898553210261303190665297447096755843497089001413656332841440206351545294219866482992674475746145847679395687921642489357015950299924927479406500643470686140769364711333014012731001434848253624088929403695621777766197609491866338021323092306874435618737382887287030753696660315123842378142670834365645288463069387725816408543627795350310031549767252209724012140246560600027747825706566561770987858182860866145066482075092174986106917725262930635439062675365205452160846318157586079848262313004269488078094576057926756069599955758154851945296493530298513878236668696152637596776775727162621854040209373054355322903871563382846963109587510245226592669538982025366485166765397374166796780213788640867567499089439913425964461461369576162901780674168241931962447090933822638432209437581735136068649687421500147302597260133297909129663842262500976708266039357310410788143874874078687412061205755470734275308874230899339128186766548636421089430369026015049711347204928898192278932265932518092421958533929285462875906513820671839828862812726542464086868204775799057733995057405870352200349688925547245034090737193517241275283018692247014427813240841973724408146549147861518689968327024711625366096868065632189793059501901232921799833238211369115646253071621150969923569990459249735657339136365880637652109119310434472476876404825043197580991500448439547032477589951557988547108242219557720505819831233165266259610088256131135448787289862291836466029593625175399695423760401430499204406917524747228394354915836308352164742905573290451229744144217549300685353034758381973237823159930923229486042809287120245048868128454257983279461739428991625278773873149775749100732990566008204900950652099953120747978219907938744938917291132370570118781399688575860585229798830959154447629108614258405795829963420878760601691865725410647840794335549256066149705504714101859751832254082190417334628026145494890356289720233676085924334553485036891852193773740027433838388507337182268128596527379726695153296149827915629316787642536657316677025154490075294553208248571946061766145854573250226512857234922076307291120449496799148150582782968763257202675853523114954099909501009566028021435870370407425574268564992495244043689975580869569463910078910485453617560183765435285166154745319472349038096655501475683226816086049435525825871553306370331350941613766113540699813080286101120611990554683790490146093761720701173349866433267751860961936116216837185453508976007472173268793891935330478523987042230364634985490615783433947979619851306426520002255230135857109254676802843154384256929737687608056164857292476501204881257684640219566554148384153471310380035379739982499668376343373085010055552190632897008174454345722419438316859285684748497427162809431280960056835446155663686542339620798381979503191130113141393964925211428371864943421604507508503609243539181106523988142699239800504215435877767039626804744930520232171200387059263660536701808485913153156219463188951903762788531444467355538745040206198999702065514126448151064336474718177774972642269475280623360043676711015749641089883927222880693531590181807876617797610920471161070146626161029445959256754117387074214924658553884905292446616869899292227217622665973464447072134254110631876969319263560191592205082603320082549218571464959096967475898358368002650968115383929793073696219606454323961896953425133340236831553921651976085742278472383019410633772094763834714672911816701715012638414910826184040293723824374210321579489199507664112132746995578122487369707141413993899419646202305745262272652959695307095528875455503363211836799156104148473284389126540449368167207076952446662827447265319074477831689954485251751893572767760505583082284477624972199921167908186497864862626699249590590288385278472243165855115030529047167680527270778749999033653552349799839768526153651810122850965263340788813686438286462788493212910339396068290963492734598504178156121150928126614309859768351103666751728086138203686027620379838469479652637216027728810642922057448734707055029600320949131715189473218762773237126033423286939404525907028575031306692774324731018262556947583588847446553608574918533120374752969034449935832458582226742594645176130179288221311619775867833844317836152121126191386958452721805279354309184357006180822411763185763786839134514906853577974183694118813124499421018894320235384145057193145939450789559540707387729508679793703848073625770856010477231482751422094529412156207338814218274941675484359718795155326938986849732611749310510751461886050420594847638089218209739388699930878930089805842801943249027690102930607957807364596234333079787654371601400817135339484329756705044379792253602404721702922134836675609763750079716348131950204954422715469285622608630492043133848501336184334138643054611289148731121644501723800223869371248534592659174479334888485285308497269977513615284236611038417401205084704357149447686941849309462176420421463884776419453755321698844144131509821383256358703574359373614937683794119425615588737665538568354471763398742914064085995198730124415858799045064328355957488645958198826590910872586557069021394428723821485170779156229219313001646002268059939322295573748591958068872798232524178153306949632562144575718567052113443861615043468388615969541847680279203134234339006218242466161945603019680318212205453505553246052516572056250541338597603246131851847995283206995333987570113750761305443216246194604343780932943145074157850473403741111726481684405546917627690299569294078692233921465177666483609273164520081769513342342095028005124581532264682317813839221487408264596119024436816757335506020834657255811656236467964480318843936002353872304206104065721592050134367913978839448694746261149641027675766404580710113907076742867212581503455494574953203474164708448978756198197604529763708191428995330905887511110785577054047530034524202948762410372491863493297441787242704964595514215286688858482977046838808648083698101568026192472933097958657312191263589046368109056812983325759004098085623069091702585266707790311407941327968350670497950973933215570890854467595884102165868000457345402596179709540189547673149440912456756817463965585574586634068444826747296084972664896391408574337575676860854565977866865346650147814264969095211498492526984743957404601985871052363193003282145108309303949337455945137202393623228843796953589042375957355770802012534152236486254809888000693561628645609622126449846151818003336954784983976883706849264499760900538084996893657850487721105254271155288850152445266562967537794660152983391890916953880960434286678053291753693785082130614101032778104300604591010097768471211957062428895179995007066877853053553338444862704630851684247508457373885745518107700676912575233633712806620505989952655173243926024108662368452724045155574008457306198235967489075319979537669973417221860858536004101093994071857390076541337316189433968335240370987388518551772233224658674360096371085728737847544482729480785132088556393229510243203350397328099807166569613469154586156678964622423508013015455390622702370946519160984140218500767388199505129267515538673170650607132562487938483336227437078938216848238837402642567360861457178924931344424164001874560286339774687750083770333177014635196435261155559723695228224987078981447160013321506156068085744412170588304539413886753042470139507448885525061968893309478430337842749367098444251809116909821705881803020834999811464042362472334937925319441602358198612116906457612937427728922135198500509633633872911652515286392130763607050814871359768064585036017487694173971956811711299149515512227924347831370194194121351145606198155329316296692130701543062222049115411547195136900366550438853193136776364408686497446146459442580098003997136797036865948580924779178209869722484185665068759826341550823244872981314016983000748258033859703134733629994784516667592262375954407803846571100611583055730679099144457488089019632465707550623560512993645362900514014817932984995979415318615379525272475462047849100758477991792917999831532142186167584119492943008696840670207972002008145380424825968765665691316080923078685244607340636776008588373316727487995693766921028083984741497642725394304045511299663922461634953223060811911730332932317956033165357604344745200694100023952166910219690147565801693002107306251873792129548084600704848820751732252548398406604550631419528219454841656616356032326042968578043945365791189027169457783933480314174210125729040750772285847826417369047906757928560846181163403781121954619080507556367263292631287030849539277546434694618239610550704686741388596008027787677555194671790746282144116626724779648210686902395606648665559831689047559879244148256047569821904941576528105244064930532286610857550323066346550307250558909716056664739994773598761783352376175919269094789938559478790024731556168083503910852960271868326611043201664152867158916749970762814608979758767012600658706189272779670433641954535352219363492262273728026823031054672046478343476509263740641412993183772036719229172192689401158612118185642119525141625218222324865570325126983528975550692977855071104113526720635337476542673176039740308134559341114251681682751767944649667505872305920102516886054206300563426108825165057069954026967652686173207970724254420153367782090768584286167356750837523568957576268300098086448935109011512573361050087209094245567674992454725438904964914994637746026741023958574076845966189349541355220126385453370806186538095793813806487914743811467306670611352812271133811133002420332967097510550476549011929330321525293235543377257743499306032982133581754884168310631966457884455164968960, - 4583649297967596284602651352450269925808855119678382513150493802532407907863012629853388921772422485245716511226260238805742649735316827273001702899428793626899972051113837079701668108720350905786126237433795658909058872923998175769644384947694962422195362404744391744114253206769368157687411024260632420090573924894077101411259940933162369140531362254323169628692579838383677432568086353844405340567726057298754790884725579452270415299750327328580401866201879225223099564349835989951879884654462517625107207853834527376963180648287021856640392103130573576406374621880878301382491912740877385564346274603936379937673789453622941879194024739119823410232386286936659995090559202633502570361626315316902304496288337526350817047338539881217651557382999814073041388098905654847914241394333158834051605973783362913957916595357228683823256098134239725623652893542410052272589682074730889979806543770509609371836689958384989129935291649196792323091351111409912003150072957628280286574685437792004860598750769342151214454557917415799289892791865019349720421054563718007262112615356222078295923384190108767422820511821691685612687349580505265153264838014393976988773380837846911559329714990175174687878529282487419677719080955598129780078580823481661112359771967512018161324158683852549654563570377229208261552729398030374702888274048522430670629949534304831952290682224586515048818903631287816571076525983646247026089394280557541841676857520065809665917671506882428277919066542202517795962340325577663904736588259398936087987697056539176305823581165673117591684329429201650419642493906142566345889181589633668614457513631761356106716800776988152174323862469981432548417897665207743729787104808479288756889897402043287218299684244122724798741243618523522172251325123601771481927536532725478919990654648061418824922525978093341354891803624652501526053756479302677527184794741380138531656705102107730249730673944421691988387976649114307240348890470421519706440185666996787253116271065014333027507792837410035056917510732096480418513536533212803511295908431527386229760027131994238537033207653697328564715697709258793845312765959111860447145597996296853528184692079634911962676865692923716461132879652700830720207615546476206487013283062352687119220729432348404588988387221146163457719755266030457974467632607504764433094770718639966891555059179402867130448651569794105955621550224186959348712152768549443535826216698168680113465257332446416537796306154796639298793977092220051815474817236765070437658003304219434734357906735432908743752730100751691348382784633146035212866412216642285775763898853178712180653767049021261663569601567800794030414663188434114623077595315388199660033899714609584453950220792002720569841365238590419665902656834114018183837441792612846262082930426792166302672593863968550486995770144277533291791097614776309641039459364165205418555119117507969554479661371854219055472689449548914667883585027037747869559376531521757734842395941325482464170530212615807612402103934086575343427146782434495090468049072620159947958031264845779591311625395080809328616566184088626638832785852996775670875129920655202564160513348497468003292494261372410505068590809611413187235895567269991951398517698857562569827950005304270126408289511298205018860189856642300799217335301824759754801223905179515938404723779183063770787866346696983412134180287821757831155360249134645798104361973707378368905939273253218472632895398608046256923874121280999322280208452430573190855197258528207723661060136009164806257861163972123676885542965489237432982198145844504965907353551309921305317753259390216743885353092085914241727020695164748991002050047516000915062338821499623412735532343038650903393101780684836429785032267707238790608086763274331105412735406826514458699095288235315756005945596373667302954146590291281194912695025971826168402707263012272770520022342039402545383290894977707735692561199007260869232907278420394467675954436466363054219856126017962892591174573782312749638270204025718909502643286904741767213034191561644836091441282239793307835057975447927865340010810347461807085572718296649604224187462835353724976372814839423076032353821788622510008872176318734369390078720123222160394576861506525940789041036222188149492444739088889224207266163483989561898726674700480649282126692135326259542660227655069603831049775657165440930245176653981055145275079727158736070544382826699687150727051524609714517140073070218989011120281472845847588356675185607528054152792934556376941818642696820126474578026271633726773893112150516367091098113540286970048689655812914360294649879551012443590744959901676231627428405540041585148171778028935817704792293194279253501594360879599236388439154112714109150709046215201023992323602887115939747132002072055676380038495818917245060086318158212715454966310778584240883925443790076235703386200707264422829357757309892111755534160904843918541677653409591201345123924817098496687473677899258052803076498738991872577142063682515200504655062375253678229776688738540140325369514938258954510648188900072549730899288422192939497178625266965832953147564018218233475706906476551183568090420670498822102546371562611984712502560776111471535038802492144996163308012151097532427275346123260220386926770632577564443018006055541705133925536301106843741082644088397584794401532810682041886791206685583500497222393540168244761059542651092409424126417808278355285577687212031339392970447370002057642450534509185444349890586517739906258714148102430212325664677218643691478682664876320467097739585935454680860223171135804115466685909815664595803788332694158077529145690816518898503021781091486011759837807715065505315314358876370688431639250643254104924403870174166844360556820047913370160088345790851621324254668614812268574223655644832911368030517090855138421903185253148999191942959614768400389572755914951890362026136350836467301274837889470264239680113829643400978116710492653641949670121064936356990326411014995194156513886165710591878633057556364724305720941787504520425406299070988786005466811387509546399889609713435932804528698725081206264233363789961260579668258259068986036009286661547574348013448059915904602879015696004253616909519047193893102987743346941198489819084567825050308145856859834890765570071218410992263537808671778496842173449987820518974570610889551597539823601534424338430555255565238206617842156708741227198009767821508242202894663433020660898296942761345838418788270846371281057933495023218427193393696522827951115219790140195114813564727193153634545662415844108896268006506001982096248440652912736895800976472633330832175777813319085482845448178037466175315338318160727120812659853884836474855380062816790148253836486536154443076922591406302509006049160836696369171380813334435549854064039132440003933306544843227534087800292623624537421669536420163740996831165122042964154095320881385932048963162618215125874282987406876201912904778843955756126725108506429531908326100412354016860874676615518854880568532926495152990504466121783937176558138217430909425519689920102846537702237774434235050047292690908485900520490978038251239691466223592867865243176567382788866433626696688869954431296928881203841983226524183653675446422615381486791992249121600141557021218867274200576189737566087726560073341825590558266247146974418819442306846266725603012399417737876828476866113212810428355482637145951939678301424427760152000255815083018984109755238082037469107943188041115005565912028755375682852163339021561537472452253787273035347088447873215784939583635748199206019809035291375129751456128158212005461237278726426811407937604047709946941716614616209461528473529193776794383863625477156301266600573528241536602108012659725554030688607686484661609213340548821570984499824770774660735948657483597115588702115304781294915732587970923887150494182079552168143445070269692966574346837396725012883728649873241261222595468801449855662923195124708818307234800430483750380559525562142157894016860547433166039821443757104684369384823514206661252104657867214205862530006300136355963752162920429184941477177192915569417967122096562730574264484782698027692407505425366899315220717083914706376116916195976841887833285203206638945302137414034209035597813808933814854918769992562439621916921754925103921389724309447605060209913124709176525668947863932209604351544724281195068115119576930828742630426041714255510800772894261199569538421119197397090820773842377425294218583069248631444975784685408663074985418560719835379082173521798421968772441359211912451741234761410410620643673401135628662908489005872041506645852561243403629227343214485366216781155257739137526139279140567906631385507917243719105715032509394687383440215375820078884883530619822415050244551987770879417896725457816579415792606737093161654431223328299384689721829950561022855604574758592537239780191437838941726931691760577913449994903261065619652597766463534188498677994878290858723477103482595800450007300860786807844797026746852435689537537923876672763990758997650661214421183822635256086677788931789150437096695184632078255063634379059118712704818841587375493915576487826463785592760296395811679194717566512987201138475524279357739881669461095296987812733970611708680927544133637900754406370787041606916422286763812719022604485444410099470364354365334917893198636798441898184490720397507095102915093002274091645875492597411586538701664237430073485722238761283211903686969654836607945998223218367552960872051729218411838907547178163267517250784072290171935824859705628237725434516764398407183998152710351635397392579819088595178280942691057389804363361408059692950097607183701180834274800455119946700781451632179667204361800343171221884330181361876131649746294581283298387523106718033429662808194642265840131935462925581887157919009943552713532631845319991216502327667457120251428473346723777795506025217669853128471275042843605036719133676211844293114471161103207379496987819112421411819846581035486241344607261266556119685829807018801420172263424, - 28795495281522628539345310622271006745776647618787203956592614345157323874968614639837639306219959912133994622745659177429988091256478001025122850595510546239973143669864778152759469558979467814339799147050218967061790607034039722790692641715245698783078316277359002496731410042442660938153739023922563258437314413220871964619424096838791421626049475246135054374414846339965785914726737420926437653255432046040033373275889439225664947710859772986214750706995472357054649298252581648464544294679681664052270190514828058064763826872721595942054369616185031692946921033565882137119860652460031267014326563490444221799172734586279068659384759292125364654960342923873773398640612682696621077299696492413213854754568394855900170349039612882507585799569258976328133219318554347507585706052043681399091940506903255310786948268714308176474460622669544603307652168246650417972161224542853194994171294670292032854287676857942332018989731310440091362485461745130385403961496639867495137631268749956411387052535330166033090790216028682605533293726922574666005511247169507734516042449272832620007352550677231574747595558617999274538318306316884978672123914948258031784904249177517557694728383028547475020206159098871665199156259049736165691993331916774067586832628480737132619741393259480788193833465866201388858136665257101611014388663250847944280888808537309039333812759409946821785503014389553904675884431949955178739506287595196803029496265501720314098957795107376281823674004929860777546325001173193518888556486510281152600467807661829882568489093585080730966860045597362807120899023249220857867854498778058308878218138932698465777580631200749758033538512892246090282641401808156205162172544076993945287444973945000473329533292260452482122812424341860868341463190295371813649143707637493387441439895610734567455987400769494499873039256135436781196088332296514931637465175394134576454789433569738007500356496945137803591103121474282686097770457950215032836375386565333583308662644993301881973490212969774285103530516913744050127296370307028695371496619536390628510789606079607381281293886288489632938503064184893500491050294765354343633318594845449787127850250022205484861416405215504576462852702926583254929744907120689304231563412406552319942518799143634781379086289128784769945975039734892509860499504757779214144257929600317268751089216382670782202884845114100201959517614195411794215796162735855471108850243777922929738525702277584078230684222226950350112022183226984266174899210006453209115326862536411004021056718934279893675498349635253258953820602958309749622429583078413871813629078008719470356792500084517101705074247426997772487788237777829944393121444492189440488295464118644430623731494038220767723232139233222167261661269483598058850694289788837534945393186154042833649757479539395510117247130514368487554285442505047735984780632361208230717489881863900641678178672208222808618431394927367050679198182719849505266844301481766595670222007443192902610719926148746059088152792565326034659541627472615651122296572134902177228798514881274896195274614716828141208801311233398967360084123659628886063809513396175386053317762540062765256577383582583107411666091176892810475973039812786121590913088028072406691005268368426542151706320297130288400443016584374911879026376584297463050596681443721603130025499763695629226274918345095560530436305917243980783971106117671927312672185969029534008283632075236394011167690742715444164776315348734545322224465260777312972444821206329514119005101386704720508844169691504968992529800829842193160916988021807685669485203871798938694290332782363892595210405828611532868096803490485482059951855593659400863833468951535289032279511780813143897477759392786216351773988591782946341240062671206875395021799601224667236515972522547726224707118063350097850744470826985620953849033771403145882405497466607653626283798977604324741713280562262584063251691582298904350212490227110598527924631236701275726050384443055944937803619748552340609536047076245033973869880861021843915964699095214133535348081619280075746845349104589938936441716182917073758118693133563040062476490756141690067771454277938538134508732314295796590044687420272290134561788217382688986252142751182392956371519683059190987268580952707616883113074937191332865943871232739571469932662662749238936956116529511139285584531038092610842747042911025221394576394576522493014776590799835755964529465852281330299956861257721125328371548673804724509541681227705912998175792381696975384591144896617140460344770727706690729351141637450594845856777035861224515328869018116709982202964035820365204050966302736365244847779251498293697767267147890177384565375539066025938180037861395193650263265697742547823259852636105914220379049292348383928459913360266254265175638586119213951043998718348879564667783332633357079928388799771485047650683950218245658045283552739465941358148274911293323822181687943018001483947573825484366760013444677263566150274330226759019766160926569064866589763458238020095263921182825547385156726555455252997213976237461949561437968434867116396000037412264062356059540931327652223055160320331016494331539656854882454987648319567923404382261621480430724782047446669536695608422234854714323514295254863147196461412231464475326866014121229524385673907449432031486395577650451873726879492301414208400188942648140465822585982753732057877622011880144115338061354486718860033607350845739149303158854187606755264319229028724720358715973158197597744760393456022679516759555488842060903607774680102722557626800998483379317042194082711350952439928068799278148746746898763856463543895266361961866200692442994398975622934766748586199153466191102679056351574483100682435541170321394524569672179511047957855669292575629715099625584552862814177015324695839053240087529663501124259965724966481120368048373419377746211698534612857886135446659254441479361621743255026465705444740850939730087975457732791966047503031959815442277699841453397588466241044975407156325792828945262495739065851462139219686545355895027831906745905563932121557068978235771473722872599955893492805054393153542732729118092637228742286779487326247479745470537367560845913508201403403302630673226866921119075806024105887055180599563408161871804066360539736634902663597435356184162715415790735012575463800558284243763929527049517755798024288739438501982412742942661990493459496732632152174538002671108811272417388016902702604580961791600704131198536517575076020255369817685811796661952976597186011606067787751916542982447118575827751807400847909580923200055895694233756743925889746017678079396592787676219141305302734652121105409218881102004992515581279918031297696236193088162595607658184070421287529585659675259277567392951055874855825017152251462561080326423053957277061281438380231199364039683113070442782925647992004255245889283976473523211582693789216020437649284771086918354240655463555084532988712998906397859336813048635892854222604959553720335036741010018061428719363653493718676191830875649031514122491074551249352117185743182797522579600831338567673446186434640742987595195120824083612820850180493057223146151834235831297683926969135051475120682860351316732916737236328484457229312248658874822624943547603283344460818196729358730218350686770843182419082158133412428889667545834631055421171693385382524558768392364286032557355419196627153623078039837299467124206551066496486076895715212849737083776137025709528281695708006683801445389316885772158582896427296283116317328435293437861668186102092871058285351025929132779309293965728799088736245630170982659400392567497600686985422467195572880554114611366702466018019994053825355404185014530876027555547989850921854329711441852566447905089367138075079619203692228379845490525504591437954343373491227258045893627997206005431382814527676200913358016948135799653530136558101530584690462443381440097372474662138547888515596058022190724449082979474403799530581443106453261569306461164889189760656455866658807904279108784076700546455722588137313221507260948928830625935278970332199231760194599056299515626517642970737420211106388619902935873909664333941226123949876842162129371804875772344557397750742275060330316928583025592193423041293356654626683560967758595148750841691682691475777643421350404988733045878315757942833750565282683302378262263550094913116733748993399610804046749423716345618437119264251073154584455428730850831449214489723127617234883134020480091674340247834704243066793026990775722265714121297935288273567802110853400252005129097168390622312717679712152488183919633203383842705436314763253256101352274708914488287559321396851934332127866353069358840276933906702483010465204017584600087855501446191524165803034652500562243587231861666493718688207556955732642821098895504699927111551949142677963957507217353948842360746675143168292968250014140264810981208626472830380423286629436340148575910994260030201194157173155998812336212559489110620481531156377538001341304964442011426717158563829074959395021099327172656459556314693889359530076623036014444530022004045344170571227710517395410804594082236822600722791614945078491734020391714278886637247208948734664593861350798039996789966530765254942199969008586881297728016407842906616894091858675842249367583791520472428560431473221425072075124820373746434363989259314111532020639584443506502431607669062496911661133417161009532488929848945254638673666502176691487969692509262985481257141977882955807799150505474128223831220030936015278971060571849310275487480233168992916180707318283281679364346095068580797905837143994207537841917530054621273066640432750117919298461828054735972752848753456978890266877327988751180725540124934947897229564520186656462108171706041101473949267494411435211142053791498585825056960233192219753909099141655854965925883696610531217801004632856745311713391041695826034947047694918853790201519397123596194451277777014847830473788624307625267776781752542629572731647681610097006039962542718467130681912407002972160, - 146273397016117156915421210301044442952656214497923927916255462450330717910922036019306747020804159122605338694129188327762144703480584987687545638983638305745379371067544453316621944360998795029382089902557570112077212678405732134404711815779325655792445161898238879772834513123363513520915007658231877658681736051095921616950191180690272669451926179672482724394770399246762083793859062256938369812745705893099492421756596785579032704552135961646928744433906664348364985822641451347278008054150107923977203165762748224513915377858764724169236900373055723063533521854442479323741010135208821986827492225919743314031167369020807471925821032052288883863094611323144676822684028586441140008762187912948049079521793397981512056179736149795035131042169054375749789938788385566563577633924676647553079799224694062236097008007929672974370454012175366653657038769895963040274475328028344097537103333878424101119910192035651356065585418361418347922487809829284235513307645669890216421338127807230993827526853064380524739046164466500435822386268635239771132657599720120315926459479761474550593519603174183895686385392539109157663489156918669916537172925885986583513983021732935334112886614937415715252690204510460403740792474107569981892731045738309294371166886231190043681382297573416333407283420418804093173391604538896415883730348029267539275787196856912234985504605224311256598302315515085511519999753983114945849730776233700704515549295271764595781323876051847175774954023899082436284736911628421622843847760500333284201292979044672739453564931101263878672488519437047758379861653736739754917457299991942848926826094710885196393261407622965754979920206883599988429692631535079170702806367382757880259697181907403358339549254878292768274410849524095058802956513300557704872495436848677934541268186634915764556198394574726149255945249599004770759336190268196434336627862691078449529437248730322496712070974613803195146841809114538215706915353340416536766522244054350417882176671693684884388633429154485202492736277261870048437996017310099658257540988814249161792743620340204760561061697903321509443003596569029771776925485664850275156384147673383541438707211252776344768061938604241187359301323053815807472538697322184264215053950305968534053838681415747445640269549649855905867150022031596084482518964857343424945440614347452931807961440847192871786474861227917321710122701001794985485321384142860601072405755386757580192203005227392864353526169691022358857949065604024734360491898359311746006773546123130535030245919380975684829737081914152737109972090689005097404450791481616089995144215514237176026721513225469084341157315735173814229221654620719535840665166903695390326257657278502789522860589009793759708222105311544138549806704587359573842575659769699618839120632124278570730041542238495508212844255363124749664642940353768345467719214530822929930347068831666740248095685707048015462755514410342663755355502977958441524006517330388188435321202506280591664841753676633276863307311838820009366536465927652540527284064627866802364198812235203554950620377262957342261184066485380486302409882039892302850453209510154237924403265213408587369065403436238542201962618168004841287663059001951029547534333536147934115620125185444196114940853057746737677862012440169185614018531909326411296935955055035198626320701457818468733635224603393044138306601288167786525869893175208845828871108534854507911405109702255040020177034347859013476914096325860537308781938637062888955623449164090470468524059416291112792257660815756009182730294667974547458198517805536310645891634577222012210053213278189115397239125426346067417152209301980144414007709358729211280401168027673968598400664362035699998209132623708651424011116417014846547927055326476007714099238830082141897655308585605697272998287438719950861311521667375515878173369267159429908652140368542148539850341646683904106675427477739780193936079484381369948309994335941895697207502364485348479140815177236923092242625550763945078290575032200432206365839980935844616494128982577553702281175580155547565602835260527306778746031697841696343856786305294202606048445384744971430070710862153893856003439056085731955338941063807274148140772660540591211245095040379191182309922536175277169101117981012232305513337570684430680496238355532018852679865168320516365362672925337658415967085788406747711707972948894140032950868069853271207311837550206964314868646575037252359352786415393716339483475992282789366622796445174497521717166057488686899109423325329651117235530576733562063214750812589052725523231075761356462988477051706461776577788067362632029660135300007629203006239091161210601786421357486015699394555030694072556223107324090883857799220840070736035461130844365040079453715976036861496965736416659471681581329309931280185603477850837472397529277851843229060350322492065133356945345113773731505847845391561654448452827088233832755908194657485659366357058854157447038088522379793468009694594627469808351360065752155482405935821886053107024095794225060335874186891127919972658292180251228077008055692774530081570788419263883045070073277898497870733753789874281909470850893370568456317807123427273340382635082154953008670563765147092792480789557629475629130032658759306887308493507425218527666834272334573452082618433101229805715203610491831198172129387093942754505421012215181984348839993991361122602889696558577104405777076185373941744848565819136167042282305249965068743666906013444619641881737068949547907630606708265836868324928402991928814485514482208412624128578553700141043884842899882693556668172256188001738963808983572565533524958152684757334408732993465541361765095071568524797933533027220801040259339038736820744979597469467936858766782403255539134950848627966477815737126769398976516823023495069420147726259752905341902777459261060868186846318121022756843405628131040130147649401143730967902455221583314576332981217067309693405172335338603365528636205289349295625238259175930970653912176610353451303508868939394547058986075148742931320839251420993089262668260851376753457670347880021000981583553824001325379309044300422219315675035219646712989107566951873758787689609597111709316850183152649627390336023828727208743036316554147369022017473550890745003450074370502737091842612267208193352477143685229536959763204531074374697036952799915236393884686254876583788289983016618242677880384668450073306986112136127901014077011226123212829215128032498299337370215281054098945255689397817371102005516719691375237341857573740445841393450430720570080493300038811626613796519068102442077180539683154788291149356337195871925280680852742226440335091696630618624564577938492992666817411651336663592733795410773115546129729454793555697269860497830694888698172047505093415075649608540736012041272640848011341308239511799274123357412045361722225546313665040141821898772419361142681190208837003510737982285814758525658440431614125095724667427956639841189930037114415562916921648044028601230575754921120588685315889367376598575709878907594238847459662805696995418093015284036449876374244307477878247399738160904642323497726020018481188049206846299756553999434410423370503296102919738330758484859650556768823788665719202914279052104631491689737148577764324930720368737377799468137082915609590705318886903984479153992499151101954185049172047964625017980296661646907255502930329372442610778280048913791079642816247771346003365674453204438807979652486887349867146829731330009915298614804239258641659773770515582495291045960910552298164726178395761626069256974944336465135100177445778294544503904626680962292869487627179383025919577934906367756639020574461232597784621657461869540119338562110456821991576876671352971813033526764839559965186183436940608857692848324931743841979124299595664136527058473292561385081287282924804827900320168443924182476925004993960899260273372740385240541085113795766537845201400977558770421946288267208067960368432156855002462834194026544100798761328095930916156935661954007142107378674103806045954280934686315379164761042257469489525428460824211735126379581125306674327422417670145357696359084086808067019001662455221976971367456180916356409928619670070479760620352647436628606880308830681251574320039540815308016263744661232169773306524506645127988537116232022780631464136903559628665499883625176675818849619393892775438350425076909586775641115102292953069558936106545871805013909158104815943865129697320415819072500419633880647420385366440204337421735989481831209814321071287945430501577459619987978654059105056029926673086547655405877954904969303431868597694510836500579373836402379793140016807746217128587172356102921613126280735377038260748341992924856302866735606806620081093255927350758133077404778763558641464692581759963560301435574917695877066846542919918782890930431207392653698451962139145568256380436773215196246971116221637781029723767793714627001976813667272026923972561537593386438465860598764887206898112218280365779808179987246989746927728694889852995007851194190312515474017461150556909314921841602378802895813245554251024857895238984353492924019951563577163863787516300830814459822415329045874522396945608975210275921950665326795036641661193052855329253813025412802450764233990859201906395420689260581607978248050592624127416770314385941279356381004070838387929977975017008888653739362542477033748978427030327261183096901002637458633341051574221043998619836877348338658634120770700428212746973466506593877444438695424403038728682673024601506705128520608090210074670753866509747993139234737371210700564704070699975115359122116098494242847650915441787267636241422882669619206313190581628308580031737194082239078016583290951719448576622266506400073395485398043777371225269072089516246207033371836541773884711341282172295535811377986422762512288848448381838850468459231526519623679047808500580078236641190474703838948883073235282924105444547647801835407341984628379327400766171590456990833509903826129197727744, - 617678744407260619909594489935815130474897486387474360020586964271593647667377953717243728697049868946203204013609485580424771277192722368023610925387091931568323864872773761582041258963072662623346251506731067872501426929604137858233582559810621138263215900112889196802812530862274073532414937876977162025281334922675695070198164609760124302941038520026455302033310905598632408019728344209068143375766841091414310165100063841717654929230583191376096780173179145791535405702869331543709659365967485535929494241198107359357755190440169666713968645676472458145703807934074164515819495970549437654858258958520356185309857560632168173371447923615145484955670787573653762948350426000537514763239819604826256161152974741507471894143057793551342050531134963006320987054920136806392251211342381040076091545287292385245071437596647972660718225201915319261271300773640689368364129468722125503261264433631127599409052552061129027537702566372896481459621820722937492106181300793889266338967964124517034428536222321923345644211488332986920444716415220098088190240679822928174755431448926041967140867380722195245736196288607241747177673507775708116578052366892747092271940239438270067287846990542604490550424348982862271522226856874758389795327459641910075105833378861688904519980898469020331794519230589431871793094615903591061333956600411456220866489823260222506440169119575805443686176666216882880141485619813003537641441384819156362973690937497516426906724187946890355458691558450983453232943853069656495170628519770804387040217378122711770116383362825568323101600368922631805039169755640683060515132985233640765788628671296163006711051432307564825749195076453417025137341065172411080866143819433801837152356716347838128825330006816178494955589970201008173657644105337237784055750022737665546723203032751475396217504507265922175319864648097602772776908366004670077167277862901164191028541851972940190311363398201929555704205339101307903966013609664653468790361136538798094643843260883093422063050432516380979578155997999511166383644698839637420362766499590522004889817218913243089740170429114927490645004480400495297121276903258330635620576594568088682607046516365787006467495355507890613070250697115719654889515790900995883346323689239679067549327797757851664358352829668815172095269756204595608361599265204817811019626149812165121070992914286899120272615110480024075241963556981583703797237021091414438686688062344752783703354189439041055587204602703875455107700001747119564659800501939237994111223072753334655856202073813746205566417512953450954963592231534976121333491966970577250083229629854311769276947689805393509732284189926093801024347235802108200196101401620453873177212303766114814213445490228655218656466535514742651428985843707979871656190240350726330555111119953192299828090023885719142134911302650213619106910367557117744143526358261009836571168586709271476960799557381727376104738626936514406839120554566357496956311073189549834456185208221029097617163061514858878111730833905725629576445539259856835085955744866263677693597932911146713223864439384510836717931493622778243818315888737677984423659863604423140798996412821256385204674433743818209947125285520029230704577413335686298889824234143001577517036200759541463067415033526277348085387874230857582115084230084905128821255085442384391075112929142882999441116917853986251541414482158371900423523672707089382830133771411352568856723016669429078445044939012690929726033240673641663809215936864676329040347513292820519963454493538413347682861778087957981758917432907948983266309574081582152209054095222301251534479744060704234947372009967428767344895882420430976320851938887542541577517268122475534454302731943910233926220483449618428047255816163968971781246966528697642137775538054454055004653463923693521807258842619730571346340298175010944560452803991723858457453671922293358181833135625444548959495389239089083077401186333835967617091050677311632097509888304154163747000462174991915668748825206806160583505326995806420671634408804108139709497293438353712485534834642782157060154994324241628918486945577947331538937932602070769402922456779098257951328652150746329167945339082147625861077758252859957118585181030742857453445863167135344742281752171611127435290646680602007586568886682999791066781274388229021481979355783180828288138959273880985778294776815289624193074200053878357414359401712229441327413542641234596942008720292725917765220777856304040910901065629822141575740459132546131762610364399382752373019146093806685426695130874857989846441208798062605442321048477564993652921568080651320532875530987146687252076282368933085321461964137460815408166606472798478203308922230331118802002348117131362761615805182641942874084060139353335519716059521769212289884142743465149004924671217901845443047077849671564130335808936719683559490577577165977627502056143218270214520796726200194743421960661404899705593797790136636430928614703280383595376333097452177031780095556139196327820798653649145226390398885903807808616906379578389073320584731602127196898062353720348643358263373421806433628955648605659478573416529888168902847934104534244142140505736612114960712804767981470129540548983988972791506670803224737109886542381042363071739327457850690728203997048785927146805620249032569459161594720963510236479770602628765688510465507095744262137085885242098908752705618530658066481679479332782269040378827507212501639279293169160947850347405476155643136838814456180548685906960289296837625619722120841469668081847627017305488865545880768901481574265845036813711091873044782742011626909189578213767396210502844055481586461334826589353468238266201645293684517322261293039665196153471787467418049083097229727255766186078510404655682768329820730486177490692511361699661823139869445173218713654629854293006255971134117710822186954492323814130507767674774372973676348369688069207630509241603997856613651930023795731056097201323440532090746247494104131974445054884070275976846913716599769438072527546852821286133921498476619827842113066862675903189775383739308805670427363439906416258727238896776331713393681053658032440600007475715989821679366176241961266603511010275142261362175219106983078712396063504249768445468044659652462928059427625916952227196030472043208703961871171501546142383870244799969555169105967737491233684056707571998345029185880604454691753741817587062829041582287060640755628170511898244558007507922372272651972367555850287206031825559363835711016254206481493209440639520124759533241917595657751777002529871679759805323910364448831612669461598314716390638944032890408374351788450185632192955860858692576332764460297941322733578416948447353991666099077337995993319989424439961204930400775865978769510478548531762396918899692032804317115795507939367222020698040542773705244002865571363977973275196421579474007684690906969188837994315808285522015271166754937564226951653042970556833974960847182563409296925235329639493623767203784987949858610280083420795411172130591363361822386456023175740868176932965156363775465840664976932626832947638381538746477481420547869301443237882566566628058140653206835385421217361927097742789999895857730075366235734131919712952249245364462267636190015589304480939465541701164074478802444077671238848365657266279552086517555392856318715591314731426322141833700919828406876970005986788251598061250385755449010468480637393773347423115155751386703080208035954506160616140560421304939839328049265245462635657134422841508449035971672666523914054756029393275567918711813809684760647918618456575292747215029020913469303505363696812871634189629721511347868373067233290892080035776230743267431130434910322442901923444230003329386878475555209506227652996435890518512733824764292567509148372763059545820663740247949221976987538465764010221023370646477018501634025965823196645673539004007529208205129176058328940319529337166343512708695007208714828503532330683572652624137500362569550587851924034849799655230644952166968987721286156290077694138856731162579826962029347555248227975442825429087618387223212897134185194972866084753004177035787093650536690821776039135244610756630980301455754514405044392362229323547235808875736042575636435082481835147264937851994133096217198232526125439692457180482484960643031590468544727662010931836465108140193815538716027476921183211683011487336991352104156771112809989763856864428048191566066144478889352929208283159082466085719041976548482097323940028220766292619762401244265537552976487020614683704592003415532958902477181423566738458769253999128564431799295150050777555864186137717150738879884701961684401925038962508743792923094992779333963663861397325826485437927611570579866275698221619393451326088480351373164061882394044262480318732759283030523643506409618468962747251061195970221834149353984645294661330457032162067845121632464951869243908924690797322680744989390369554236969964709548623009588818150447327415133481447599274734517248778125390630506352240081384563917129641822178985157408538277792320203488894411145657516526998089064312953804886452533333908249689565444979908846684210313859327755495725303936513669152591669653057038283553231072571047625922032176399185417482179138601470667974675785513699752686023319443901530535607648093689441745620145229892418430768781863734457500666437172165556824756767310535623279857892649129848739004710079488995949913735836098740665282899254145345754673336780526435901048978443381863352807889990466629018976414201130611838559372287789520669777422374822781583441796669916015981726875229267332085297909226417565498698683551294692903749252819336528316553130871411588172249589661281436911316699385154559254622054127332008743935721365366464436946291294712005664929480563075648179235897644690942721845781315271687952600717292641180723102293416133911132279785382615855330951135298535258140919230285739936699891330002213736345484794160583633327866341268846474853117971031076848184853587296256, - 2212440158289027849736911812425476943414680319731515326523093556092130982831957822036314415142619844593008417963796656070721460577827433374517907356381092854124179300861038842597039420399156990946704211973447784135583419974319636756804505527012637505693584791025499582428699240455699966826782769968270465223843164931253700265644458446936169978442830703450726036224779422668947607408548491650188425846381094132984469153469163444802763781969185710032282483651020990835347097038252689898188425192249807756993420593831360248514985873360303987534804607983723868566131340287006439173276141909245448166581979617365711767742528193197634553937308692018850698801965623351574067809773615053495384522983275536155398509351056673220490909595975129165125510301475373772177774290817136224547609172819490523259358606638831628670471046106204062411708163161528938500736010859338386834689198338476817709836898164540454056909839982560280479304938010514005340734414061378905488170093978065126622868848872368231258795924832993016098778483721509866390114890391345643560148010179904525986361469491723443644879948271191278223877162991908640297607984035885380697249987834071269866755508814962368919020366602092505678067536305872006131258195409731299441196767360959854330102446592437502706834080486840032156195238599342972791436278245537660611527987148554389523917401031588318638886633290227892577128629093755475118930989020574882736092419347859736550068547361808556859646512487587270788928868510210495290204716124357885675593500125814880817152319477552288474149808024529359946515395850052888878746129035634208125951979656403480688721062773598908758015624581218639654431275227623867236883229272170149875983866089632856203040362935913305970965331391927336133474252692006629578140319722047680954891412410573409065956495992676781483845978567584419973928090131859077655160724821746216592827930853871288561599769445417031214432176041046161162241149498364004880250006775520067059497408102238911853667352576905373067191845565117606762041796962580449722387639216477799702084965665515073223717942725051095488028926584190448034817283555739535927746774221314405325243436716317613143751274400401967430247613450429888105533316994905245427333146387884788225527814702159411361284454757104331356649096371112696714555404676165142824679630735065368379718038525765161488129801323497291760081732674505417254370534477206200341375894463966295552658327961500802165445135411335826510788517176012627637161561242983236712244790207538164691262291031873641261104507801103633076343869846893406770268787703968887757162676732720875987911525140852881727718467104645749086279004643638594835933799189205424603598911688574136972593101680202311238903630034373695826334545541615392651127280718902049059321214648573954741474298630398760630384610429634549930963494872733735850699629298497274214496649244493702989002133683226304151089644608953743329318981179231709676611578674950559883467328673132349154171126772635779953658791791116147781277758113179912272204142028944261595374952566803460369257335762937055217695341797779134967650970061898008434826090659274300225200686129967179080784103463858881738140001924587070532447861539133442958139129568074244347120931350167144788456627804707195555507654774074211764006126324210204453149473605744413863485824115139139824916173298389364915690943509494526296171943789910015363862065323837813481145249764916564660507245278889157911958754577234646058006069860514900141524651391251451035388450364314802389570552867623011699987180787792110238652336592216780298749752784853519219259259905810815340171902887497517280487561620060450265512822572511520589622922741560042567867860483976085787920600155280979611905852844875963123815269902315994537460342311348614023770495102532593125681493190093109254376874796538257466455981820201847731656682677788376877808378733013038598870376262671555803421266380153449913090315901246562958060310886318129130538053160480962004171647533790790852611725560906732856250917815656093731969924675668776679292247033771303090268654942076744990679376080307659254558430015166153078591251019367765430838477616998436976288468832445394119406098173338948033309022972557950463332617738236764776461605264821138029548095255831636125683210201611050380619680409869449161274791289400063916160011543812397263489799489139634534969485593994559236481398785771497543607576365879301219472983698283427779726086511492258205793950848915436762056782080493434225634137228169971688064021592437901795084017681885488034286357691241828292086748595069570299891358694837157279679724084620213021038809015990828271975600323282518615968104044047547774377794994590304508319859912096284035554539218073682297622240782324044278692566810762954077023009317007323040732610326275483868197128850305411641600264277620075450627031116092666349186221305701105335278912717568176046698638637164191609193143819592258886207511273253083221817816156576120257168126242531655205543201847056937929443667423180696387385723641104022186240761462851139410791645874315967948681347328762114703195388012936032797897074931075898360346745057362245692555408910768048967921199874607568423053606188771525169877139707339103020668771687160243972873989567103026407558341601321369447951831935563939363984486150953338833516928887324270464048019799913107500352352384858663181832941554411747431823925626359444118757478744632303147221731828225148064001530877618204878609272777600992277403317030164243225213503340152221924082676771409979264303061443990312378464995939031713931951753331069510057834166945923618899415850091825643257372095994846628859108439040774623498940926134857999063625652393475928795750049397518041657835583214349537914294241203151070576224619164098257720090071796860539425335195652037974959493781934691883879729817553098278390959069535370778504382774937853526219925406133924472349096406169235593999392889503379485203658032253774514071895151174574315760750956481316822875676553879414423488623140517997082376665856131309605622223114669376275582538035774315464100562215594230101729272067726082042478384820028202642821625664625570926160154785828711726926382936091220366006750842703935737004008306051740919025286336970344530660873704180436915494050374277006274710441380426333225182358494359252622729139779225337091181352112712791644774944436299724326663204587465669775514239654581584124687383132750645645643099125571536334608450914560140019968131766865561284390071133404314274416883070328426406119278040899879806197204282309749313661692228471986844275770851584969311907338322628113923393445442780539123373718482900237470832000468434589813467988259000327594826121885270962193200160367896299094659211523444335833939470434727161917166856492748385133109158409508985406138323216571199995119528782235287785661199514973523328719932524676682237279184236762074124318697860826908038626611082190409609141696618755237765536032698043681125097095543881873798753359712002920406784537420988006968336790921314012654151649039190693060943243529914728333670533534042912788123319015811422350050060359110262294420027607272266573162228237382534138390634382530899481140017693645017264613781261402733420770843350126431791690625138142391866366689591235006273872062259046739110020977990430421460352206892136716734411919190418163146495563734443023157060266405047982814683821507724967763216026035987671646797012307448451860008095582209850894474661369482133351662119388311565218793187933068354546312563784152128079533223666175598334086910030965926265272663301489035730509954753958048069604070560204631542828750542530279849679520724156373273732210165944544720530990478349079339570282241158485438307412121556025325573705045505833223267020165890357563141104369364194846312116546012375624747515411508918390425659183377890973781845247390413938985222498262116254406792922989781022406168830045896466527383866485500650450455798853790565484760933116788900026651756673166261205538867482795524891056203647289482459209902175769987223916925622789660750107779812138139286862781706855629244478743135423608502254445515831297036104250678603890887276851256430722040610529654947967552055650171239566088542642124716778220587575699076654504121830740851282265263370740293272697557975323110156893284537188704204674073307620655156824186575008462959504996044303000614295977607898223243241588959584251620149976252393002485088819715205847703081849997298818724726453701539400100085825607226537056007336998407260535232255698408796901057471848513114058197910335599666275826994417705738447814091988685010699291089833881824540062401240987618098747909956634516326530021352928033666224084180189317739290190949165493821836290034084796435031431882612014713244065001997811338056664182790240319288397285817384518800007637325588100021825778672832529935487881823426665319383378854776734703577242529024204919996265963070199531924337592962855372757827562919027072755593808117591533152483906678722109498707425857083212560054331449331864242641969853573329490794441659594469926272060543690914104426554846289010012337047016233372349594944730704010225392523875222671972520998996652327154837031648815613170667008025242853150252722395823773755606476807948248896341708453947325303743390401550980443338101522443392947167499246663327898940368549926822626316274263574710938572796319189590248167477581405853959520711008068019538395359549756116268854210558594828355464342705172294104920523121503028683926930292117543497518109887830605197321148088615900455142316060636418401973801863058088963389627903778222316138897332911070126116569792349010262688944639602135218585725983543304496421350989366239308119929550499396254685686467469373902103361099481904942982451273234065062456758272452473138008118501248468715186703650202861488637958570860394020305532592871376259619038245825737478758507045743979860760396136045109790814517489122749026584603262746963768378294585580528319716130816, - 6825563912880172447512534475118669309552310905574684415084487419493574884846816106223338351958369903477489736776492678587612071338496855523217360526483688294258781790515577140607377497218301179617895638024860413718015406548471840148580775586469491282909579933595093291807115410352568734401501846797559614187328100863095833344813816648746938033182285934155016449424671350229832610943745678528146553829474622178900778000135470628499938729613359719546427979503754806975512387758021325157323862181438564445324119177917002822885614140050846366368093391794767555283096707669929944281658477351525763828911001628458303971378648290991318377217314403016219080026542436610763020349519965298375772038948985091255354401423781592541553770780647887569715022286798294697702319253492291347840209422931019658777298728500457975883368091384428593034364961340395188796181004249096893066447444961972693179096072097108804147157423785273453282801185005343810525250648005032175360098430000747205935365982155336352080544277421541585694047668722205334161606695919040926844332053951211505840851904010271388563616869796797156167601109202525747663574717069891710642998909586488287338612368928823005149351977926870958097558550153523732023136221066761548908172130951097929730253062926277555257558978555049805191721751047541610232496269209394765263184943331711735691605958402753913121250711412556068023174532227476024236823233974896981887692241411708914967225711361283158175766174262093457297250585139028727604438923178718380495745076866528653624035967085362002073541338453374446658546252926273004430798818247065402709146914968936066945267089100184304918802408924180132089122407197743837823355036211981874860862688271380326649481830222670365538678336102823953397430863868709126032937303227593375152005657581027752772343521637470895505460766923095029208424280559481680676667008017875550790950514102632234692633713242189496247021674109628822842621556303109501812659095997621760178733073350897815319992375734844550706374637641809163246586431891948437140876488480081667017780025489098313336142941598836444655082684647843862031562045362893496029896572126954797205611456019358943359356778311380283661923312376058016441007552626969531658893246204421002865939487827231009261127641321711150921245345468440147081909469065417329268912125923311295149640701096184281645146937454078991004814914105499158410180190742805126813902797279948796368386412797728914465765565246592869759172972553741330818227221571680903738730755228264022454007172127504502628277663835790516942383689622550839230291006187257785035697843915167379575541890706211839587183313207199948900549446630372805817974848642864363379172026514789685321656623771213348698050305211399534831873662133587761249519941422376653480104863953182802094026803834577220881393467969894726578229978937109543888887752394639549486286859601117065799332151378765461190848163354509025832842191021793219482200034127680600272042102872024265277375291608319610286670109988398835632170853892926689863928598524514266362565799574002202728279901927306646324448790611628047532996640882016953973313749213752088412809021754904085824054438384672950794356663753321581498015300420070102890072575523321455539733488684857848619087879947198754697207075732379052590174418231582968961402646810181027630520878044506936002921851246523082478275703163741656213930790741817458079901807028656385035529869309194451980727436229579783086225510232532396624822821371463281376106094959858747369298243308522401938159035042972441774265317132226786550196205756186048440608351544197171619928895335515127198324146320601010556065328709822245658153479379285118036696111703318590695645863782410150945925762744197231241489642912442624374562051018665545541450533963276146041169008706255739197300396371637579373953785461201872287920361691855490327287793315521867114774067719348757250924936079261148874263043489710768292410153943256490036554370528182685214868456782322897988947552204473591961188095708987619739343910157829679124400970953175250176933035520272551185179061685212732657169873181802951800974567765445019042877447613436984827075810049485226338903944711941309932539589727248411828443524659529154846655107845077115959528249572617740214186798919103448796975184385713719014520966820018944029319189023650822662209109300375806236316723806623831520908136015593901368255433985199338621698242270459998129819356090916132914688913548715799530197795019470740132269173819033407706993519035434097259909783089331877317711175065046000663094581106809888318125323564653062049931442178687556741742987066596606525425451037444547141689962098489577187648301937587439552428077043965381671172856463885618522321393047536205228954889224301398633172181035743040206089610910432103936407938300596524943016243765617955924685026522934656239424424423735701446680905540171723802309350306494549716361088726236559668013214042982963173118783077881637013924383475414389972728745405105947548470816806207088124364225704385780971152219237254045872830589525010939441197681042949646367818556210494541786974594672514634513912496308964428939358015423776042491447728536627481299589402106631871525525891309596515679539227363276660772700448825988693976929246326761238350347901873151136640645179373726346568786129394756533004332993545759523746082222946304847468635983726811413314671345963009363456086575374125974890933012916587837769988749589548088448010069163773228792330562616062897845832933399647434308732921766724277196193631736207319290731459637774388890913694812419880793943104914225965382361206885115285836494334698635952800847273718991226521141591154173260969499858561131216704723427368647483679823627306495004462267265811974809051769402603475364798843646939957445120801107073349006386442447650797896970772905102523920558574370074059257445578210913805004843470289659222253464885928334451060765502685412943757105512778926303293026319284867082910715655038313586446588381427123171208591669249477507536752571370343617014519729132853091609895130338936270199234159801439521272890522432475058818328743087178443470562485653353692282534054363394545283839487359606183524514456279523176887686002642208920379630588449558798331086856417574511680581686635248743912508347139490728400683388828256751894487948990355078427270572567051757316415098014276563147931242199107547463277796053875076882456554588227494949012286081008950565835562795203702744351580072445364377819059118996454134163205632148243315112543127770641752868564817110935669469828200955124173500770904842280504701583984939476529974078337228277187078667225862444290485871460320095272360263718855822714219755860672130442031491608363920782153866036014024132934845299531543691393129471262943735401836167175045909696433367417161308248793304122039768858319088370800133220377124463788952320502251748177240223663030807739256294554395548890184098062088240577505464869851788467680887955670167943955698538111580697179354767421626758081110786865623238877588595616271296388727833940412542496605284632939984766175914788511220393406835573356712395410316295122805135037875532455978376456984979764413115113904148928628317574854322091051050567780768993026428896133674680159594977667674885643350785265018104078137628494170642620520136478818140197051848601353559969353595773260834021881632579344373408715770776679894804037221940021085109866815782134669895872375530756381540246802414696343350132614812445130709207531060702421753508491148601136201247417236068427214159296761546281988820984821038306974805278696387489688038830428298703625206711258987346825114278768871241599417758417369817838995579157981804155026522642354047112134217530899929890945694093960589495349561410535701944797909513153243052847842474048346397379151696916210549454912665177062655460426571646162911768369399509123712118686476169695706965668570876251498409752618211910462698215092602327822403783870835267882596823473268490802771452596001380429313344560627736493540436654509967677659540120824639292081896135224218451006613623500259504034817997124707959663415372478139626966621642918850717056417603415973207841406709317913034914505031807746474657624983589224054970257136373753638199455294279035716673201752850279372710220167499049815436534754153358283394414252055314180886627488364617029335198471729677226519650109179958574963315406937832902643394657178780580235693163775938041858927943357712615152838403872268799461407273603629791887794718032596421056187365264837173342237164520833484082860179231591850764181783536256105219255261275084984364633126971702681420658722792129010481341240931369892997919438086128421642493032042214873552817197616449145980950944146610869949838262573357718216721880672987883631363749255403220817404126070166560776320761923619013633029910753609040952134346532382476394415995177558249238014489872085480572600071781539752494907565055624087874709187083682476284729741179278127070933475746177720149382770265487394587727728005215362922066841565457706959980429526612514425604412474629203866608671905695669974881355227882059185868123686518914336256418159231968738737745847428106843138414244763058139070136307571408090991384267626833059189484059842076968255588919040750216299011101890977798548244477113619011169172281294374646150378755264626493619538837388964624411179784150067566707492488047201199418870149522162691781902305450280595154414398858754733641204486488948919303126701386674671928058785172761788990552005634216562983699886815156562999010605943620378805841130792903878531778720060712732057777184948340991917584419002854421363701737258585795935835836447489320595225036361990138243666052160520801329898130688166586561757366644932313373755545566295241535713316321658965080568140154940281023166964464655467414645811873792782892225055150087601212513643566201178748187357328005321891080974676202292001418466405330782901060985487564546582087363927077646499840, - 18355826254728417203584143447792665499845441902826616513849842838046185115990511821356499887554586866261997717316066763745342608795834531489797200855081998538036165466428632182526534980268295435776839476220545407822730721541759920186035826230694491607336707151163919592887226915750585904731980331258703629127339003996955358113983144570020665631973563335652939983803660917575961057923976028504623828340954693741718387135341539949433448590415488882422127452909474574665820408197053242139564807423490324856508406342441382844956136627371264932758278650294998042104399272284133741140792724909659042277776379633486194948658373044574629460411011355767473404657393421437028447754086411468828387553638937221187499698245280488718385529923614373002518865142582233491904616850554855783323662813596012750254078762842812952111207768205118354522571438514105309261555849188343944137909676107448404043937107508596404408888217719563306401944714984948542789602635246000473820006263550520401712573276430838882241420219149011508673794615968613102144117424867165855544756777278256039068358609995504218207918018414752719458852395344709477864575583056222226196236083547610464043362859100326936446307586024918733488183309294472178692277641860839383126386169990758066278393309311109868269056919739539281031659708031358480227707836867201499239094384614218537909133425897930523100151979448359488565197046256652141227363643302336500952894061375770831013063897553808371359129180784710308712770141575469572327630236717664893616925877742020843019071980606667823188652153995029625364776760852657806148988001412274659514965445177336552520361486034118261699002998643861624259424843221065987271188239649511249600680967021531833366423118144714310040087395287160301948689188569432896614893035682349193544678051493869666586257146698608196558168298343846431296331077902375276655258251669711401308223073357265968488521427865160709811162787444333623588332697104588477644059962985448226923319045564022279000284877217791795013094390429488904925520495589876086181447675491849522440776082653779066813261540196766592351216318891786993245084316781543143302577123391967245167187456554350492648234234439457314876204327427839572579164674638217180907053779329978125456365037759264007582198743658186905702538248176826410942979412378530528426165530869472516242045083893735493802387722700310234907049285130644507283639420402918653703240865244049299246489089039116026492556503938886879161117519170370033498283977779446472355945222421891204800195434682360451157723041307599177469079714805090099849749441474429141328342966028990545269329483641029406389561043250883788727258903408557677589843109795380286149423079858763824804034145104253339941121793617092877773342325558979765986290283606299079953528466618804716494093158569542939850789859114904496509249066161365158243646056528142784916550935609337849807172005870416007432987595854809231803401898560032355866318324229754223892474370409115800369404953866641114069470988992184859567895597127644128796026940222831981754791253461816522490680661351395678330749647782360446315357381541396866385234635371221636556791545425073936549216609309851190754219147966758806430927419537799924461406320491464803845059852720323936235554941534619631531493097935550590856048851969167554787683607483328750169257893653426898921925728429594844685411068800272596717957479563590403617699738221787563702616230858272485109572224422007654267427873547371762981141940260717544785449420124855392511655022528409333878958484709800895931170396573722972110101979231556467979953546159179180031184620760565206145406200176397777613749046903011522249785524975213422778710205911511413222150016028155607571494648776196965227403723088661480602543241579282836798281225964399495891238838368423382236289653982971728326986575115872211394289928568675589103784438862422984737952514428454356011406147277890153682839721625200197231217697593483934878830854387144287779807937924433742002253554092085109006157998881769204502583606881570019418904342534776928365600127542539094882703532106380943742231961755013174526772084097570551452234926451647300553840859446375710765994685039561416770761649534976935556499110747989279794432873207707244933879017756794022286858429219117166318461087311691223032701519777515103587564315555298640087851920291702713583219598861842285122521512014238506013574424841564011276647634816404601220877252270393922386506338712288312572376642710588473254555590339123391574135150838996442025351580366514481715988191462348494289774471073839588966491464373268361213677633557807479559384500049096981946295048401164302805175809119815123531353708986886275222877566268841386412485767288722119895329628257481809174140255968941540747081584003128076979331187493586659012099403581722024700902481540897693731981612577221203012199899300839634549093880195624829809441310520599595890562709933484022201224074967539480134256385029499684399418921171910597647088239629848475420022009515649127484435953700468829402624868118055885346596501770582585735576014124937847736255749246666988593197135035863814500141283476122241596363340410167889349116651182684735772038516281936186880960751975551866575951059831611311055362817747240942140370305756919976135198345447452982967836917152397571245482201310947872992859109195891586300538660751909497164373253366638842842019421891830059072311672174573178666770773289036087679521904245461204391458342025883972364876158404864791630072827370112901753015545226738556906467431592198992881772648571223064448203844872823675764852984327905143484675918371379729568607592401399112931189193609023328386906371454088342543307865584091739182386088139154375079500812335671832246179712884375256067122272429041634368894696791550536156265165610839925906644189657804754643035270431513547741846565392151903484920787200897363961097566927813377414432186669802824611539391980166142510632520680632762041775057897330703515273920733025891273653122957403338956948727146508606260686558478266575599246985565499744578811282880719158539642947115426105275891573722295975784893661320151364729009082225885489631677614380817169209727853286081895232762383390972881195607406276664667700574836205431366646723364210513092326170188915374457996211049601792196183123579102216354199009013572587701956459911480748599664514957108135216602012999151589944186185005877874553496288809819520063964577024726385127550841034489127535476302163751605867457681961603358978463791884508844365997242972177633302024622391968777568419152899358780735113165202866382135710578213556357617887554377525629774159911486417521154589265751572549865065593797213278632889366446581551570652576354291609840860967884559478904052952587136168449914456176699269775758110715764644640878243693432220525526470106089677958157897673878894951359512878578181344893341481014410898457391613473230253711228003634865453585185076375165064631983922421661998239096858826627763287340314093628723346404846677625405094063083205572987041533539760002861112438192101042846507312205628282488599520365570733730747558249655523522284603437035627070488119925759947492836586353761363141206609463904001058683316897747358998699922114510625263028023047529736800147897421928555590328049539171816380486907292606216547131146169423829334542177939603106810886443000223956989810817265058339692571821079369668707966230423319300350509070312874358127098246854075598307770068440951855380812516832526829159187938806253161157758315819906806514389178136009307104326715408209223961695251936151136753900720919255903773878016047744905373897961337244208251706325399456362776281917813807753563607882701721522627988850954828156516480758781990792395883831065933977043810099395842134768904753139247587381049420254988321845805590686108917247713239787205236406014383297414893574214435503025206452127868250490413478758861824774120412162061749774228829593851469463855015884094111873582898604579813463255978389647674847509087378322585190721279231286672455243812773830900610072963563705457038380370601541382780778717523769465054362185777833221913439031288143628353876878600371754616357885269186165484562021313277295682122698727009301536680463476876828913543990197394475976283338771863969088652572334698627660077761507305989825430604852215216642243129358345356675026664932393946651279254823087164912400850685069694786555552523514455009159916080041296634853029810406152608694316856670979447718616547051052588844104596029428192665260798853186850641223310717198875740689731763342633459217660857939516118490568193987196068164285833223319221155119950971031592421734295860284471576633197135146710465461099612007452003305606495934442967871557568820303468797259095789490257782958561169048234496912249528914520103031330377440852859857058765674763073736287921608579704475937123242624675793981865489497204441163402561710829059010636411177570150007688959103445845356863195384574689359696481192588088034699917877467793740154026367273250641222229616760208340264234096226792802663105241070655432009583156753027803450870011535697890503756895312092719722617793245842808441171160421939678298046597141945174776223899828254860721531444764129109329797887985412278618570042726092567148436952463596661648858582849437754404424497831143922825123800308369939425566556531266615656668068093137545614940060504660944569815920146687557887035694205585738803370397978149878663873318108071909165653680878228112886372092099856836628512270945035514047570784770609458114137554543313868177925687721562702191582990915690361823571261803391813113259537205724277681931892457658283078096350141315456498793021479963999843458801278455777728046621547923374080753729838919328452790567325189630851487318953985596542105296154738226040235083677646473225933466805273688335229487427966087716148043118163668159272310975829987253308856229858979136268707143692279657606790547847054884864, - 43447724659075631423823755499154147417158256700614127607660276804922543577215043349689658340369434986463013827597808406861132185314906344465302730656913477943695409780322039037038581500887404573582673503908560624154624680349377176380641191160339440025140357402489286892971061148979340611332408322287112708716625587180650911978895643967691528903176622376062176835878118294356326688177424117371034601932292619225605405349177003705419615236870966873870940600632237858671732031370395659643421537966144777797192565402500030912396327805896147431093234189282413462035827689815128866843860249725614274858425425331330052407347533158924221227244893044259327869332299699260472725815986829204100316618109668900928969431212247817028407494063201364252178533851932931518984258941838946774091035872212277467478708272492632644325441480044211225096326872614365141366537255466760903160537771422110461815738768600355893933022724192594292450325689631603049496463393235474949802490023450150018298675957032223074791873046522106265429946115399954305850771279087856744578293977704000334029430568340614748175133228566109141907434280129280646713298688387378152627433129888983033537011976636143378595988051031196584633990935030069946886254572145399944084693122576672010412608384578632051789890846150867436231378028230857042719634246656611972412856337543605702184880748974961709472141926033881680444500368233457812896820423996842786246088812703931694629479384421675141623091650415480199659591988650341606106482122784256439373751928036892165689260444723228443678369953584665065301953994391195843803649594911987808528892990329151030941934876056100216525995613932077021049624772378076987538286329158419960307494659772818327154537644703895070363114733801591311611653326643757549864722654960168610032031433196914218999971130318906168187940663003018712721370747783057985798209046388075412178450973581050919616410379242567203847617518343195643354630185676124775996888738766816933204987003735071602308424732389654130263438037635574048770710671839523664286745734770836713460904549658475189653717001231719449888515718165873752599381479688580028474245346073211901912975752921884196348574429021466256867313299765228739679059111818369491587194798410163481213342543172055341641238015104355543711120320744377033337341731511207586067768690546538981925499952576391484419985479369740490433644614355042839152427683987064668144027816137937121777241799106886508937414944213751804710891978631988238116696875252282632234495336362464927075009785297296216457596243996990006494241646095189063224392916860140282284763005269305292899774043574985928761232001044291040948809206381479862482332032350149679479902061708660885126692123293735301139513724707549089854694123897106931620914504158252675517491800526178421104573694297493653738383345292527741628014723976582668903660498372907687487055456649214090762600851216385576741568437689450760606643910206122965085651351049348138899161514183700266347807694652683676186286635436098177310256976160439913439581903234577259201987457124613986639045113024099131755947260709731181552649986331337593806393863420127161527275336327621532456310908098394387725402927578028950181336494770161599003669085797111433620307999023475183129476619614554985031986295767385080400320503277569733038622920177256370318279834655542425125767787260468601623182890824342272014076832891440895802447611627001469482137731213249376711436245360169008929030692645025138281347368827432167835723704029288583959537228367937412386961957948373537797937653069496808267694215592814613810020252694488230528352054221302875948685019955758456563204802079087942697368546395535939373775648459384312994463757268340793948424761070272451435785129735046233397735069176093268039523183160063659260096620025772181976819902095640467718948576400303023966142030505170635072186200945644244688386235676575494276159369532440707930479535545846158074696951689251390194335428510058180420315771467303035287035844921190404023194925607803587748358532931518899543262163081076071875083074912505612817800214224787193587702648962920812339890753849311086335608954755739359298478207618355120794238308964276804634971631911170393152141070627189724239058883001171291241053226316557796606450683096896085027418338364685080354928977198369008306519908289187580214981399597728321576379751105191986274360712991438364942484279547882621654909032696624035801134985015772980570169166764278929010248564207875632586782481535879077520839777165529219628438306111574336012110270918430796915061518043434837246105417384604681203930851584963877770994944325805671282432547887930809151204189801735574718492667223364069678586852854308782617834399494333904815164847971776909879696563601683492156784485112125920383493661217622355783252883241462442276350160584954202361373676391974851559289988003656815846532584027575302791691850076273543768104123131281870051465486171615088156838241898815851343049656656810393900055821342497199530931906792170140177769199631394701659022761874814293490551940069102498914124808540650073370432352889039518085491340746902768473559494400838930701253121872644206987922540420864795705552822451421697904364344436497495215864757308305501797317254100205353580867063722822475718567417852166505495305400883695151285958540740882017992347714160001556355707489308897457055781666370201812458461604733874470185264020826374365423183677159731144145851921620218536451868698884098762004234127340012267571764051104715892759585556786898037252947239716149069431681499136093860177380025895030638441217147577432191343793681111094052760311834329241902275544565047825650166948937786126098807635695322756518627294883406399703423033956860274579564649011265899780435437920528889204711295827537741638193200441633831001890483166667703282412581548155616803711048783724390893116686403683682210335583213902022578813988483422809000701054726908072067945908043695008601457703253033714432867643975850523506346893195550045191825914977276673429603685073825011783697203311535927073275669542775560684935494683225272244909635995335897638690197176561019008458801131147581950961265132142543660973589333207271528668693145000340326235149289811419547422017814793522634406890232527592570581623806282959266858906210385224752937515840367127528794332436833582567785814305115036324452970591730111390831854889763316884337515436858854182282991555503324731644506100727194850270220363582925965012126168866040472386989082627977805400900490010451156462697599865801812107065819955310488881886885130432083400509507401693499884504291160965351609275069733111627981495779173727551722505738436190629782829324406351292036384395094608901962725894450643669599762407755723255119503929956211071398130592232917002531913379507456229643552072381625270132627303726825032522364262182554951946241189378339535107665830746728040587586557950396379706722016689476966438238935763550712723356072982718319505198321555455716407285492537804475099052828395778536109926883455123156105230138619241931750463430236920369781780158565059321377512208333536287349772854606102764803889268680061514356957209147117599918181773921991050140718831111828343933117694378910287231978497481139199769677757921547889525702609958860018706735499555423268426266405316708974093262635117781811008522519000407685208734704098164864192703937715955013916084584331124146833461091889829290861344952782144740380439698954313731635352960361959453127346608765841717265141671879226211254207558174610870519988116361003062805699839141427878316116386716374518853541113552973919153258465488965887439373866802409394487400249939113009980428081896335127649913476946105581786038003647817453551649670587253057925420060143253439057285422859725712949799445240386498656098750079291211126904219522180213518680682120791759186018189711780105982682513882026828505698131869343006966312859439932093941477069907470433388535173519775000246104549452865160871889780964873760713855443589738639047104745182110460137693822951119563156442692882842692621376090986816121592552378116416742666379393619470974270373750605909532193791994936284577972545395981906343795433109663664310688746710586873715024273189504813595106460376728203210519901338573019511672484123306073398987698078578432080304116037063942748081776397396666395369212664066602814025281134924066459332711778687891778812248421278466251613022373613305753363504999721424545926730987688744879384443371605773019465005764351576935282942434071965521397145732855782368307287028830674976095880006834473414039787384984952834898643269974977523439936081289878158712309650354890966914475013049259289587802735170291999535114859688225606116823758946505388717955635074585145385959509115643081317994170355232625993189139997482865712819291009447772276388710896251325138965159883212136174966378683930222562951492239055300595213216990856614122879944782847967342366883509914589322902018638267606918633838367063012105435575183321637260970109791525897661497821808077357862892267279282437611706118123265342408450416828740078753179449050736055995744267111682328954116376759021044501317517964472194425282525599843021176027937329102295499890774189252194510781752429616917342782681477962106421647836292834676678036419431191460487183931318695983917110696282601457533501535144961199369815624493217120149804301033604862690436877845869171927945961981490408661177572354406159322678018672683203072116245083329395201194865841904743755969056226850603279546977007113446753033189047587889653392498941327055909934089904773761245270970177493201051282906806376110825822870569607599952748206155579388466252083545356878272503740966009811811503393507479403180615911462861289957845158611575478353345991038284074076304705445809210475885010504061751167460993852410222050316459669376349266382215704524426682715833401477859779456232132865055621142683672660594917376, - 91234027501606659334261044918452437734266326048233331089919606356465264248704797981484134271896108818432090253969079139150249304647768511132108439782595075053871656687607615036806161226515543755475683959163400552196785433228885507822627446262442171571356235548084920899280642491476555637021274666236526050133230528450205244696960815568139361917184898082108133014622126353686531899969362297528543751123324434288693386913528110880878617619952917653003013922562992909252636224135732093772479084362881260423877163652635540339299441536238089574445024612818025200568578574014615413597899000941432570128413923125372114239158920301368709524262326589103860988273769664663140670434709575561161478469083225204969305193048706111333826605997510728266516895848135638887994861187036665095356924451409221199885093719363939000425329272029283872724409297488832599060267294653240011031498355540099234272057466687838207709605950513165382259789262523816165715042921867128181960296499903383032937287575534390541434443616927082380434102513588312265938209716290076193711507608633664071533711949744630124432375818748361062288641214379777554459448037697403619820618857361750131330661174174468526674194281377916635627072225344496361903314527463842759009576676675341621416558210473113762338370917858496189172332505975193932010734821540323367746115994754330839348758127205540119049305098162828358748372536975384754509696415326774465750593644226897993174167251298236067445874009133655162556448771490100262486171367071012666397850803285268646469720122206734931458724015228068202785557928956252040393063637552846564513748492023571923388675264724924113130326177661519536501540204452828592209819574084096794463230152728443495277966855626924035259597565370605604428677257869540656089411196896534281203481113357476003865890629993855161309981692744089219009481840946530148640325490728548278453781512294958677689727028754083538426336301104250124131337636145040958575392447540800817745998648771835828524659883788280450514173172225663977843504896216427935051740042677206678960596825341048534787307419204930065325665238776827088450162374901188909018181466524111083967006862440295992416744314643399356866814962062451191297880502964681218723733622763643431906023387462707305970803850649032374907566611441531455758278431972701200572747451501769515321505220603864054865145252752019966844912071383433293918536442095080672137822533162083471177236921426278840377457362992371288713620865254380905558570522605877832446559857203365206653993889873165488077373175417030002877343443718505184455775485895775000793399756468912407533831728375565159614689687305720301824710294408392949106347194978863373247208375430859137136316080096065909609647494236892825593178409069890193664402941706586389392356088676884043925400426280376520677769421947068743999237006803970536761428194244174574699046356533246166392589124344435386887792536770374274970491760459497396162819431659128266923154151008827376665292921776623844961228487062462163210991243566268540205703937851618500148024423361866899247269980827002849017228562966229116339996045390849262806865689421139965667499470596241985516878719085211068736577709236535326719872951939274523889835071946812469278456040156139538181372946786045586938324820423888187074985700150765857926443058428126984996886981588505537191441967999918432566691230277929969717529371902799152684492108672704377297682341399883168901956569375537597865669493189491061941342256341237929606483499174587347156896372012487842566098392509507043871819952934919013107430746978374472531892073161117897629044307638231424712030052179558756136470986147723360581678966266573628290837835554041866585258763518202736151312295384579849555673482247343801555016810426561671967237869309196232595029339721694486446635946297122608609725300748318404802349167562764244306514882087588212966667273539322389434948279289912679288360711970010950496920320269005512847290163976294622146844103146557555674290707008064454770742183213534284270998999928823949087278069186352393479053876738501542027135497230500653905800537369966660113195986713976388400010632164369799881425755298758206588457128734221582080546476482071808498461944719455641271842051487076569106833595020165297870062906294123702812687974264641509444105197038123201271673868585311715974296429096853502576780848472711817364611259794745238000622805900906934137770338035099731072716219774487766952744446760156058256750546313509453982911612327488481549798052902999109879462156078688065957867695688106695169898097187101988852316639989731474135446035370712378046964685734176683688888247779564800376993347672063817313822343126939239679534606219271806324831317796570197694107865332273757517327800589357612578229487836996591791864716880171893305779985166534621325882572890403139124582293621212294846864761128639574319123401712581601731564875295596457504492826589923617958556862499823590234114744642991297191284754865805923313719027616360240971050998245176307620297191668649516505976290932286025687519252348249453948704767222868535738992134994496587611637465200801142623955696960069729378880886495127958835523765875975448452877256446330825746191133638002982149350113725459302142572567316711576189451554736645436625492293880760775018034944702434937407759024428943968220060911832111526847656947491247495798903245192137751715243520208065398560686518957401486976441984217238166509712198738056627827691404121630131143860582662718630321569541972612558010965950251843992045830267553997642165989550806066079790789498735660345474072478836274149271595525238561104112455233830975465425490991448426798845026362211480535800024206715678229543316744527340658687080074663013877868637850006218286884789492309041929057043628969719849279600998494581627782396573476616137394859773951705275173477300941574418902805360118156529641092081762115098919734581591150224745691852444510653791744267002406153015846450058562347329521209475050631260455871336071823729387467633755730980841015523782900367123489559896664296186425164821333089377878181309708866550707043934948672214213105823019743094945811779419316837697499187693786418962673545271664304796092746317365337119874302917117551595174755053975574488707580939646935110190564888407870393305264307920757826118645409915287893770584999514370228979428220170962562235924029571057778907686650433370501045434286950489997154754437182678220578968167190731603909408894589114987564627126895463880683978997157779785465605258850055841589935899956103951124419651666478075937229652321638104687490523520357783263623506547321283506057173531372220347464404874051231068782001994787778569599708328502141074286073763968187945383714407213711605266563752677809126222181506906703975467030910411802211644615648544083911475505808329515923401314757365317192242979061406739641822686427547049383920289152111998828368787147963681031383784608503325342419700484727668646257478938207915674422439699010702998985687000981686820609596526270890828479410866221038341543067502418600082620987219646704016665609883237784198378652665343951261384804789760709154180048037287268171834205769249481966318720283956702676223641876298249229183992027090518916078980414448324105130421955722829082444401732414250480474771110177151959169941198884771747005537682528432370549120498452404496031949647250010224399333182467468465812011421320067420769560743998549554263066323204635317177393299513641566262437978564403604776765386762743022169328502034610301802069119471141835222421469814616034637698958182764721489578488538487559717586105704615561205698097295399981310615163175001443231854117872424410893846990694623997284251864491786669407378061792568998983812415592415558345683847040502315002725202282892199539162534693785005924445632205099572155112459615336088741793759737240160421388432790273365082981460651955782166296775259134759633795816149209763482624703547392928287966252316738934725147808512969485862053892589308022771934646631950255845687490924137300549551430676418015216211540817779127579695722743274366165875321972918541840521539058560458509661508161497426287920413679570203160390092432221927036498192857327143246789983475643434450619287360627323736304334989510935160667150746593299184517614241893695229394400527285890559338984825699824938388322528730503213367048969263241041656542356247162709436802264952943974282389691990994648749276956786494675001218366567065579786967310984490373274740316611228524833009641319629978760774627437840346667558619155614513301471981494566644650238614597738102620259096675138764376652009001371991092339201991930242387905972823820771354202408720274902011975207530452545600246335900486404710287303663833633177337127701009687684054982211251194840488090445996933301057056229055143170853582196619872054555335492758845161001226409223600562088733707127694659008154352236010937357499813189519348402088440665335263502653861017835145582375096620739223141011733813905148153109863161420390532957095336875332861202579992767872570838582516077771759472245189532245136309829914276414718409573615328729120527076162192822219207959648119864573574389890536457744621238123886480715786727595303767742761348476143141468564052544084287164618973427928830351727610507949619230709176012995717374468798813206500170629595976406244426970333196831015218057138744298105085234178114485735798045530995613672753137942127550799299051650087426963506122377653942113496585075226888264961574824405047900925175477635963484953417596251147129978674406416650010333313956057734914893047470770523573029783756386715933454249601886368194654212682047277345535435332349589410868955593711951684408357701752326204359022339244534775511964023561339858670688134128300482234205955527504072021323265871371788857718084123110541092304170910823454953416415754376507808084516592865281323003338031104, - 171086663860021119333993246664265690459427068272501863322620038590777398946858519166120808527038863040805311472938665832763798659823512157954748175976153960902110669330638255780280203499824275522066249803243635878607624927468902355265435221770859027130342953767724176046871224939876789217587856598118164879635834950014794115296476007359410547673240825388224589236272524780802877217229098878757169286842390272385183456709615722868411547649365491078505656569378182308647448219809350532098396490082345725042767853057668748631725673095331511596473624202280260185770104580738963864645560772439113304732571946018031957880562601985280514743190306782149319612584046050650372637102876907079095227115320891373325674963099687305325559037826363651215510963635321901903212632680226551019857278944568717625115021203787851600441228373817734934468411212925903766066852178405582022313076837163290609330340908492352295920199175872955443741251836282263480776487759079969346204186546347808332566808040799831205443699534860468248057839093224390439465719361205154716959637182824773169381895917439650214566869234715789667408052240841704821280431218356904663074565828733385918232925339659829590098982706993722597896138510518622063375725607864224041500342922756145678755281979461523074823011798096291027622518703557195526253145739734985265238532728320945336102857337952265677276760563110167705431876331930925537217116485032730409553630374116628821575250842511397304298204773381774376538443624074413507086781151236460083456149236956304690556877791513657959836815855243657350313174638592750959857990352910030353528359754899035807007548909875116606152080618500195978603322800525082596794447494035544960993953398129608464801459756428156806873059361992633556646400469768065836823179034947191879622355646975289398212660796790970104102165883994892037950164704681789913693583295069689900172539190137220716690015645116543424520109530893530400280814863922066359555320482899484135192786315703900810118125048930004908733132065721829777454272766030554128500006514152858374457191322823455649653086444739600642812555208470339076245228510239497015662416608165663816472688262947317688708555120631563458237125873724487380195974675683635332185999291555302456075513645064634776104648565936381641143287713619830636550855162661355994068230415132356993921389553492606967541669228181195599748294748652694084567184228155825682301582884437236882569442170965403277881716628720627366165953547017349114370868951340240399298486892406803298123227426798762477739657271589375050303881087163391435909250757048526236175066423390714775503146101976653926484956811188018092356699279573523545536803272851791169213962640243956278106686186416649351617461938657179625444576281373254493050599328754910530174086526674299867491468305961633979012492714621571708266947129692340022925467726879750514918103874226156465883608465424141338083383300792309547184339661807766614481052781244775634578300639876688046148093516832468737267163731045004352012709106125498718068824879619746618550347667603228660224115989835188763131094095319071129148494984582583140648317000249806034202310827077626104625017792728430592949788417042554767162927643457154132273059794466501731215341929912996415314212594291928142870870506743977447087073710401322738955467404950128861191806692693771326552214863066854936467766532298260720243473821150096833720224319381911556153291682611737078494607599272734802695197370285350340120273006596073121370156079369669047200191144427684183227502972478921186510605881446221015332869160653430822056607371893412376978701128876235819456041171040914570659992732253227154663442525410281879150646740524247114340428658038001338023736197165177975916685325169240554766478080163251253142067886181294224307788012562201196609546188330586448576208617611732651530216381791223482617512924413361671585859123946902593204105964597848813256917543869995461724540897496911970399707645874020892338888337340061570739403168997360754253016960937506527691099932515800997508949131728123216756070755643269577878321672557025658410001673699009969902823698670078864784457648333550698400538120468906568858684146374713734439225914677734663151094101954716700145054174375569494217843632877610340968316970404244125915045872875765027145926731571612817976850851346525027192529812090744580301204878936655182682999473858827343070908711184187642199822450229172195135828712572806680534143718510251920356072620294597337677084284865274164819812781061655769084042418192541747386360489281086249179812374546593011311616860347037492840326161847059458428791023649290208477884440805824789938290291425685378084259559058676777202478997397644629954580501029858826613522508595852122549618446298888732035835320586139548707283981551903070055365303465681406349611774302942403044761203159075821428163419486411877069483585813334154552694711363318178059364554449265128339470718921259699707199995411647169563213441403413468242428692350417747598487105958509664926979004806023297007549894581312342283626957229023121408906959282094980722678906255486874193262757124645106234130751131875766634201722849422444547701753362706828474407479719449878124600396143558701331207817863405466519623743315013064421305563558944055639217332714561154346987066122708923279906643631689866196386369745928672371168872129519965334537069006682517745418079568868280709158222633892275166926195665792152402395552979563356970227541431814783626389122739907867328745883259125321363169035916848973263028719997746934632648618167369087076586792068696733256435319159795296001868805921634129450367220827726824816739442245540723589194279256563911307866315157024033181265926648449347947294828096242251035168293464947589272091138164446153855046081868640885342697360390911647447904622882704995823961035316102033097265075549147307439654260232429791669174722470007386330324625032331495879147429007444889212303484635571900115149123827291985277348957270359231364846218122143519249715048104448610242477901253950488919420763799315037453112045107417679327237765487298903199129092816625761190596332145058351993859423626677820315143702608879775269909668658628824376639631703728082453985039202471106953265125556826627505944404873769577334517877206964518429747058994883066079557349195835799949661113141430965380288015833743113700310035788246238975792207678894081686824864137742445162871885075196158620564702471473079437595580532748188039171301746345804622817875426476889034114642981602810400451271277522456698503050214324266160820168040347659769425850066489513064367478110197580713534919321179573624133755030073212899013463468257786818357647936137464568331189685002685280934446074599556286655508528534524127944798915883252096623899702381053857016238160736335079135074625003695611617741807274923700401641157671441575207621003632605342818421704267905696028701287170776051058765501641274950848512620454436597165723248775648268593054432492594763052339140204776429129234499333407043846475817449491970124491108006315881746536635736801428458671119998254556676149833150100628888889866401019077330411704087081348808981932028743833485171289293188084374328022605940011691582302776112034178620673963196460975884536474840777221675767482667322910491845866191774304660012639138554356618481370000975377774938856567656875700272041066731271674626630838039870921979338189952912113305355476315768772190921702028067620999644076537924742074881053136353528500962276953365089917380432825108680358806444011253243960485337100856068314739290839004606554915687609744805505313890504794335510362829369088499636920343849359913322514499628974408201276172243130950222715342549919506953048938288259950112574360255148066973899880517410366957046794079960165955718898702407546287037050712687394362455106818851527901118428651338699826697774256634425702217235393810226484166699250376216523212699244844773653313830687374947064794971016308983970380297914182525102996741687811379672176104574093311173016615415670470966564965222353897441616351056319627105674498383299839796700072663819485327310618007148550544385431050902872624924452203961175921509954897827902957518908887163612181259855665279092630990902933586836713595649666246606712218693132255112025051664005576849358672655696707131043026928899267679003809233989504835956648498016218947561332435757131004393712244861091626862795441623635934003335412911647798446517393263717107301652160163167287695740032934325301308676824419999157907766364445135345231276019161164419978500727058391434787262623550161901539893230649338023395228940380746284444834316423836754279494911028068544306150852473436362817794022372976982772126686861945268762014506613332448596254816474680319729652112548351499186271991746630397846091859267099217032710265896335493359383576905398940411045656867814970011006807789751102009493139113890551613118921370457969798737130402183004094201619518398851582821304067286806537888969600676955871842595033548562957568847009628453830256513428862029778811811569938375374537984887783074438130650311637589830128242319415593264612838581593012766070669904972257795543548936113555983610781519142948929661112359310152301308483885547486695301679002472661205609590189213328400646183555779932426242182030467306138955340037822892964478846692201972887149236695377810117239528859563138831014251710616566808978642937849706428837632486332763143064046315150515802139700842858185233427146452488869964567032115013470432597215868729191308732325651956855351275451964361497830068839658957831304156772500356069282216487597075450010400607832153141777193181894867512236728505678055032929373631696586167545841992142334904511250184729993312939966747417120550165533551157636773495618035340010515696626647032710614180131399989849563870728609562618938115702639860117263133494141255680, - 288125126327013121087336877689314265817287887839821920568962386953159054754857875056302719087447230430345783482441463367940451798124837008454953663762553870102569381655277471007043496425345163321977132085945207983937269955626654368531276167194283000511251648745904242760625226523058400030795141874855158573387361917567262002890220852991991347016751939397943263610750521497619309835922773687318239702173693948421453099332975949588152687687815742193211372554932609225834867579974317816596298995948538948896372193415894970069169567168970265001481043492151787199309358464678824654552732856758381831538846983349824935620206528656215821490963095952175906289721382493796634155439317199736558797162532270100787164359399911501020286631589384557656562133102903423169268143102184906525020095786299979274954104789453695162498031597751989187115059670453844007123758603471023527437115463270363784648438555251242581259097291507353630107262976247460177738380397715908821632666354216269968165007042412632026103646303298788527401257307560721561236135792449528715600306746217333060588229050222484262975979792346638525071515049618740740521263128070029899483988256633291865568684589430395326062912362448563276308656969622528356709997304325852656151381292053529384287412562133683482048032290433239313299821180780215388395465435508767467327123068631360878341158524849686827565947608639487569840798345337557717880004586025350471074437428313101874988602377019163607928345539078139474523679890556168240432575284238530548048896143550317637928527530572588021622523308403432386060183675095591186556450650630379378441332491808228230744314298026069440273922315679026101965904078779788855814695879927300600418813759029373873911741189170162679753915734329490859743423017895096488037939339773339073547415393806707743428742498247689242192250441668859939595682806343505761925017917505386914360287237354909440045153107687858849315857756233532709557126232361569616457320313587279678687338308662082192680088401976764081461418064377179389840900809977976443460030588418311825420686497705182038109170672767542755943343832763518293816494546425716074341361857894043339146184003044267138118609595440077846614980021795789856333733404514761059654679772984787898999267486406146984782401379777328193866841699306047657183105974973592376903061062467087833638920971755041804269259829245241502383156558079563574922749085308656741355776105232433260156855547451684185755365389870860361210307260905189486840326911553100674477795806158934561586211817180042026520929172184316156618606792605606869917397999785604810239578514804266698840922045447261350116750765647525711580362990967231696390690107729208027282004042161335047240355802814796330116766613916414956529836424631102594434006697086738914091070310383247966545449196803239948589170609747868672640537181194610645074463281418367962322868032395101052352607082337755754138997657578916841262821915820788338365170871787810364761428283265953947581289236266903207721551715290192747716248313445933395834276029719178516297582321570351294612754911981132857303962711796472525613284353912921126198434158039542882625345320382773860963542460226506421884520304170783208211335450093381895381617874411537415214302494393252215491760337899735523009618510757371010445617502042718997776457600126435299002790715356182359934860374386680752599107090992340900581060701715757353219354629522669464054377417053572559383267324166997020009067037184285033161844030048102483250550674471527118298838671157937784309414647730015587505534025417830175285825778019824863096352170560520494031129101473538008176462000346420053499098253589834178236447849243521705843456320200450823892142530079886254493425437258800770251139948084308292242117756188164070936346579321896015334948524944608073308753651518473587389091825981242231922376509630199476188406676103647096141774933217114859113766752579343660709394267332842307773645366479011311890757712307461154187054863328228020284445985398934516192463865871147152976879100971568673357018423370867143048516444603787745609628112645243521980607395205789535556661817017626103061603724747951629174051529252860470525303495532419075975255564627572705244522958437266068815000305701634196696553818967986224793471370082984225914607462708253682514227871901511761345271399831494582950726763504530523730855098494275501153666385139039882449669756254058992346220830815107136746997039643092559287384054760954139890101563782026200901438831485142362332028846134066565833766013483207133247286551524805937907885796506354889131550705160214869085612832669427151689769905318306771074669212271029596225482951315933260178816112243654681897668546745249952792792001187716593256494678466296805728003343855287605944905670853901501467076779482876849860790454429217062406785323398879392799786940060114872845148606057996976225523851487473365460537441592477874622305871975793031590598375167998610800901492951840557249706000071183732690602709749151166680895455597810337310795263327379953957933449417827266160056409088248629273411209150418198624355803944754435815745488808261177929570078671422067551577066246015321651187812252392247689881481347774694684052234530422617039300790735901374847748119522176482194500300391409656781349824484238185822943840266857534163032760697573071863259857218952370402472141871663215912669345534532958202444522543893834180869517749755971857695950018407278089278800925090900928294842455765522824915503964708507077744704902031331403580204776001102776039188604144610195596904673501788142137141313057799458606569963305958541969189933738576073733752656761442396202742940387621829207375717919167837511548996357666239558784125235827559114620237863257252766562697736908894112917597412245180544614144376998085214059388532895369572226209537402685075553873386429408672197468280487135115420511799246761735469546958427663335034219859352639952363251395227741704279362961334082892849196404138651275831194613558606173633569656121226090564396004763043223583869880247235453960782278801828587052155508002582284549223763494570364524917786244798748053986081069574082186760042185773892522273128133737708112363874612021732167856851750585597514716283602745651567464868499511140449127601577235390506068093843383685236581773254910679961353488336123415133681271736586131196855908612613278771430289397979862363844243944071669257177267314954328857162274767869339108815275177253795464504855552542063188272145069885024750669259945259217634946246256501674074776546683122062372213642379192650067549779811229110196754800428722366215971022631678254887520166083004209883787673755802193724232291999605755977893607086297475672261724981369818503851939958750407408665625700364129580062926671259742122114849688958589451278407664769956207796341068628682848213490289965344936586823367991429894366170638756173434813549047122028353422488456735187298053676228479204869183408926549201016589610806516955191176869282743713519160964785595844896937918710371858899453542673057210408844782427212485759299635012022938465591841843649835117585254557643340414812743011999981981201301435482522478499521871563691453490703013207852027185764048998960589147901659668785798253741038842336273527500837962471150503909777770336937228511910730024314624406354223112914387394158678620946364328163122102049346171449902564795502265038686787741512764033521485799617021350503147081229988556320590945897054096906745114689705715942715376886658396741776997808081398106789201306330248413234560744345073485076489014945260908576178085697210209767181740807593133931300170559513671174855638827065729208050450916653347962282403914844895835702786079087465595203164932175622293169854736487104107605283956445780762742765960786977398884215082971021508194065385399058642183253104158350426073592395539255889499734050232729787583860255169529851479593903812358545262264678372063437415506271049201530590533797961690697142377272649242264218799214445202638651069653353145212286351423678442690245942058832663226912730119681248175586969035851467204874414579094758849710954611678909859674525188335330980901984273192634885130908206265072593788979125246814123494361920235446251378597221119242905501166773900082647918930271760904985402812161609336617511793489267281015417660042938307035468791892876052424168177680118727125419078218906762462184410757998522155287335017776140429588325408029580329244631672483524209967750221870927477358979560700052389558507156392544019282793245785913949049834742802353688954865993361799288879394918569583481156346742001614505879425683591902579916033581839029289722944540206258406906946113041285028447345208975102376020836542372057932788020341270177227083869554132747624253167395921335704224125892086237648605299018844918001203332066545649855111273643159467604049607216174010905723974927686438893563396124643375213016429793801000221641961350664558877314255733079696674824706701415108552665335322184430909792114470377555824598567865395980766407893658153237671076534434267580823186092348081958254162472003224719767098486594466674968953889851259327070662034755471022805191811815945655805117761555119195493729536204154679268278374653854455223754948510218746910752469133983581750528985170647737643676655132531803673218483369426068528391163717182224504059654840689784290845873552352839027409942340926608108406198415599514110542666156641296403749040836703603988864690438089494501993350073109199304968138775745747505914538038172554722745459639202580439559856718073886874535207914810477642873608723719057238264897955908307235525689439117810110422051606856632552572837700541286317396386024992534970311824026344957407161773815445660370337399926524235456366577870904641121578873403814813164615051261394633733808028825399148804707339718150733129045770240, - 437870005428640108830219891938994532178525675460744912204766888911185561213536762557821903607639652463595326890874886191931530405575069740767800101465623400003539369037869760892789765585220601491524306666771948897030441105922778383479310842543654009166446820161385710405041244036992630707153457938677322838108032224607681536414980677458108704709977781393703131716785203889393293293774820497002357124878845896492832515839778383673662201956815680184068688989941150600516279424155876022540910731966664042289145757711276006687207020833283885665900814124258590403739143288978891838608646722223978216030036244273479978358744726447621476441686356152606384147381154325586683245252381047477404912730575324751979656954453143857494568408809519370492781559989592331049975846755978124636713553635279887376091754156534461678355287663143348161036994134011671825863473857219349838559432295959247923565736474036373016962461493794467300005245908391416292412060927560710005831515169339022068554436446175470754797858879230651320975288523252438047966632505227518535818668629666623126461980639660615841703600456713470736531782057575893201802479316944436296475913296563614929525130649981018103009285671707071639279652476579887544100978080632654762120702004948817767356257202670077294926584390665563433657223139435419410192821219702597041141295885351349165248791743315700034491569834333611204136567180963804903875605275980253287094449029279532080888666074869625743888242813170545576144299280800412155314608436697014145893128071849803482702845415314434525904748350937832747972602003342383218888511515245675680901426790457600917860212746399885312389626260812359363201809866589637458953046393006870386876132678055687502654096611180205802860201125555695609190079298148822927626381792778207829472752811369615691909742889416971412603543210579106168111247158237625589389907950906491593404216165664995407976929184434641301747303737201468904735558968602521809706087759238031568746404671927473721348757238004238418314473684706027342757806849555755184620833950884190260506715454382882958677651018567900427874134921128574513803050187984525099339381596357871700495596429983679730759408979376614919626204796858014132788059130076960534092876140412433150270066733262981008773059818463657413073853855520761873606292822543473727964078451947383003357513053100523095627818430297296246302094567677561585100126903032642293571000766853471987603819680760760537872501797239237936295070261065631286053687994784611107283723326647751011742179770176807540342937726184732897917221628462910272019475646701707380186874974577247839947599248432327650152462720429142875687259651577372685284576364761894002672865092287515451531120309113204615452164432423710444081109332267078622265464823037740886194551129295076557403624090247849148403903369637105371758826550064568798396704119434530030396423572161135000808098362810846874886775148369726835606426904523418195827754308380511498642320111648754275686256873345978546899393818562809619372359926122815216148479934826517809454650122391735086557396732723809002253197207967745657518437307156428842429891517639627008477044457062824085189593058347117120887686708853529245795026613755438206443499284357196712869814796935993740205276744227763954500394383961630930731505985870523856576603597285145701513553206324391169739022668882474379438134706972699675076238862670407833585948196320127681607011117522548655219849135008379557420515929430777326197212944603697030314231865728203419086873279360048118387487995708720200189592589860369294668024943662906162712746762294807047992407927841243618719724786809847090414997110185547805642598969561685821669213008184915760784522013175516659444768215494357712797392310707381589275316030889924588164062729329815057562381659124737192719745529099091554944625545025479710704848289580334080207604152700104084750793574081254945914287537217021868722087306204714664281033833560569050926549490777237316665405750345519023668072108204859428292768112310618209493607769813428911768066727993562174877812385715425557445672452392676179400995301901589332874002350948123718930264183435124338550801633904420559948010108164303697410094913224876767716996493981727421783744270704859124497276018726273875387581781405862032064749707207291098311117577309813665289204111821166106615204934043810975260998092572395025422811718452078370366157440256507633804508303476346965748030124513613046513601669640164601087480313831792998597876602908445904199163188521378002425882288208445281264597362483970078825665485025111954105048976050860433093481059575929830742273027099885637491212675366011035886680652850969035883508622232538795199557248456079587751532945293590947128600057819405665037920233850317257266242502998530966597717739813656318469821063520797298240184632698034427353403907686166642575754546723091914251966666826442187449302651927059882219785612458900393871147207025550537855821423394903373036086569506307377342539787023728231854475792921644603716782215047078745406298240418228102236473000729910910137252438806353157428544024203925034498717824985400905079183248981462879027834740738497321988631566804169920829075742966747296885703326043697763452688547952613669769402849388849220175512255744607045506366389953180174705860650097803643025203403952638197304758059062990269446414394065912702371668133358423047155564875608049474604700821541185689077635329823526280306332601282264812361854964633897844406478550289607345700652165163592531381951537981444439725052195512246575949571010384201237367407063522892876417767787874368031426341765777642515183390459464502680699979511567556668436055191317810100775268392273901667705519976400872250857698715714757792475082007181265909924721624274538419818745599740406653638397575938073988375793126460239659173505560835618833486009157202585999012439906911485000562296226876365158179480908530605681084110950393564180242555705875505782626325067165411047562856172312965303834919236345681969134221307667214260938044099329671805708605697507379762067498635341258130812690389859359273445115473555765632759843377960203620177209703736559831118594870542293519143178968699262405983843719960643851046461886728642105217620282252380251849636096170911126693827964935458579539115022488645129152624668693482130495523605461061660960429508194008806784034019912900666904641612074058914956220422354368922584442086198179171192731427664376612263295067971294141658657009866918820750564619987493969608279012350902842228816661003959444590961847085201044008211347269560350407099124405079574623568538185557366634374722766207378785233648096327687606108070229528928732815355414831518642947785618412789861491554631073434273534506334407949878234799139878213650111288265770059806358736658983569350718427133958494477146535178067248057161903490517455841792178730963388078456322367100739310226442906033447946926373503908976380092537964935989523414145697355380100733859280739841596088953345579357941916925770003885791556694436730766772040607110170113170927417105965413482568469335541162321042117247683579571146051470352555517926066883184892009798177190068078417798236856746661982674091077919720181052172743739948032348811922579736551171236339749009151669777589656343498985370612729952325025989731664643310029460374649880134572259364161388013028405699741037305940000963492222591798525349761869548656187572605270562090053970852099605885096584366300131822453309033602836760434673111039129949447566678954949684666796829864658804759745587991131032040617877821622173757904169837954098732702801337149677390929302558872998897655006221029534716128951699230970047704871970056988218711424284022614071734417323179115864943433985019833163640199349747922636341343100173601075862095994882730061655998437970286878970237510736095557963203765481819201127864273599412222492848108092912075785890064562328565071550196674535320322804795294506143855749230862384901843057572836781042469066315843650427921210595360786821901667867699208632235311589015171351210333473310463858524059204468887172622391732841146428782868823390482123772132727276095590503886037354481481628020758073814509604191386013378073357016792776024083094171145812603866935471268622438642971003838086445204639492087138802752815231994904283905148463877124429713370570135537384768301350458706141277197429320646096981882070263101492118108953873960004002954881507616060234112280031074265666732182362027508513640835988840789683386757765590604130358884582454374412297002810968558918744655224448026785952989478232073941510196403235508352104666543862024116314271503952010959109608361117263343787569392950452143381201089042320458340294729778224506549835549499299444254067686592885624582352538907539498529490226578261918183862551296389633696326715670457666427455928509861741581541770088583704487182570435964253464805909683306895346325088672865163351861592142977431420881325413828499026672801833235137954848519677076494130057011412351948932819320829774136713531863606985863057553573148386931033691917260039580319091368407867230166077127108740967636919045443685597087925489282197256737685152714126212692944867829930724620117454778250985440029579748592936267293989924647743846417289959139253296128583508597348213838032172749492496692580952434877588330599926940391454708535144859311951078085363432922824573399877449920204765739082167792789544003680795646121384142098207742267821439067631630613999426886264329254740707622582053082928561852585343612939809755433615828183659158433506381719002702354033394101161921579993548307572457144374472347570526541245371899215562119351191061476463286642112912442965221343227982750605333601008988564956989304236222186326453948876433410840475316203177552357302368875515756791036541738908087484416, - 603015786786475930839917943855520967178413401685863570225789233853425063577667241601934042153103350503887649520959812955625084380946314853875660934820740083445251506357597783691120504718558761194171676455394827862607098443185076763317513603359536806165034438176588518367564640148649804470560091947459864738244852197923240587884160531044966573600781765169012944468440919636993890949007692881804874238837890718983367440320047368038372487589099790378597742499905981306887765440248036819384835144588180354195034541103338329023625491726180026172611600962498551576966253418269804326848072185237094909288102726884732349858460118439212143807414684091556190964083879624768552137642563348104348418949946847729364864377571216280269089843251064242290576930736295278892586465747364237422077673706523493619404813099809013276072601022496680986519432190381022548787130392416026052654950243910287015829446097021208281790281579475106541316364719121138299525368708490123702926315485784309969484395400481774574009817459619154152936769323215354555220818394506398284934521154146182102365074366046174753525074220348858101379891481398973746640210957376668676559033340790335074028547634688104486497262339932975261765367576366382630603028421319903188448671194587290140960411243614242863022950063827422471118858944536909316048801370334802955063325711516177248837747738943862249478706328625720639952855820127208142783060904050786341695889167559859961254271197087993129140421681266588573163856912575874632583635796438494167024866292993045915683037564246337126403567281495239711254294970864087734967849455255409826469989942053959854258924634342240507480397785884943965134677202307460941486059804872807073982399469711860416682764085774719666118722232004450988570693975895913766518105578704451111626418014727126554139946029144798972703838787074755527528750338936893777175276206826464433238839940053879314048472471114034379000235677143034673293499818005357677194179305983913348860725610130111960010262613735897054431372268233463097119161049137540131972948710265631750588230659685920665436957536252176616045348898296057969054658083685817673347278738762290388188290015949525690463530808772164219800534541238804724723552614123011358187390111253743473462684285261456225226856837761991906459848152247755061956327513342301303714626250279370739492581776775689849621113730242743956219563039101725409568651669600383662202124029346033244402210820133599806215928220983091803297747048054348762092656612960918375211187817225896901778496452803932354127892199724902086204104387473920937812721827635247130472531210039680421270858946135523958524621652234397575649642222691434361685588137997767939086567970942437237642752550827211342516885554006105725043295545245860211425331908087167966336103648766798972726404691915758069860178048397937858140789486110926959979012176105280504877170430486575808015418441045430571367168010466454049756148979157219000728215679244530561920587244732667418747901958427003487494218365490114103601644386481657501091285226803591114008551553897657289548539541286947818573867610037706751433346039705828373768706620857410697377973095403118059104354336231235665303356402343194955923793649867031151729121772468297108988720778170466110327225095153784386742967102453587148642572400405506970602458251773196417199796875601241330500397415724575197334102242050550226368519351420591045152205923214219497708781463809139203891916304599296241154889812087818643892458081449584169279635618448795792805983334836721293730761540012824495934687171416644392279289473590666133735395152647560476516844929659283556116238990503424129951046534953467822888667347771478734376582196210406909557402342401911989857285121816217884725993744816317566619381213449852153847815861091378305133214332956596817657578163373603842918370865165863372290783562844043332900620820235660701456404507017185562627894850970036041781768849037183817969819982785721214685138879443204172292757904550018905257298329422968314411020308450684897849935185415479839585195753789027324355601575055389738638472287451178560751508961334083814143805926347752267895138404669213751242835419920789154033064435482166934025382348921703931207188096265141803277263709112195084104030493443801241838696535238516673384758922810084279453063879282456488762031583321535622503370499314676411422147084396549547896413848029518521388755053682276163824345356839722316481429777810247287729461519031397048659693735033776264859456669378038465573110783427908163386893594673308242054715325467109980190688065597097941573321527222866094540405072728036620656539755524979101438957751040718253936129662009794416987891025385301950605813340389371800196453866569453109561037818713050543924224768972062602839910021492093175049759806448115344561697525405838574898325002915738003999907257417536448132379242770068686250924430312930539962200900573394337760104242442687109179667900476232989341124077129247753779742537117837838707515717860499338992758663516841802876909504685390578895479661935967810659184878728814063171136560305362773490818865333202798785676013994920437231691985040731515288757455789063317391572600913160241366922734325898276500285383078184749707230952240274488433446242890796119784385849020464162391037480904980403750081152831225699315194386401722142544980893515038348095232517583804834835889504929458450145454962005951985124897510083747270304352127197357209870649006844686394955221135603720558733485094386323006812097217203914421996251960646356900901113233645966653287047253635117368807722089299459607718742514347702409914462261095490284276199300980148124063731889440103651908502212344325862930589285954300283836008062058795547440904784802829433514584723892549548372317910014107797490520085544726270668538543826075515598793918860934811219487741210340931019434305381897190417472090320963318550848831699754071866715213698929134803965905559568967612046118190909102289317735657582838141305402470369972487791025243026942352778555448730199016225373626628549391755974825114350605171310598317069593916421286758562013812867836172651185405650159911495387406239151164276646841362087453116331614433555721047858558072124389821336733324633397501301606912678995750208041223704257565497698783871907431201466728037033901449737229624739895582374604089979036500855014692140010505038486280797371756464989932111267038712050123505651432851330146912335879211774131191964042568203916280381250446761550460964194333093218570463942643117369648217554604228571212594232088097770965489196555080644337738475885117792324569075245807874846407403532595482308569362738322685675396523265696906311641502345716071362437429141832624025164941989316412177166463152493640550902557215211237517304681127206006651302875453672391450270384754994621510579905121698556836380432572517411660306878191886049774279305165349725625897801864924653666232219554603372297108996283680149343730964605453198249636185111724858185029265534730430663377941570904986765344072579032236535347818900785328194343248002840785895586916509146510693127963827023678941971719686039843318166914824538382083066382009454356401523544303018897876068132371408983925547030581747140003785607880220568800647702306307821248591223372763979972282163327112768077723131496326028426521975375230083280926780905504852841107811880213751569622653597856271320343569171284329884834967283721855675608237511792015511234271639133634186223816834709101659257304828692231869571099932296098938355319451380790660664610880577382468636236488687775721297493411800280180799384771409971107339681725408840296318156748924502888461703544773746248972776347116539851924713587754164435567203707115170325886512949715792741997704059381316552969607795232889746557171834524329363524162909021808870133566935842630928623512450889365819929695503689006321150423750078488926650875763688831198643737630963403548853802957123818857505712678003999579525684386441907625952670753538628910956220174611873931833268219325591295751347777846905461412997304162313723848450667842053942485434308021161024053188730826281117381870543162742606712834942347251242245311308508073335022906548486492493140135676613402121136962163090856459478235195584163456298600226695257121671703402111462708204802996709405693992992554805345901683956763520081767406338181002558814981797260667650527983053541708845303712946029353155935194332688811675641849756041528171786846215205316540138263987084372685194636135865047746438762116692343864965587766694249855761104899362538946262689071662054672259608823626459188899725404524552292074359667459335483414622638838994083422025547140581992265723890660802945577057346106463404329941339791600419975414169353402136526378813663872793380399976882902941595307828565126447310012022892447708563369223150134771758987772061314178689204296172933004439059279344330179476295959825916371448628242145003648042603959851426508115709884818782306574464036136875663179824032291878221325485530860528912073320414914567064675998246974985383573555003269073789619052423882721839220420374104863972156544286507723916319318570414444851846169013690731352753856059325271286799718608602304344415219780495928136557576505968658765723153225572347068403662791783571219722647400869343310163321994720050989235907924352663912976520007767576540291090366420013512308850024194857522624728374014085681075622485374323812261971851965629205486915179741653241137806033565983652444416317910213128039819272678471142224322424249761905493466602516134900775216941057881031913364916311877710576815966758435935442802001434551362032612659032466270235489128252430027555352906590930759468449776134269058904134394438856720649040993119958446281158434974246029990430606719710007873633546457426427904, - 755320947743241143492337319722956541657147272490194745636795633519899946441853616284412635917484299190892724911352402136520536236212683869500503696333701690366677374206520080230764499111237621707549607034890911976713399905398106592526193388044441638941216525111240226442834725983592437382306127516168715161361088489086727817291179874105426206420059513595207106294821724960980020230203055386078991516441911064681838760700835377333751689206708279499710288126952754519199705101432631390750011904359485304612036851722981359069404666898383041998907667040677109461588928626341928420557790489120757075534147185168777528245738242543012249164195771600424207929395813733042712524742494482079881791636849246899332400428064858361376498426251693941350980736991325387537789044979827139764867864116040318384696319582568815556580701801574039767285299098927027342549679648775362510884293679110697770011439940692673236566235781753926755204287528504159114391685289598114243403350300012506222463030646186186483300185245919985752503834413257971526656224198237057183953423102154032634804090513559740689357257808978869055007326036896559915265035977808773697162933724263137371201947677767097129815962995901852043390618954239648745503224524958102725206106415812156343453115557588381827404381579102042577957665170896085790227143125429531865079137239923606069293991425906077705288747947880117813134315302795407306140054190139806307460018157741555378454822852266980842200111998521214555495237680159178141183115735359133226579186290151207899610568435085353039654310335574576622932475111594540500525336745617309404519911302826298990479525909503683273996719585531826111716545555044880198157805136846042281088666785957692829078379298490794959376638687765843793066193795155231470121882599539647429357685427652298235898122845323966533468287753079513264400463089067844218076133207184516078501476725005356710508262886278448525415598574028144533587375758340764499879086020460445469724881495224870889099547954526983691736038340931425199172646972158647043303357883924880484410626750281191307797182141925672140178572469655651672858282501918855469400550014257534180434801815329370307956213003139233040595310736541149866565950483714150114298644881991153995646327495505573987141318042104957872145114668756542614569228368051660762157899035304447464156496522889419543458998598641796505878376295386378963198091008664834262969165735277479598307187384616330036966069972096482801804967173344620661616058126401339610873296174576083199376749860267959357588307004223311368523601293015346319019327433341363033633356377185092516536074449633827526444672677786749106161220232039198740985034000062194616408428744864385708382759450615529567003173806850112298907823849639829571540475470825327373975614351406016459962119512636012066516852012662927121603617064039820901551838582632979181855477860243249327286654926053928820768517020292922835391755457763262344029393077531983891283805406785066926062181863505439738353422775827442957882736490757507630794639099784749871813783702307745171091578935097944149715241666783722235059282475975384446308995981491194075363108616638507937818056808848849171209694418286561898398514320767256556323229040026884856906429446019003247958681798707549775017064913398195432282206747001515204365362489063923094497991918013001414942238097096828495149206542864706895140366826494618256782001968722576040403988672412915558853379421383786188316378366990472810512253907147061259502595691152434745739832479005859863070686404176025518380699496847149550797403551389225096139272348064836753220102793426192727595129763644479286927230457433222841414463242919530264798396132926776495533487517353678111944085085149425561716382888114604263513647899380314123375169857603019652286142292595181920828128796027461052456103521589623051485298837432235398423507902770604357072109319092547975470711586053853548127002161244930624203166846325065254170453326919706241754466918474754580536012172044064718767583764594054754030889940510154346078968201528060314021114336809825970172948833762645911193062449177720683483923873519010648067537620137460638003301217373058690279944896079107359881133982341216929784432856086325793324831284756073366135368254830378857992461591143316038901818370502570887714924317428332321661380953627216949432177509210981943717451145228451695657818846752590549966907735194020914358673820271991861891354552460106313321591718839605326824111679181415039091011898755021876122409032282751321955735843128315896520198305815607237191488836949613757057266660679747729343299193000280785861607165848275180532398019717025935762831075390815707669793723194271330073581978819677159867456199637272313683812235690347671870541019075662210248471145806436354679546821824484471525134035407215201991525717252130930565411745731001198375921021925130633873057546035249449795168134904190011007240628988642152674002699726398966766545245162802225216609373916620463386961525551242839084691689728667252975651008837516689216956731932876784491713802444195053292904907300259762656397414937625868531409788898264215488034360102252658057693614862564002155156305976412528017481385979866553668579986043731527767255545528819485981594553999813995126676650589055754682736553382284366622793939265218759273715185901181200087287390522776596210928915009845017848439145249134828278778359617371650689221746781537957094965831161747490044140593482287367928198819391102219086910306612466016746413842698671844225472220327817332729106351366712575985927073767421704090067092040470213746711639800468359210845469491176811915360657543156820588151840496772794178310419369141541043533378002062180932069935776109320704576149228475157790727731149355298829191522792042283161261194853849105901299121587965049668551810572582112396710211878792646642149157972324218809307683841224293302370469972891407664639315967420543486045955989365103828404450104785543920062957578605756798187678619305314258184447067343073167135899603231796205494517560390369880287037790062769359368488544061773891090130955916308323074888992024001455969700108269557683778130994104943384537664726396021183070376976938073332333117610209239004591138686748736637313899267534765760423253727010783074095815988882644956689202643839825105440161054752195921749878135625359032646554474309976992082115662750458424726441783142425272182660348497143358327764616764898481485597592039689916601353873074554213710894255634407129638672182849154239573014996699214501077869879231621096570857017927532849443770736787160038366976387198199160158062320572115128522274765728671588900108963078506220765004926534523725682267620940914578672411325358462091480719296321171633501124319664790887457889102537642074906723931998377302650866985066728654642939145581012664108077072712531443562254659421502258874929137951155806148108297554825483378317298767273582699867588601891000624795778848121144958843781817166833359661605394869403313300448351994806599344167086682183228719397612035986966048149455178589604004017051377061500105267294951619556871890125934105501162204997061267955703026166210500155517399572738460264190756258974770373850627994302620859026372067618063625990147631409177303147559336429690151264240000117257007483228358309731855871803371468666332437943101197338697015197813453579168979779984321457626862560389599445735045640870649982864015415387848518159758280189414521894477516281342200450750929939571543900797325793702156842682522904580747726618694658341826508061789225012404681853428292808838091477687036727285218461054195474057860495616833855080453577397340148466648912596735050884204835306572354441317211979222813059864526350627656648135393122961866512583146931889520880958980474162302869613955552145794235034956158904003888760846746645626165013770558863533828831022979979829251342633619803480544923667005634125553387088402355992473120687137384878343762867444179210674804196432002668740137910240051276101667721829271707203671435846051709833562314837745375968980830171059659850323028294766831235742877284219384402377532684296105764172287384771624021228709258866404182149779844198437279149415988297569099012862055529623018137864651696184076782511756424497588209563461554447532879066727345975240555306331175215228381860830764829823800139140789125185568506546251368980882478489922301015910885720960819737837335358649219891853916270764296331765330813385249926325063508422137785112878001763976342418334720114646855590950547763714367983281072324121969031945237497839993910339978017703007414184815128169810273222050584595788658638740108196530316164513188962917773649363250002542591624647489786024547283713568140081846711773604746797007117927080547938055230466768675005779584865955953883387571468675108354517257566712134100288432672254742404278755558180362333780634151807814116240490290069506350926319516212605830644862042648930617376736798723564431566857591292570168921115834058355010961278035123210931089820189788465849133825325515187422718046075532019499085830841167529624945359391298297420870452627151535103140874559787792114804310209198169177122140471415245753475020688478413618400638257256117629312771932330157555508688147474362190849367891472024616531575613340206448815217814431904413027664771033516295115307438366212998820866197974325609305118863176635182830318660098757446212954879020147815628749233935866017554755863164382831636437657986506594249854465574057008753579774425097998633119670421147133681281887030326615115671508003021247658881008098128446150394345730104494386656499223139924399283725941578866172435933741815551571267339866543864914890150719337571705255170931642141068011070786209921607955594761329494496895293148471754752, - 863323970866565227318401268316924126465444601737446529706132708563196216757302990733784485784985701722824495082147073236524845782925385351130731123734916364886745670100372571469033558419751152837497126212561863183126737983061943621148963832290040120680575902367476444161522711338829528127468658235570332786971247748367037555553134354836933342240842799210066860946761625255038318031349759139771445134830006564697116526399674423675817607193281191707769060000253315050405558828961520554925042826650186250487709458428782557023048993905497047533314060325345961417419502425730478942034247245551049150560379139962431327312818898288167718029604544369288908117425757426223922434855141390911627717741581282297087163260736603250511409107903341144451913505955378921729218043637149492159043460486106356983061541900250081763562370185814895369305053175765407913262990846907603331887468475963701158516542675697839992402209760280949259891014106015860626298919012047804678088950756269473836871521568073281045906366984337580788763239698313260572956752643364648668790910781764892509167151574570646909509642972749307708698157749779855881713384057233494696624980827226295200910595062694907853252025852554620525052790887720180848147379387126456588483852073685143538306165691035851976213267067625934295111836267246732707307731715261131756029162311491919998745631877842151853353484396756921790228703116317151707369731517013932284170378663719635893372575272650524491988230988235723437248703487086249029618283606563161278308192647802489120982534189737621707355906419854877456452299769237985710310055388974625383229006031004318588657340934952839203275730317876333915396249438080885875750141970964503965260653774219001034437144502921929863967306820938614315901826793353512840269382886264800071762828507717352589563970268412382384724329661223049379240102297725415996830087073974620771600408489595078805811165763734849983072752153363791590853850138393158535899575425659125454088459629772057528564853084899841486339450465297589847766186441052401016098968795929323426647306873702434837610860572414526113933808583206665105953617069411330909274442183405412037119348724018361667177684691205092943118818489023189759426422644711408597069050297922621981978159994590499124100240424738533408271699367711575680800533953714917848663955453418694491127755854480386584424640312185229630685888758781314332221078141772707739242342633376149257859314953447625444493364856591793313694977101582618769431701673181500265280878596853323420796495304605668701725523408667465833245614851049807479463059984344571918844425237282704353490132589612630356729363127690426773737873058107178721160886269744775610420777819681366856981470709645171312891473685950261814357467866535471223649560900874540762443401711139923984604053958812003480971578608366718055672992661754890566620429680947619055448820745707158665214966408186100153795455286932575186951232322481175826411093879817088957876699872990108023273319186722460646837006463829265461654557351142659042350320222548544704181774922684943085920173379192373837869883194762383589856193110321055605941431020459548968799544445431627365192512041836579645315903410556965581123331382718370827725344179079502243971923264798016629468962095476356259788712075944237737019884078283324248187364352891783302325568342084391583185966608515978024457340714835504350363144974730636736057912663285217984611670249383269606621683753214901448286571448379115513913821080573068149796658257972210182303176921558072342955893352753547838296681489448666340406171853549032340579213103900301074420525106772100654457430275547654921565317166226502826382798469840800552831253015483132970142154640382132164793894240856917089982901981176040451447168326174746378966850997459122307959246119294806380655904789286294387886353869724250575634450916099911481645048988035337607546314510791987311337235312153120019149687919613665957776460403678673656046931619177068698099838042396527386659061018606885173647695966917285100583008010583751420682614923541608253603219404330029287070275841760520889904581156755833604272122063324847197333082419032453491544322340188520441848298026285406944778516177834569809410207467712527489069410222216993672959957147105690232501598169736832513192695479918156442595043233269189789434704731339894081962359584737479089876622357218948705128897670794989277189037715127485594146014969469260538241925052046269880899895724371580294481244863508899011905643545657920892942349066812876256989714247810287193256957286200644648182850869642781054334633623142686216607981924417351602033682599660428395907297544171245716242824128937719546954360893948023905781589478581836061040927050042954925721179119280019842593443877719393973369182874984639634222477820377199199706381572280748900554153697071448803205957445855690191987847034956130325394346180499399213929656875869748801062475852016059715141162330764774972418787534980350174679159268990135051037950309778699932399196843715738208705955794757248963434122183496365848356306110727238625587450969664197116743799500506313334593593254569543747324374083425936610837816414929492886256338413200714827789018701242758765614035329784991700589960865608229532445799756879766344617604371995527170224071407112123182684963930654419030015970348962470797724837446161898020838676132404615556977525005952705583404430509667737930724943953165925418507378274420322013209545628031330591177560423549109093438395795154913877111788644940144454519413379623394540499712891643188342315862145039632345895747890678165835053580578195273444254346526218583921091899655002316102929828452003752261077969943459676361200473164501734438902040268958732559923557447839461292365073532792926149585197989041806212842082218647704440633556561367683474347326839568551873139783732695769365040605470936076239693752735398933570555167899844697311447539236184895613275328159925794078918142739099169353525188010759977654742913236810526153506061351730528577437290346451902963965926109647532384032525700763575282248951280073836709346874005618095912840990787163689122516200288298985268722309896374768359175219964318255128884752253940501732633864721034589606233876342909484376537450272322525739540118890985528701038578397615375382236686591099308048097968881262753558488042583182316351885540514625280884600339125490187852196679314283012586328032824363093465423255208012911558599441900505159871685320883778609120169341384918116074735627530039664031324817140638393606959079987486820159446901023416679277422828872203642855917156356884715094889682031862762564197011774271409941222773798991000094758842343629170593211411936215867828918961582892255584275448629290305300370098735618988716820818949418600281298094405235193547653902767757728373074904931670146929974286666662134584711723782104782847344667007001478538308933181160490091958025133313970522752885393034926033138792844038626417553980285689117344530459057485266349558474778142357809995273552566688599306613105909891982747799095846242494126042311883906781014802916305090433631178243230840379458520084287837207881751507232529893711797325401822331858683583694243520232528493777996120275992753216822524707664753087586639129016593691706422261307877001461465848472578759988646574944356772498472508418408260446290045079052802033749362097977624986114369674301535495972699601584220683265119339561916997629521713631989509123342674706092607458145831173858581711531558795886060847530733916501362076703264306632336647440239803057259297179720546759313046375395506087357636087608350369627417872005422048786745184045091453599993280713714513038240032987001179659645505530496461504264159796574343147989642833354910674051438073718475032485390407806666652459796290376850731810409283769813765756959276822255453400298224695789840699995759851027710846450744140113366514631611372823085105149430556348071437732460973901018830312674978654870368947147400542234677734081550599745627003878933734607082221111655015128302321370240336858510771119401186191476061412405931048934226991648848352811790642680501132079493753145267089570948449152118861603079647665465476711021582976617139787501315953526679267061911076063786406216184784262787382224033384361671359532486359057303900282939434985726550918737942915512166378230937878202646939805395797085233519227234006249488581006584727479407979614814376497649295246370153503949979815348950952267248988188019813871589330049162222886157190174646856258555665797824652635249660359519893416937775525839924062967309702342448183733570614456522997670269901528144502524967910107513362636324749649089477670492849996676601955110869692817773620944411969316380545365897404641453746487855056604295361499236323173458281731841825549754115774420111270264548468461750810371805312284992565672251320610474435166980092958491501498258790968199741982328825332865061944724894373568015921889604054619307290076530527204148792668853748516202926197254976650371740927209397514795783260642418726824883978844912442249488357044984889847989723823594134236117915593108300231279482054416827475311715582113924295759584323832336933982049002433207886051135762367683040937880200336872557248369463860086091996079268435850282718489046312120575885163463999499643844770967028430401909646848272335188843901705186210232429695898153898803684382167440222148329305039687128092759595741047122233043912839704123594797259381966052980281053276014543328131727132227069981509790833455131542182094367784066711843365206055536254435962276132687814965953100276173821947141882608972618822761630739780391711594474895928288805605555658093493495258151037198499780787275108911761080306666651326137463206611242713088, - 903082097200523597357604904643101082530803039649592038090201442007772350569947556678479707407932008675273676486579363858095263543077234992114846525766682849723942950318163728829232416849391929966177046753272984994269502260052053041672207356571792488461013681774848113979663785999352528305539167429711838249301313493426987428506440498861056351244856010977278226195366439853433749254650374065056069690420467318500411059699647856539424944887075725436214687055510195284646297285872603146124944011611390362593834204610802179392378712133048694570463451937043274603802161919869810957159181524872814214411212053734989784541830474536272292786256194793058710042478817910519173036350492422309252256295771921865307004419253571351492932674540450607859509573760186613690654121424290364697951732759350085632042468903454010466045714011335282109495797492460169594910919357986194730091340521142506281343103976435775404046778071402977678515137555691922976797668973807388185396576978831528537671900108758760249864168231303412861177755852356116642376813366243130887994441150942929013112886269096348862260165848356076766669902345313551420600544864033835431933312991312183130115130706240740261150989918636008820311391707708590454485237647067849027432633411541317540369042113626018261120791553231766508135201642578469951846027142734102201026806932683142225275064367921225479232337555050487043434051670970072644756567102254924472464436157826694281376751045997279274243979954641511814022647070519569765362468480550377737189066832450106613653933871370936184332766448370520257549368440284861049764539370768194847830842706631178679698935141821529177722337272527722557995987136609460361770883157236790346959882652491918875497990127131202782429286914863311522780943812047955481662578607307873941327803937135112254087120620479678799501118360839590776515144810389970966978583601110199524768073324715772090849213755966556874414393650602088849223581641787644603894027549227480966133507164861535916764652866802950393753648028705686250273205305967174636995918149548235614638078189663804562545694381204555596769556333055247982240251634938208379997694066567665733156124242803994278170341845663130871611647639785204716387848888486526564670632172915939081125451238872436737190404168958858743842352841194787043310544794873140134036126968068120927548858642014348924769701432890817013112981462554489063664114824482694506550886439168078953701534086476289443554309671101681621256690213510830021356504043995601856827762475194212910557786844306988807229807543107063866374234377457671297972876561393712420378147786839089238628494809395025389911883871487950785310911953552138854918313029610868924471445714733198359120168793906850787496303511427441547718942635154612540957774864787049710521912216410992654376919516339126845089843728567348227703430704371737149244455540708493972896246932172423540311176505203072572660936557909995308355942487103732848187766604801832770236778203121038867168051308723975109373444075381156309213931306133390190269979650664367963304668141227856032725753835935735470416958077998739342405106264328674446350540529872260460451603979606534160204220571770844442137695889116598611287829811887120907495840906736148152769817270698129440844820807343504441607423828399493351214113556769387737693384180599843453492786867272544175091500832850892304164663533997958028852391922402242488960505372936447130714035349591993553528996047203426605530219428029354816084692596393048690099021780725912413078481697949571456344046704011417078119738353380399944398568242781849217598457027724643087332864461817238692066364625156036134652770114381709307469785193040132279132451513899501211265134754089458720339519430673494814810813377728909593241242558318615842400008599178002416382686782061032167036820526669164009770072108796546654475517504608177528014728171033571489454699680469178064044143788781827594077145780318966912894790998471134432248636538868759935514331289764132598400584765602466647862664152416106196282630880108992833862889068735612403711564561480519300933769864311607553140765250377143828926011863474472304021235626281961319327873240798591395543578237944047264028522871152659399585487312998697349832414507648311382242837123792628217579570139195912610221339997381599323244512201067659099133220129644525922675105433926172564903745843529784023084892635601182640018246323661565608759527476938473199436129423491198368704081564034380042756312382080933804573413676822424987731721168008589371578051299823992402629542931398002466064226999825608103608802978478059746143486371336288351540916772583181462113457212294274212787801058874722384708663471184152419065412935337995900911875155611646704399109350382835282030552298550104049274536789763509629612371462188376450191918773344946384762433523995171883924188007250041853798204318936648662796976882530630970847082758533936104194220644595612828928106335158413686635737121796064163674700979884523409303448428910145967810794362559380304925232719601592914131587035664464474228017069524849358354384314428860583606300991625225577097119714316663287082977813531958365460337553862678049496462434832352636898530852408814745960798029243461317345466595445044964098393762110911859331622725085124073168827163436329936552382040616210282533556876055763526102255358563758562181786668307906357878119851842111676479342533802846527691412748212739997144282972312596239960673930826369941559224228350285836601002593609482019605203094275231190911916582195849069391226447971986493137932577073724558376910818071197901281287784372624417318001771336898627797865042177582487170624484757085485961575028937963633710159758299232565574666148338057328285213888892193399519463990997192716556151327942641743946795089097093349736082921697891409221917661191757809348823625549754282887282675082332027826415583053726355234113446423134220567180445385968640427034296933727257886717255995276412535470211414506230591037993268777584359558924749048615638817720703757529049493393619622898074099410052457101613129796827754817561192316798639454865720900376620802086264520910452708617679794876903617122828080233179027780919208624894628118525136795305897578341460007533953714182106723824214554496767503617469098984508875747436603892577319687698680459119875219805082645791550345603110880062516259703745526316351725099885443480508457801555130234881845710239397751142759629454922253500425099033978733043677191093675664163699974840122457874684848742967469308075398364402266249344250693163186491699906457104504375352607078882984481877744622195470980217511223169229606127660479002925401773400883912463891604554359207479894073489070057395057040108614313393407266013797509266152449201996921078134906899394541461453523165328681458213781693895163921445407077677443165402198494471047941679044083224805570560895413939232175168334665954217662046439933282787671201299483325869211961521826823594975969495544077865291759503880661631076341179971822081113210803307056112900329252529103440996327149669831302962301986991679220268444415385799732926708330053908982147028604133916662528235894488835145268255257609210192980963989416629365814093725159401115914444035557696170398445678634864943737118132116905534932511662814703016084342001580153469980041220818059954699940369167942742578471819612672268063098870214657490715563944758112564576916636997402522893097098147989517946696428494015693642867055378495796434627848359319702775999394685619527470576524609336898220891915151009460634938770669049297352015553906446019288936985623578386806790050133679618032292770268299773718828121252217362896677647205393553833608567327366047400939070756184812209745578480940327688051188778356307520965506231548157168109702514194370962670276049646725436556087981916363726471447695092413494880395095169075715498764090867752452790184930054066848007339430774240526080416801741029376749247991020441924079845748229650316833741121511337120221528422005582106555017547297423738108997026907137064571910001089177924722504209458030961660323965821964891669545795838061993622572568404586924209026104945249372187214533197096421564880133510527120842280682328278325412055571955592782502663221321488544668648984098433584804355007866011466361912716684847588907420251695847093292155898148764421051465522305478340731439759865661948517719199699651290810707664385808188824699044167639736968754347343644059484537994623065856124016162256748159262115850360355361124875211961083228379639734488352709140574914799072462440351435817373763636029504442481148741281889375323286556208183671207342255365797381790776183640454235887138403921416544157550697270089776064392541527237069923610960339458306851052994215076369973595420067911944504617676218001186217339445775557978609029708014741998079344584862223834106188304177677265736903806387679451925752806262408907762557553572798960974229690928449450965096007357217103161221610441621134123737214048868725534176458492072583462887521566356642351818650763898947647702897305976303485681132092315501904002204994055612016557765249080320985326940585059520892272364328185556262934651953578255413606370734376675612304575912169393495146932896655579273966925835475114465079467539157388318832936586258755968727106742478796786758874090964094834022993161884300623086220407757811425277703160546318416020847899091645531439255683201981538232663488533234462061922651365180409288178159591367872036426185264389565867384945486914331719388585666007650054735587693679657440571306132356958351850389181755130843628870726405760109605776754364205861145651317707652804384113100949011642319901176073228932262386834918188835580058877820928, - 866842280899944761413216996152994572129741502392009993807623321229699875326216263856188659991952667508630497070210414060554303545635976298176627870786810598703349308792951925259909055961935622782715632490569867708708741141517912913244555436524204027513662073653752219470896535591011404073248882230969294534061398422696690154016604078981618304977627861392245910223263959971354696652510106614270029100742676903231865717298580133738466253899295526948525686104173044353135085608448049361986185320959413144166962495761363267441880271005774823214795193495936693312315510309440408539984688705595845235563350249457176692150606095057315127326316933221409246053631263526765032213783909644002986937295223790343151333639280489848060485152122296081339320040911242614933092148187799558651818586031237702532118952528491156967671925752515633144685984309173817730362086427274778622477614727498388157580334879946325679018446309937758805710761123326596793784405091594185076972247540102344872270506818634656445887360699922559399596157261181307293853693130647700972432684816534195800007126793872387260721228698574311633374324979863266051490102996877429952979149856245094809499578674808999882964589263743248233971309950555531266344897019425169808645682336744189641159869335991335956596728868232003584884477660264039878250320984656281441631200484385215702398906072673564975090960792937225180458683045606707245231768862979816358414820828687932667471701780833458018913857173173446123700824156078521412024905384302289002197648075025990212212282004336380239035906574378364936623622101454127965442475201402733432121370622582495068388854848164349748972232276374823633361823629685480039258735764358996994125687169973355633677224257576492431322871535472849042379849976909814435575793384784574971595558935368019853109882276690215281100950847419831902168152673589041671632416175005020542837882965688967301547669975309472903659657286831025341902132259088622571495147142071896171781434621898196945995814296932282937920023026667566352091107519397814221960162690265765231610076409655729812014280937911988504647163938486325146917424555370553786329430747744183837294257673516476295844871750998186688265389238560371235199360549469741803182095168161919389716240507373682780458942518114639746673056564040027508976628826086449122750247117793606748285415808197037120141187082141289345483007182948476987924082665184494207652061493498281839823890853614672534971330711503807184774316609223821528668950529287456783627062557274337823405500487882842778401283787612164422814460689672435068095998287698587720873441243510101506418931487674131341898436034200029792056405089569903301372494232846041035425608616038722763702547870519947571780303488646553430452506458402776248301012008207218435860252437757906373137513701832826211720888817426737336383815382479723405464327295498526239275919265540538697004795402180926022928679019248672113949203581961265711628078524966791063354374927817392999909707919890796103163408599178393488809082195519001048876378449970963132868368873587761004906909166455130387483982112166111462323448843246347812145932793588261180187537577259968505331046206153178182503783438243646901214502134904436119366657911017261745972557809436731184334519480726344267757991031773822985107498709291742064788574079797870365657350491211513228671510920184112048668287017569491196115061871530548024051242863525983529714058080533520255912274707465952268402280104176365349529009084765429367335104659205289844966048457052357649225708646518925647819207617114014914383067591774824903252339180825329434233121982010673042222073583502953279330226935119650988667411865907457276357787791703135561354985991511568371972446934557113663779228352895711363542721769976597996282382787128162328993641675704726270439439132462845676453719083555772532408660549745756665541683579819592906180822914905078248181267531485601379759205314180794770430847026499231168015555567452553139629631563080382981558796670654420722185799488156856380544252462281360996356231487635416772016266304692101286361881080222272605081075138793966410874645204391337416960359798063243958442882013919952110234040588514061919694980701025740913647333581911468217125241801938372790441041625340837509877570635145417216345202028657419766360765538128801614897452932487802787890616135508682968468967779590392227587671626910304531193432311026616040250850503741071556267803162646173808786011463663270929668320295763105497294442540500761689076357372652899704782956201028682106516113803629888085446713968164116690586088848736577593379675048022437756987230708558711535305803536895423108546138906105177975661922056265496751462583037105680528209826131487234241665016452622454929158814079167116298026621993064962853666218507347481667343503482831529910814868375144236665300898438725017800457214230470372313781925600099921654872246669145775011760156930842554652692270545149139534440672277366647164493757631681468362759200134396877403399358803808836345533632109897611571488610463141224751755625292874774455007051684846253296119972882008092524877269070470346286145212694848862779163538757778748818520689367579140962358633939832963194846687796777330820642202008635104344012423927209513400986161790462004359900156420836672777849961959445566970351918760833579438395378566853730996309118396544250005839124384378480956238781545832720337241410740352774118970092062391662859088185559081652030141652845735431642907002408478448568737004609916231428249192776136494656270884097256493893858413415414819193741428755505261782190626984823905187072383200618034225935072183020723821310939903084890588545613029070459117949264263348258040983460405720479414751193919151190949995625308946139930693527915417737314579150732775115274907586296541326622727056889459413442104274110318769989231275402619621431705842063384886333900358856687963144482721903647065937758552043524703311219916345018605458547344050780019994388832568464130810603194323109587643974952242439661321668646047505672787642126980092333785278772171806768409743581020311688025484785830630875252603077229680853260648750521552592526157416646918028345370071667674438403331927233707061185312088930925414283388137766315524385930088569636134446210832670192788661245652754827636675247783802968611009251159464092779147806913997868464512281126795175475839861361659207231601805420003337880111095402991661253112071714399297344992095642042477123200942030190775800402304424721733469003867602876188474365433878006867717049847603029408895413088833039308899046705887250481941433338488250057318563976531625606265460577206624368315911410247343752813639173031726148875975594949990438153324382512313270594572811090279822876523748463311489449718964429554356705448677092692978075276821519615006747726203556368960744261794023055118460407583347279195596170249467983259052665544651999309851675547456153190336363534162518116158104577718672354706984566826109219626610479008015827428700911276576899571926349014079028176555536056501062556072709564198376193953757025213895991575576543894359983863260547209873799828684013531641210456764320344441497992207406909706060521600638305800102756023289859435574188202226132123524077200331112303468815399732681272384364018985206488292529286756684100263394382544917789210625711991245167165196795596494171896305307189208750575332242403343995804412360002286239302321240109714306351253350859522155055350847321989106450473910746069472173027292397576151055252688288754229844516525635584389274928984481058963036593140747361634405598085547701201664211696416339099097627252527369778204576331352899543048142083623913241217828490121317667365668358830376099153217011087463777977261925675523564719629688586567399239076700621223797774858446060459088687061290639904425277966360350526495726572715322712895439140850143466115890083703440876196579273499326848288387067648907329645046143670911338508694159738579102232283482932186187187862077763350593720868705814556977656962666615241538851728204440823859734041506895967683590778853749425760014391297786881379958510913067465584734708052590398462219230009219720702573536922096517122906999071717002044412221024447678710631065233231234862851511788682519943911753668281067312764815198660451146890480035952078837531130182036291341771498576618435251404651696064680067984433561870769649967916569425290746464122641611916942599781854139761647154186054892924588717098256527866362138153877561085029673537614259856590763663533791721037108863245851284772993328708610243681596908168194035604060319180981759366815545673557987474976518827170449019074466779205272036778811959223501010247384622242007792983735604573533157455312291910025317114331171885558812766518927626331902456515729440478631897104380209216512051943645835666905947753545419877792518609968112843702747053940444574466782401866577147112941652535044714598763062426904677757715087167559184385194491514411205102592592252297475883970100299434684870134261253205248277872589195665084221278849248152083906636464742162532302045963222852219910739493145781784722932544939331420596347253211477300039683243279418008068534395217703202980866710269401934613017563145344285009515749342083723976093786829757379778661828037788061870898541650546257258870127245628288958257151935988419145808690986979100482236393262152817171927951053283544227477154181438652753792151281706448445310201866852956402758791423695631226502199640071192698417220516025398531281051833069149606970799979037536309980591480900812903757674681652240293788769319412735098892738771102424778757271079844088386499509286577243404597495963703141038292992, - 765344275469604883077937738515997217066976999552260962627236355644053264795514596870915714313393866087871775102620265129999647374637603414594510933499132331856313891203791074201711547342767889624784836881743466235455468081114998836189032798700099376990139143824116156331019862943889193708594921526417844146860633598751672411573227237803634159678682610109823706724205785094955747277806196692448425347017180966097726439790512083411974017910457713137173996275758355108921571649314225928014170505464100002558164456886946431543417509539961992417626073187975207280179481595596020606179267102870203201100834018618608847184883638657913758650618474661839602682216891602582026115707727179269628184926737546632287227412766909197334895804756425617567604512251102665141177981049856735793036340948046184505102854567841200916031886754549240178065317898712718443076167841868262816231453345703919598405750408790579680824225923048415387065114264864867793714078121030036345815699531616183648201731097862890742209618052073384326467535779885120772949270219718487573956150344825059179172751242619285046073565829815946994486235428071184807536167350135003851517024764439720286074869517631542645008488122048908745109697062435275936977699407884933096762757472590385915811231412672012808404750934427384823995904133048046108914490782096074193897773932489578551289769719364772576627657129954685980083863934056108616657879784231786549567765125170732615839258653111655078682016509188719534180204777668658909176313622516644890561571306746126141887304970872105295762708759121021696809729527093370805329239373099866555672144183120784111929619380088538720958164371398537117791476733345580388136104387765769748801862978517958181438920571910976552334195944400249877287129728599331044688021584887714837325937507931171101643916764477636954640456541521784027420475956840372796360364450723681325019469680980097646935621924908889492506889027550692537914243024613137818393868246145152639957677292932326176945329366764412537389095236414559967616975127329609567117996217756655295374237720349311657111629439080427090706994495964204147597354251334743589003851558318799332401103141733844495515969698707960382753427955627952862300527004433723549987134048325867339423289413871150527808168175795378207723516369155657002619052892177857561723868088696434026997359640146735657853915892562676264551126769328312608372913511861852200314831625841688082434240987285030380924292874589950375303587246314027379231447986118342579949768338416661600651233419108802536958356526224926936377712344102313168243815371732115975096800518757305886778658731116156572728539385121200410623513698816929124713868274468143110099978289679440034910154843285910290890849058295913042399183342501149586061356108764452517343551387188129441500519572189239509098907485515153112121206160058717276855344116425004568150172614524554782011318403248262806971531125617813925489338795709715006962036064158546899234881796364856919494022362459862873715404349355721946459376695983514714649223307426716625981172155121035300905902418727637983074522779791296019569499137178078012057341367248694823471702204957638297531492718285417063926785142853640664080309163684939531573109067762705643193367298423447435415786950856943420553695471239450024283863642219778295775111616716378090088665702040706610529696640053053884648238794138520965598953463172826820609114520339789716898026199323818409820370772413129578421679304496598123047773986555731707593297939246476898787204362204963124238070413854341413194984562225467319251006893547238018033511394336465994814992460771745204585747061500106125398820461403596094403289971658671317415008305253321786253265997911057939754006765885004374258494565123443745525414358112301917396842976801336557357858827103158995802573529873038079689999141846224462257244715930176821361881816200355834286771032052963308370646823895777621518208742474657990768569918859890818036207709581617333841875201979982306677868073606571089998499904017592760203190831113638985707271075942252870557275985006177610549849150210463636826122091721650528744105828452781896998045324407373004713914299960457548378711540850123705688306626947576275708611418982959587143560973879603876968119289662475778834704148712221247284469008203842797082251598474429565146624721279247440422783662419673282886016282611880664707581225269932774263743444410648144182772863135815511524979627900413625432928329063009558677206511926823188751100821691311214132318743674907863400710013071233511996119399700799232025763637071820857175784126951819596274728889649556423496648235139343547257388279477648401622810379860663662435419302763228046008704143830873942357742269021713988487706860344912584487610568221183015011756506221235226583813839015678091339048960359795303616956991411266732549023777246532853253194461255795969484480407526968573293423727016497955730315422581179642620944569463359845294095551875556652449022916156306356099398457258007770952278370894858093856217288057363934080518112108199016196579958177831145002434024210174933939267135281092713432545721295421231317996997833045140447793108393799248968429626056565173876939483912565750158242653121640858122318099026285333773001784167123921119653829186635713840294831448877583451476374903435899238065282055958977411693667981644356017494393276739253289727393873253109275530886704873947682674519425119009634155211150869551239771285771634739695535776022690272929952592539030907915302331097914199532696454892871588850573049609710429316706394294146915173240794487130246038121589193854003744877310350571984420796649470320333766418811844350351370026964117276839314252197296368137431248935512558729663006715545844379801060581100949489404985448676364951861178159146514509215531733329174079159131872425086241857812055929935164394541933541177588543075883452851382367505330904256122218346597493661602175498280622914444452390960645710898933888039126553223281648879758329311957192161686787692522770218148598242346384218798001000358607573422102670753657693025134009797779542645746047363960532968515139068010191595101108159710255121879900727706370156513373090808377218057797857149315862018927130407964229905428012120902239086829698011298256293554099506514644931055863658517173079799698187940580782931544579262521362008406907401318119390557783652213191363845813510557151544903926657856807925707580500956675284134829154492231464746902055413868269448110945257493663932088742497737811346192469130174901801982571365018278612862484224473517886759977437740550951314591363563984527861061430841022276263408327373507071484468737724368336401634172987034670026264337205667711925656274272109933756001847701834168639807195708183991919911853373264901835904546295110749890488505822759287737578521143166449965599567775220473915344764346584538394997383314593754599426289536266487249600168483234481106937672423878826102308721457318089603072794260291429271872394656507987878812217248211417349688954838904048575738019312527437557531662892605001733648837210760839526652363193903209770127528491497016682226961623507863231352694711761595479836283646756355181415781277352873635661691399390017757607122877570203153816351929316985286831331418796290708982396873979550509697806065118521886751778051452923458557123509360703497915710899592248023935926609901560542210509919060551538590917982388996554015716116817251146051851796577416072743486044713027448562376773272607550442928020980902810315425670444785251342377737002714664246281133504803963458715514887564125925473019551260763160163986488667466990424522399590115065198343158143808018282598875053201054776493564627971947707240482136377045091149374359534809454787444185014772487701685254037586845586181410973923190296933113202772620701745371751426000751974449611419981893315466841932934076772729834490161667541061295005090262704995817269997776434105764483966260202266417741333150991485987671646873829993532202085006650885616215127727672460981424191130480914902229996384414005360293807479968687800746171045171654759704337506563289779887633866549518564859918647543542438984191239049362207703135202835421634805368277607367417595705190337383972262199778956280351734556150070688589369827082327507116128139449506883290833706604808612611744114313398058157787690992024981909048958035083144877911014577734215970170659907243768440756421284600161228420569936010887524955659803698153459735245363250897897760591879194537474233983078195803338222366648786155639103516523978400306432244907084086134535704568945562864402657666338217846917803692343785288081772112000827010955455508168395817550165770587661820678789801936427724710001075746089228902645540116972055913946946041010300600822132223310865043229100793553481481446015324417074312721685962078566266631075044230535951986165158582644653727294925758429530081521333466997360916294816631751832352720913376874339852746924632503143465086432000690042108216300823486095597205169348631683660848233831730780989602042663848752411861659859394907430708909256377539137273942227104992381592878927611392687639661151258849394444529115245567851371762892095373723738461757237434987864850940115501579584755349791084577606691628770751712337818642375224970070630715438608751893442258781391199007827124483251677246209064975547187086209629965247256975848159093209951566536457020382613292527667213741627847271689959663769297329417227784729272024962972630964526701538444900256807980507665959642289879223505903984713123203214544438647565249287624423846181987376412719690594942258573319943997332461966630325786153293054626138603651072, - 622922353841662368593948394896204936267713731682080143402008558921840806119275120160262876609282132080053531906377434614508112914738421514155086532772110705922563836243413586622509706641020504727722489429533296497084424043448603709049543198147632656027760952577934386740899122538311387827221185253448486504790319921234685365063802200361952976599777755946146873489564280183727769373254517421991764161898399172652627662305834829202886272932420783427338160971163215705881109153901307471028691678623214588824638040927417169774469765959377501964292746294975396839280357448200403752998753439964842330748192500157720171728053923279980405952063379808074732610751231192312463816388230371543543202153839616736789102644210827706243499970801236793720095230277185690896749127838697958713844571719774094379162002015626043385641993579735909323977816196330605064009864344636517758191893239261006216940758123503110766225828908849905814721305073492753960367054788052131023797782777955280643386795831157530896838516387265904600561020168895965235592903413647831100472160109911558677158228811314908235675693216264925505353734027748826291583485153222859579604478168336452977381773121183097197719908595580184768522198076403497362307507175383926299247504785597619618660581824144735032659373893243324401285989645243819722301014516096155036224928366222457663184599101967342481928511593699034420170566289838801288116253453012273961077237392118959501808593655184066831039040061255940987772089188318571177281553271799696459384825314580946836827231775227635094838717786302413528686290901412935351974532778459332237639581553015245516627145573228793453998773679527973961537422324962673376160953902804206786137072344863802046695007849156998857028591803736135823393678669491567710589259927060970886397688756087189585958475268604905956618538453077634095086149969108421393783347637337521684947853970679037214483066067609815491607327936317710681480314773101193961407684450390591885704127105443004300899417798479357964722538527758892783210262111923218849708124300919767169233002000926986164527682627606779336734319480800084534263414980820462354671485945711808798173836491928421940874004753931602319839050310991953239816219414156842414545199776277249984914894200034113845603715559420149921770134752461369333301847484141633776852568049778714927643509340324481297537489733942394212287515447487570386170903212800811068819941304009036023619832536349776982680129623634604815384815808243221577416055984339968555808784235705140212499518595342916551039231706194466297336266373428197863949242203633736935377124664616770309567248796946452385623778223982911877688165828815947344841569303368807423740516862077724592786812413292622017896937849249547530873587182469185771750821495237599397920610985231575326684477045820887539069695761896844973961072099629815190671605167138092320450396182376703103021125778921999554623762180466774829414561937333063283976350896088800560252535123582304187229800959357105926489596188373636265769012744079353580372873066936798417306063845064892204646893392867151911068459874592887374948162089509847606429516247647256355972365668563986726720469188067047466680333620977983545211337729707418134645526324238617982973147236604096575057612161242318811539940940513277245403044475220096018807655884717760987648437725288312164847527129779866756990944805572049430417338265588860670742078043928677106670161223782416003234588273511494069879705914461142266711776361030095745477986929256779081356880726328978422178935744410417942505868846381143082654191845335459218052525372530809165446477359573303764793103217055037049294719155650766751965889303295617803326145322519832852887164945210864646728547984121693682668368106355730856472591883931953560427930633328875165907651133934960150692384617187923463908379387232143177004758093599872349767713812991642001867475550156437660977465797631430922059578612146557589717962977159990393481106274972826887413308978830954064868562179968243753406941817793828760974448899722574655730100348884591957313898431922296736966683967025427457885174977481950312381498518750707578514535391493383868213988667600091765893685885367991520790700523330341915461314859045992315868858260279323946958054445905057375466355764004086645892856124838017883574807848708412437959083696892198083742876300234910408121617154280692706966540327101285889510737732012338837943459060128964791944995505923978986634482015972518539752166634039885576029422840244087992923546157601146964645326572264384657146575569606916790489291365846816894603605314933176063809713039291495537453173339212937410029697469366780147643509240918155606884818842087684170652410580231270349245945418798943613882710531232263892324585136497394909866494444461187941695779320454364598720389632382772329352109263457313199514287922486184538222389678465048293699221183158092741911557834915443322136590008903330397389497342473941251132938406332317861035821541969057110261889873759686529989626572663711022472472489602560744139123079914723403221055183557482362179717655849161201826522672649207725903813145018337034837508037482317393321718176266417366543004078481273009335344683639970550186591340200468702817727990189157296682755503707799160665553689211439935541321151727591380921009130420464455826016034098961365279160466327507598914263023257869304852353535228533657204010112610350342971657893900923074137335796074688478435160594427631433062229263281913150886682245736824925844248466799150506564253353056074015517450221766929041046618428135784917867259430429567089281808159372756777887737719056535689806482191684658425723128976455540095467612244158111846096921464357223641343639924561833568010409826163640943578205746979848480481994465529136578782684780718979860587504158173517768948790171186541754402618286842825289573618143810732061237994462606139135849699112556767908561215721631688803047360912850637254613050746067666608212655750579435172360091581616129674588467769083918221858813723416832662027566355361744890098150059613703312866494428319136405137035181595185549912903114339906642552718917715307873052131856980873288146162460624044768083366208825045913052073302815657980439408007472705090445431561881972982336369398871864861834305070101749969973509443380748033723737050743535249023773126233350517513978754509500358960847078713890469398261839030312583494978890754565348390274854764420224151781031210238318529223810895536248005716705600334870528603036976391970610895292094927446119442064750292842073414060918584875589539603786436101526817147820900482650318792923139715607445685102998362767919954118424551199529316036472353609742706722231433580793774730853504265795892399645221133158810988789725989898301712087745957062754332131544461644264916951069059686930342935630451900641995951744729937680247183564251480478588366560059982490802605738375335866250246420451054042480616421664972995857393250847392696345828694560864478426407672667446124097189402589637772891391942742664214948380687956228690428474140690242844927919601898677995806063112835331006260022017896557480976834503501140430120359130773184971168305411012788169489874481973434899931098635073268358424345843332733850876654859340158518716728251074424272306994246240865265249055492963689006107879403285294804535364916758888667442945859674421788944943800137089269092188208225651879281386147069375912929993594763304215290320937362934782718451138138541393714953646658498105567130030755186301582241673576874364154115648264768625769504333947588598928831355966223316993990680264046055513962934899805951637205331901370273392902948939680795357188060663446092893295517797628021371459099867724525161782832647857791998099930145941702605717197579656647213987798895549549499149237244024469847995446997190206117187901681869608395620126321198397494614104615591168412905047129407277544437595727711158051178827693723886966426249161330944335120978761087043625678820633767977148487541573915893801134166406350834622078919596403939300854315019817970523174406296727999271531600728248659984040408163172531618777965845717361339629518082734694188263636244275850046455875852752220013651340664643425626872715587400612220531578807861925081774301598342850260065461160088202395777805000487201954747831692851544672667930584008384790662993339354525610780935660483995071664868234371138780100792237022204141707703917536511341203686333485044743466674491928148353369116818820851091814603463053641976299321778490343745556944091232078805300593356568511674321295653985396765276346397257220601044272566242172700011617759373473046179328403456541910173739710223443495465209881091887095859038101063908815562008236141112015351988939359005695467000311976689383027620695698957634875856268783421985478579444688505578052947544582272960135052157717308081451754233540079881316789594505679631868328372170972944857818970897076301727160656504986778389628047160616612078751797943124103595783476080776237002407459131712188606111762390008569502481971670748790095458722019755668038093998101019207195126155861168383482641503804764846609640757574938871265501962671829515844632327234648835231432523772440553934531521579889939980062036898885432531343813118696519974047479269586185272444932613083810418828363875485537367343291041411514312881972687223115503752550771842015309587841481415397791458224056068675426173895129039379619127649381822822938844779408686753532979271009424006330771907826031389319952658426098152097454327607072686602172868865952694759589477278673879668241434924757705423904216029801447743476711702006857728, - 468330352071737048942724659479641101979255405571252950134190576291705192804657320434975558559352241404553686556989991300183659881642148701620621082374463462622034453333706107571029681032042692544288389567386867411664434811475885329872378563970190607158346903658168143306399949721271096483401570856424903332907949915652096272195916215450811490509156373631152662656934108307774768967413946589608680726890220732891799039871773085036342402321435614646697465901702182831024098919325671475913582829854623964851767158807805244046894651524210475324535399266462033065271181500488575451802522917666978430210873829699594222548553733502883986993837736053393821216942931532765168201660108633066313745263331511685934196267083387081293432647355013541089563953295589706000917905338087582167042903590464143764255757870796883293446330194448327332721741449944333777762095131829827093827235792709622807503188393407402241427357242729404457530803331064020703145404275304798987877128606963998894812686101067573510336607911806546013511000927147101445002065034974833366595551444955134082353129324095917305835382505125573181425069215038219808116134668437966288669657404203546643620169139645238594300635556826369545676753180612367762285158349369588117293310181918882791157478778420101897083412668960438740710966319115361525352644700711277405919237861414159913014454747203112436910743795798688462316440472712380971420050261633559235697401895156986293761548898821596569038397953911836453485832870890873566963568933501008810167721018682700314433363140619156477816010100679661468995113457701759894651938203187849109579691669647805373272402866736158803669312035944102367255318559393555022455017269794462273387490722735783429327789505586395260898953404987695412901531419689171182889449519000241162309452748351185059857869591846278244703216499302831516661615563211476126755165829858810360042388918806579510652359833413299952662919898033782223272033212647621758486597135204533748408415158055692211122290294120967781500527316103905542346897791152256725224229867194019666367659668618546835899208862784628057925933502746902230807888116996118020330293496540112708131774851543428448667551469171983783710463334365326710798020226809484499973935647082466130333655619480646536827891789348469175410667862791702384005601848926332169421311066032252308116746810159096784788066352946430052361916265339880422771788251897560903141724422907099829606838617312102664791999425000579127381437189675289260810613150577416358863945627285858141111431501769003597115321066224427090898324696135661189212093946156425227940567562466055841163059427719563225827759542153937460914189901333360392410506320544788850274108716212253552249902534656350322932101840761445736803464812201156027521092468736370338687537697627258881368613580328504827693572391844019751896448070420924446888169468554518845206005119989842179977813032729688587938961297147380225174991428856942644626783447821237773934381263960406951911408777660005915134375714448121711217445844991001763826860550804622656847269411553856128662903218892198722406620676423503779703899743271426739002046217162155721497241190626804569078275703140171885364769960158793964884081547379876607139191059716019219873408438378880459890548238859408029324876393538516173811048833940111065531129558502325868076784325972658846163332015321714247155270173001810477303630909312714157371308807941921721497151741421978053012373920258113263807929892194201378260220213713646648000549280339083622865128483845597079375738269905920633595836741034934054646567198765943943998465203542246469586350900691461244988269411565209909665733544840970635147371387179901781187555160307080861594025514376612177153784992197811435199160353421371448238959758100640284609230377938411144498044995955376622327461580253664806290553382813539379436556144748850751290164331790031336796689005803328079213280346704458563163959338624211015469818863080511823505312189601047153304003852307903976854296650439130332566383355737248328604921305539098110282571916191567851359629492557205138705265814325206201785314705489215752956699347830588473681514372286866765744426553861703701013682474456695231006756359499347459696232108743495427259047766627417839866863950399718821052677642421122925242524819967802264096918714157445203380879255405732985972833128453758528573091226471085752513215411376368590670200509565003106282266692103168826658400154590570638994430328964655554501580896914239188474170263673027551166141185280627877208858267150173043463900441218823575207147016730960284206478400593235426955088982190483577545143248427232682689697331430922550109413296490152206998667571882731308439620082654383148107911047437873423317378933912096391351822392646563720097400844136196071566847873475615356679358658248713718056444747679015245611923853997031903346045988661919602843429368403587417040273140415669312703388338913322305337037963333438354040203639432399233423064156701060412572217801276819688407320404372724797509920186651824095292262598086626945990635263421155658474085939890327702073175169350451724961162922958790751798724009004820559080554834844959928377660267481172984156891068227088483081384170933322017586927185343675424036354961665679398460735099603998409161058479183029982532846001018344815178376087044600257464911457419459169654851328385352260333883121392622590807611266568423242903569286332507066883575794652085220434498346737136443822538402426400885982095746525622421747680854906075369065004870155623101087899164114729660587220326440739397607830493004161495188970638289840977282199092469833994863442074401714378421110022183877898693219211083585388818847506318181091397720009947012852856728627188162393431806561199943321993473881831859281213455048677910822084702033864442700537351785168449414181047266624458240050385109243238846823756047347334904630598858601280769901303894808852859435391065280715979740490618307208653892054583897755594635651177438289641013972816411597610848040088780035686949934574616659770792552268978266826800028071617265865336209692621520626140857236446799458653268358156983312328111119753208756977296785828375394175995773943881466924756789650525958124360194096518461829174274530724958096756091060517145131400117224688984844566804249206172950933246302477679065594405910936061869679253561048070074528436441482524305781171324094183092037063779094292497418523574210823121129747836379761153266121402449430810803919956928262547702331672230335216135927918757663719494456158104367836494066010377284789712299369839703563638959156492236329543383560220593811639746542246414401636873425468965492649827752386279257036184973269283330283033472130889027024820904864399322986034697267275317290929377341690075009292710408916201784327824017176981577334742512307673475924115297120935829436581272478111494939643123972987093139893943947523772370633930698452065631047000506240552794456246243820615811038106398401164016731258690850670956138092398747885770775223431497527430014001191951860813375877523093347428164188662681814693958869211794690297604672829840540460786723614249742052006505534246542439731241291213756255545444812836219501719844580844765645956145470325147878275062696449568685500953988307408048903198620892979465903593937575116573278749504673920714562686237263806800461000677105488297755237887930752609721385966059161068348874232941315743750065740637165089511472039759423339237807728544074351683289366724517269276478189791567784727438894439637184035661501123561568104251309408148945405000461585555116041113792276650901916347979925511033202175035932626009189775323192916383916646842817509218548182826854664383057186343024494126685908730252412443783958349860957935800534016415537879790157448991252451144623927838051700461006276495805649742380308986732027327063178829444171290533899336874800133654664963917315059393247837037013850367428737537328497361905196774722844121553180961997200491613263210786902140773294804459825926538818485456552770438438755578145528480322497509174840028908251601234186586691389766161618736226065550547238570158786589307695378474841645967142261953544081740607261153640558655732222112877662292559037336636152838375963518489596412561573283692988493482645016668891306218953264065485523331191672907763724229053240772804975768665113569473382258169570453915782076554986326623960012585803270906846959105391203778509982100164898544504885408606387921929424842715414154356791164769531869364218765566992141482671348725721466728899204509169953993977912480087530517184185841493588888691930644423710989800825039272922316679275908509576621963340044185284997755866253464630921179514817683464647569743252742927039901481927503417911113063251044369847929504138565546295783365002614153676167746054287957425209074580552075986842967277420960503820268063386465618240008711974480787939901118703862745880885590142151152378078604137783408049494981729979830452814793411097976389884218269715510517506161766468657574260774618493698990196358538565659251832590574569774051236022301436484447484887864608502830415628017460851676146127452786855616133485282272038711064619421873590878548127449895880110710485378394939346726198694223141508145472594954933302395507478494150315932473608538082374415301897813315630868603207836533577102384139163259180366301873955582092532413633067534489006179908652233751665553691006190399503336042976271686946709779424792717531621575914825645152428613072819036255414506239192682310713564226339076303350605432419549073335000680749029105954954197243967955795968, - 325857477320048091110001600599212270851328072557107934732674929532350858814062136118415924075432990441405887972484809864642044174930533790373655281081990703936416730904230108220862129542062128873295683135107309978767558983873242795839945389388077583093068955598571959812225274029488603568521898170492488039486751565363938032288873387359237053828739250546412847673455005523921316802937287975492063197366902858363263306688722498456828950102791947802673692122036017923754792806091162518851830537091675231754036036818522430358143704202844734118524097053241838748868023811684629796900745266365934037177870445623052706427010495619789659385382633052444568403212146109716197284693664172120964388534280783616478569878991549685413450987776040761806556910238281969412949338547653820630873139912768541345692218286720029225165245824889801862203323835968682099399950103279398973016025750574468106315319259104145272381163520052751681299027622609958060124681683194583767098159171364121099989439627696540520082497191745478866495166785726921739558808597205604274209714895618691333763294241507635115528170492439900789669617857945896612725113154671960158519227713939216432991204653007869535449222136806039472313562202493716928130171107446767630687118801627679543254464156764192120885537959120988489670495774815756635201266824226225837671351075644782008025436274874754765615335091699309878581133352590576108927942673956833301119744382398644201329343335056888784489258151193702059160037991375831231012729969978020077477538901479795175632807509604397043585453422006831288286278765587444357982276428669539577682841275901987456719639644422647096448165522485771553185418669632733761800506146024580609228663907899422000967519698440033913642061242916156155932871225594828960902746150478573465899963627568840783179773440778816393620242304237396898741267353117736388138147443244922565996505225768719785287704163334050540431976659466724779226642669450582329551452187160996066148886192378853162417246243776326851682191680947660064430115093984760683221174021992367759269345802797144540328923117138097684499568524253399139797616641151103346075852846729991696709668720833559172635075160932955230042733469150598460697626748589275729892204098557485285407430008928854032305831152590884216204909576008993585754332035997461402919602991753318594640922890109626560692010309835688756109631565875377709557300579040633549284859764918148244354450530707171451671051754927347368352489007308316618633281597565129730396856772886992865254751088098432775430885023603670174966069169699627993036268193421802747084937781064013057828971894843848444661830941775840239129117029097729398857970534988049746806059009699788254171724430367438144845986055339025796586288920106463275517035893894261902448900830041439817732737026361381375349689022220810107321943721729081979838683832154046876033217703557805326740908035673417173652849908111805277708887169107839092581105523310024045685254542368690327019676278842097273905337296872305984972492762075550418974753694324962444760434187305421894773685449924642868523268374874644082893133434287401975479092820535383905674418943988838853072084551176709450085088979477734117923511293648727762448935184640193659279732953827687637030694508895661673239039647215669016714395426724596161326317663014511166496532792420229152503654100001198963122931777416112214072202418022460722226051167366461937590723316680218724761436368816310324154648721764793957897741559511376746118245720087425153744774004106941193492591064566185136573910997896422184038919334282912043967340483538530288108510238374067210679937448472727673713127430061305948752873322691125662737019085667046113686434688033104839015364618767105334601651237811439815849672262692788868110057455614547374086088219216594987744544704068516328706555369204994550851816252321863850665242365332188555836188211103582921346283706978010831826002777130976978860427157153831191597870482958493501814007136465566847847076735775003248845236393625164334458811110959108929885051853161557384708965569534411290142575925052472129280108724503574098941308498579586350227960617795712384579283557956213835513603578647677946776815524915678840464928464239068545572019656996058876939029011260109476952698658288976189863262201546715907126971470914602398189205119390510983245740563977141247725809145223836962658172741886655710340840458880786362682643892659667103428518155235535736543200679906834911355839769791523356533864303108070801620671208076660561423236746967593036091749224777707562550871871499834362569458039802301225771845135342169402522994788630383496641452001989920166423612711541715761760601383891914969221664096838005265139778843152612586012185159865410560958867697124083518455845575124321563444036896794223012182829342907055668509794764386801268740752473597038657105900262350900232179892227151268013071978553317922823209165697731696731066874490392374855330739215809735493399969919529290945674164756054422747204403933542182412380933855207704482908295374386539922072542540465151880100525056363944695772487257749674650350208826725834155630915664496546152313468511345189799715889829551969748508432603504980235413126024980510539227819147031932029956466294523389468157240878778349837290919852650819408963730853617967340792509393046744618799339736987715785677938142832166243236081042526632501417005851774200525704112095315243815358697769855820251126292332942230222494845089986428239050949980782466229209952839279897672041954894169617132883874494084226304611130570242359042918087609546630640406849758084840875487696695299682845307077498570255532327818494201645332888784481010595567652593421092772349792382169470022658449833849161741515262317073563580590396786455931189895672902892566344506531436287292711049146982689221962989324209139062476287566133403668314796431498732077414383508137011751912535955983998283990368746929599882452213418287964936192218763208982967704937173828193365965944441842777138752337078736313647680063512829234852239357606254958333348157379430846770551444453254965064764955892529988387604515524694859569640131872899323873406949024521229484335048651594192480352897603708907207437828944228313849557284401570890860600331168406573146817773641496032826375708801994764987803332893749509033585264308843963001234447945716749923476999893972582294662091980578733742045139341834246601935688553656619501036634630226235191125200450114670640062882570262818912974271180486034781247364677820711321962863212868190598286138084369675206554611133649947960622752584356081625622169069688179346493960578776180053956798680594016044450682688849907793574812408110389717443281909664819944987051654317184431615836169542226726612624200767682592230562180679014384424790794014480135252258223417798731522554682577873361018221644684176808016976294021270117803641218659500165975701414592880340018031352532159463228574438157644672926502237491533577546982784115877215100639499280405939895694116718947091754794055721804492298958297192831394930871295874268132853284086717226159464911179481394863343631067088070194091696661221586188317579552109954358768083824676552302917773389346069664086956660746245863531951027775485408002452922806385603863462676162166025948839644631869498485578788858048263408306009827298705973696095886334161762012283538369114243133969744193385103712961245564853661554854869632673670860596917358747131660135319394336839669114896986594001126118835035856489521657748045618160195890703363287011200765024840831220674626350481081623793274698436222437071284863065989305446559916211756401003391976464376912252376899371794639647210591656409802624145062852876849627510210456689410958576182853517003682563663912518910052899614417169727103021882931561069662561820649554935985959501359631576242346728430141489181963660095199733471299124954681179076164818250132800046679864231816019107821705659419399942395358933919007141328696957581039882118010683058013194867792316951683459600620104732606410839356638421297336877289874510253014857788004198153281048372056333152449134657518434120661965908531485633096302441798971246285125967014375189614035996496812335652562924917092920381784338353803410266421751682460322598499701186039612439469693676748196433455239245988035610531552790390124569981505498102070602396992584740031558282273978385342399975709786837231118655690175681776042785434085564965195935630174243493934433136460202047957565556764482579980987262060383396044092438600579683861077608544132223076391686849809829534795156152802682990378909360228204145602150033019916930896995083559721639699320111636466314211408938203177861080591848080438678168957556289377647917942717653615497051856227006485669798481598320909514696267217693381231824262924825733694431607923828606747627636297747575130532375141922354518825854807943117888464940219638435432187204640585333038592320979474840796643066455959387150862846994732334602525070539093329858579294440120667235891656871963684927725873176458292531846708634634792117978672529154955692275800714965535907852435442228860916577451037317471957620369863503421962806036233646722772019881708528288340274512922265034150136130387600474951943679263067539596070675882010424239043884268025841784536866126492341462152445769448729866980976890050569685545825250360421346602273191066629304752191875166004304221226073128758111575981569212665697941952418150665153321395240511651982936664578594758899813048058593121344866423130769832118422312342418798138157658644216606233655581083697152, - 210193190171622954585675994790085290079848353683483099021547382593911046696272123849235092925034377808503471666568527283510136405545874541566971339531384713663448100308280078373687715363030111206099185420482528003889365206914020253317473937962278375830830823168184654466591632222722429508434900111218796112304158490753192347662778500708917975654985195192574386037327621023126006639715617076725454183197487118296579429973612149829435672071369995804866054499990179589415393135812422104187183133409986134367728703675319396362405926090877490255706830982282574637598234020928568846039936089471946783080521172440325890767171731627949441637701072720234153157948674488208533711421702918189434011474393997190056650896449397087289903953531470393070565756566138227052468034636614341379376696342586728751760849965230978382876051157974448032486700203790458601241160899756703177041058701286540340099545032554123549008879998048538297086007907808781743580223108128541893794610510373635040827875186409323087138250027525536230107694159948110636796579628879203996368857359338483919947259545871966094985450246187133717177244869696541151440638126095083781764389325429175379482095163260156480145413521131143312483421176374624066599490338724377389619085717890938912870228476890559287145013749214055603964033740737726272115726446856505453910579551696993013885355182509780170980070625662620883830719066211695978952518914320753017710285535241361965670219740742222541192645731481749391292814447861396036343062898265054262801333314144171170922820934495896994283824059865719592094430393919552188867388730437644430809151016762289756153644185641937541798522128306226713796225485520650861229784771574041067707634248630664231572477406337203847770268048127054036154606616930354824754179291180009258430313342423657281436114925019663758846530219163666602291076925103243421182258675228940378742013402233734449335696848242015767924895794833980832519678497321208929254659113996190063631693174860706201800694949797603612202624301516334685827369708736236585264425492683110922881912888749503462342108322877944175778285249470051542671299813261358119388498930815815580046032580975381421658799023517569361424456317875867140237369408638238106916900730575062197265667386983422574486451314157690251584331418859703888084308344639891574934152300785373266782751544283151353871546157220412570189731437513780841399286416469059533033168244446198280769990167347466436009974091625513107580959878341639624408533560040948883020780840429501251754898418155212898774869253951352865691490190620469078056344175796098619600501803153630668452605820635359055222789421300988449398035472695523774154999495902490495237266139573898645216206490234867406520549340431330342828598155513335772422068115950469938727556174006798451688560849385149582628672187444627181540320583028200618501214359667006373122652396117818511289797786929736725598249148135352103281867486977773153537506357337482008356135672750598135993075837230924451517291103842098624312648797763018988129365730062255961276232985348382866548056800253239050842528250416920748689244350395114432277046820464088628848267841786075642353800832074289585168349680898080309427297870606481288139836380737279525076465453789608993089174157565767964435208673134088883172905479988658868910896450324214509659558043845949506462645315150425441894529532059393881409915903356053344895278316704436952435397333198973721151166735248997612879824938011958549221516224926051685430372193825110860954738366421412661718141826450272270021274230745191309359500188948401627076507389641061290348709417689705431064222508115355670416370567570867990215830154259277854336270459320996797774265025008218856229446321195859837143914578626687199604941676672456569986469206932692822398051896171544184893208721903637295661649944880248320092041225374992692820382475964660108066985065575677524558951855544734649725682815792417146871660285288305625818803746516377872752636042438561497113825067104829093612232322364993150865933519031056051509560914967065192866288417000909212897203480854330587508469532817610289728199143356544739768991424780507195775718449997019189195918560004894786608799046287954587427259714133486630877207861693932852066319306928809826112937983927090621706872390734043398437148844650362608986593292099325598640332959444435694858311535391503517252687061513575840124298168392126653550080605169459270306912945663824575271580843993352730208519000226360709616138288294358099653938359248525459867397538784820941264271952333632655660486292579439052140676790048982481289433443903016575109814012863626693402951234253454829952452251768441928573510596724983238081835974526851018413495261381053545769607532906453966169683311479286695816104798281625863661772005022295878240217135728157157318560020714247428423463325362486536469115622495785601784824470678838734174520482374122381863273434400996453122997797415936875524664844113556794378019506570572164091532653199452468875091392889308898573157124640102382491745155945602817475720769402386592604342728193235326773940483281130705086725152963453799600937283962633313409594321858369442477809372865043549725136479040930017814844023316068017203397166384273260182396890053512619512392560261869751500480471962302549690561266659744039263606667884449717790719171846214051267678410447851314490561377281577164139223831977036106834051940262233927646770191666991658823994599237761357373631490931663969962318461842547361810448779327255074850329183664863102170566566001029777063324517381912730266187372918409403154960203803901805207598007474557489085295345721143933725168883073490251344828971853241311434326813461759449411732435111772906757107165104957508277222562965862963796117660891744371003551039457798919852256520063443275529531065362519773717497686604831979180479261904741124656622224783833699498305305984638225763732003719441901746631337664673477575048683352557032810093799479998925768540911445588487481784390924954253733031560854175843406302619614441467411253421903277793608099483275595660211722889486821853727736345829926469670135252341291865359008085262963113870730637661924447395659704910053593327193868757084739144069154440194115753960065257596307308693668279346554330628076835144206468403311396254271281087505042703213796220409440939457659503051483441056257287403352673343439458173860989326353661856316839089203250602053795088847744316599257027893653692297981784332721298058764259686555380278798667174618506762104552339021921179466995164088903613300521057539280154341307268308726402284939324593035054115725178737676024585982262884138663336790923575955863955749184075049052752652637465234592388669862400846190222791416902358940237556105473476401938341335475822519182691821853893968334372614350513966695892883274795995549133933263610117679496461592077675228348209989256739379605311608778059855598541319030936329470106959737312678172108914354271555677639677105826967684753599679224939810270184695502183166121660644558139945386866024974793486870563962922386961660986211879920092540635156743205518931504782469518995600701873299516750574619966134157329936108301275123218384253003287145418439775413659677940214796205052268649345964780762493798922276224791103393690907353004086258720852639852371306394854887848269062809037672898311143041841687954825402460594541425037000624642298951330903513930145840223753761986641890366517655564551197517105690194374553133724945518430529299809402360101390376470395898301886680233075666859474694740188890409765038024297851462030250537810834265023976951405053736703794706423666675421219617929082626015815290614274986119570948784140307769166774912553727108326147505469157772941151761463222226972338726704767383309798131774770028220561794264431542729156763972240453538631945654955547500824049672628090876059012950906242492454860680130347046866322229422949381576330028474391599868946215978056560356440681602944169185076697177543650290316412521932722342260510878606371952150045749746652529958947561665925341785502029425308576722273253239569240902514161172945479976742886841536651237055361471361365022472265247136602612158945000417237731193996922258328927729364160423285267172686667721562145891716911654468793078781428689364274562536194575621990165271943306687433105262517481898242745834387404075252385942861305205456646050401972803364682752478387237817602001496199553317452349933112384660153660036264200991207491564827579922524955999286686788418305175572190169975027383824689476033091635697152411723088761736706011430824310074832958244023230837753905318739894667005670743741700610137875565247719543830914060453049821174953851862415384772517645018915089231938784117065575648376640983028082609488931297645500855307428464736343042609085818805172935597234331035236448786015571053704273404813907412838975072779918987824986167376599955472136566383148942942401134428174987454021420090115207189142240475717406401490563622821620548939883777835041070418948120712256998228131980941324928438447918327391165382562023445961961050733892251270374216691570636133768564000786575354751338122802854702750901622497826940703107190682208010342810964257857736218533623714060748251400130455132776138121792721606746264989543142755669756456189399162453883313896222459167917916765359152217106671313862013967315314753830557055778194000618311570960052412135859916210913309941269593901495565670760452864673290503011229879604108972022036027081923903541656238778414230620037115138801664, - 125902170852924726675819095389995703016201399876769693559882142185304980970296198518263171763233790181125255777310984737981321630175773842965847838967979067683357703622239338787082573556604231809717329324063881807403120646513940072962161389052489066044323648768768868872313186550778522381664035887246239786297149345705064383507785916949760441597648280055777832470975554225821964351309954623422700489267485866984341130845575014235608382787960414657383906568110644797271249445708611040803587945558636494320488918250769383922038557943620873880753870797319150761417728275674657315092956646686710510961988664071964356685127891755038994272091407193531008069194983612428688902115348444197365935470455714740928001987616400508006634587882492385040066019669143301852170845625543368719736194633651970054714240119955380248623638954573394973552746924777516717333505133090394147021138124768131815435155545847310600906914041525826042892581530318443677208206634702394943581342414241095830030971782306092185538787888711363646017133348756234290404288176152342454466827322510786233522948444027616279052183522123604162095807658513071437953333445675136552357323525261113558766336692624756066940599316762867984648689327695691495575008674890043455327618112624978825073071915946018841684903867378251768793817837941406237086926816611928301749690614048863268505300073810562010291036874733413471871952346601020074649290600866192207493809171356421797316540662670442127710848293321850070411294548841280974417614839024691431809682130167640528222249684778471833095130680875928928307489840546670556539395744011835307080849018993945105532209884165437880362396286638826240598353017375168488195023357467116441163630716242465585475178701274225555914756168081587895357023276030147420917321748431011732239630036587738305622571635503544522334500625854090142324391274539367864939214044375047333603180604248467517621567798127636748027827386657056679587209584966905742196490676244634969640297487525707330215422848680221613031391426463802437032608534954395324579612303596197702201718449719609979517152024368116718444685442899259659597332668189329826590566538153932159914823269855686981153548395334819677888261005416158451341826623934699569742554379606801731378327725478404051771604895692935910190847916553455724375914755290092775404395105197073114279123817845087274071024905853265825726795189216428568967816782542859457608621144322286988508270584214193168594221920677571774237255025618176479123556017451680966609682184154450942223865466772393565273803206239631162066239332043793606479717398533699006122384655567575078885125347450261280480882701834522367665704499452343134937985986921246091645241168682589493805806257406458724286717307872968020979354169520140847782624054407122888695675204117098888852339497149629909026101602266591084312424669080984379511832324700928461422364118551406858044972520583423632418866258978756968623951518060261359529606101216507793134610379584265214629521870224882984602231145579156121783869215946364397594854944128959759505277900497355589792734578119290646855327306408866267965745596346501438895182700505184772306957040693449394504192827502548976425692652768873765334773345527505157234589673372055675999874963229273724969259895575853417937236628689712365033678458458068273121458618949388019951732020749042536235702827956694796237579941469542923268278907922011359539282163884932805449564023281408219242934691889323106228327412277411519117513065972032596207613506931087700715177254770270936752904014263270424926663568203890410509691426927156598121209766076525422682581116829939226822815918612774186295026069799471947845141947946371649646932695472435274056760312169127436547053365086682983610287577728452926546456186850491942253778028853775181629326542786942156755527891340281666717048610866942886757065540290422427633198546709316886149770091847578635328704009664125563812264725956154542179384725141345199618264098975843938183284894671887241166517295540030616663231300994798519205778314520271525765298834747173983508313324690476592276116394657472192078458849607191968412091388115218867135967353675453735219223458240149387180834739940546702194357916277991663134064640803979820504000100262251496698248959773039611404950001873789767107720824953358934306131381035862174290830819137374785029712382269809507727881304185014119520320619759668585605086298735314729639121436195010044224925712515063038811908804956050824654990096474644683199713743757175800399819030902462777334925113320330641406833739534358877876279522548913348228103280114806902278538464886738908561880261492841011652045649678053681809887817048771541318880591327102298017425498992378377097453838242214139571666311600501409387611963567700110943781526527919816180405239457490982097991093096417250362745955548946820174931172704676936801897498424033667149027934662251008254858085789435641778389614697517367828244341274253365141572979211978950343247300223671320444239191377120085799010312264225881101137084715850431731666470431090732027809436648201739024454428249682154238219513419812644024856611840865851084583836036914413336549964190189441636114526774577124728955438360073191794460002421674729486651724038683823886507353999052059927262580638509754648563977656006205565830271065102787663256480563619108195870132991285932681893846555120774685370454437010001184264583173736719517955519531571377985966997734931798633202427359939502078271686828116050584645145133421194008091258432526530408106699009657181270044033715712470703240622963481868617161639033802400135112037305791494751493413888652486978863758300146003374801249302384011002854785144708828363953512096069215019121603137476910915700000226110448204329364353898836508583118424211394550408986773694635176168802377975433723955049619070527390908078600996808113921562932263664747549287496252928034418332737404826838095888200087199006718252413591231337200921181658078450998136589931970578607549473075421775831238687515304176993915463938369731155988055868796189622822525412893780711427142812993320590643143342600026194922336367964011565112295964484811430669641815925818835053055490885085853654778136103824966758675821057549975937592856129694762560934017785274260205468507090284255518530529761769087664611456726732576128869513099685939756834455742161305429866664753218053766044710117037434714280978513083741639628875055125895111206176902719499565349374785966983807353761420341050672147715462233851653816877787102753423978336486472476915615332323558377811050884533447911863908668594136913314736657102511382723094899665161289679857979877134339287053669402193568508128569314404270125474623898899319686003083745262800349203719925961298222386541143062576628379714907840229391512104558566791758578073940498246837177798773042561176453797781926875957352252016622642672041455724152316199001489434008181697424062748241449382681414180177349611493971362599079822633899098579987081755811428053272040889627455673980554744636992890816228642399690084802914619970988983481902933449725537277197059409197932178216964483404227029538210741805889199231559532976180886948066335270694293185221226804713975199144692044490324748692489549051868122638367711678372534800474553471079089287405612527177930433882142169261536230926856259055490860453317950599911087244300716868341468493223379946591092832632141307490161429992179787056077251862180877818036694516110732913706916682428575567953911159371481872485616093183016808900291601669772169246777452793891038854445576760007617620983291308961025642113399913354549984487886254139330072257376525143285331953005649396579607148467517995998529139696135239729976856109870429212263856306568713635769796295500706138810668606438040222195279127249972713310955074241140963362097804688727112425107003546149702489454381275989078708236485039191171993994388642691112374158372179835659221919338694540948689438186696934563558517874209126450158896478918722478928745372256554766567905636934154741763781133192773454607228644707963217091817588980559585199752381728915822520681917072109950458733613320674584094739556046213128447897042879155664773693513671206772987430981786284309582951681510067947428309581754759179805284400191440471473788397385837919154822064562547184718115375440664078325820828606537857041481689780622196270095674949149359276857703463989356120128389994692205329184554406935709188851056077835960392315166691304440955375111791559038917876098404992452398161733385900025139309314695341143791497607925032932562604014879322145882856409845694868674193790558055099863982831199749841294501014000226046930668607258572267796824519817790744415531308641565024052737929959805832352535253975164406328704641303716973050039644260443821705386701005991750837219118793556463519121692527377146745449294658926942229175884289359123128219887955267219655002735524948722822194929692664927921711863083689449754349146301364809051869242605359865651435042833621375931875328870635849563557848995709211533386730895599782172935834813639507204086021922864943002391233732071778122872273795675450834897988379070383443294464788285295671909495448463832010371682392327087980682720803518685399447429844667960560130794584002894266238662522587796203757215104682809070016706585316057275220572902127697705908415906683332433758890199014087940569498815348243656934735158937905641546926574687400173579687674072006840204777982931556754198809456263145238962087126164737424011094721399682498560, - 70134924781646999833021189313838172544707064756715947071648475434496588391169992713031496633226119604871703233207357705859569986210646623626922514327847578567654818351169037125410748868651782735262919517975155359443855248591839423802144752510356152848179385522530059230301944591916905222375413307006320420631531927265250749589547119593617308387166905188507688711509619030109278816146154144846045094502784617231777635568471973494590889700023390051051236789491258023430492179855620232377793356029529111199873212396137729884027448256837472549228861578648407622527447625845304036733094560493602235610605831475123743171158851943563186407163969067008640378913520391377111875195073996641466763613592455691173243541633762351099473663471090538993156346089549702278175031586504974939525113180482453772163021907541830680978307596692504085643537637809878780240644389807949211083459216483931526606991133942035662518126721262252831349548283000849260970269219798373009990174823409094845886286828447269317229758586574707558050765835601110447459756762363797260127292378258629674235537254180388274154970059286609207691161096485620909490355031117079633651326362626565250259974518775630067753330636696512452228254436152543257047832807694893765335501231976388959643265101086959149117177499656155707667195401841778651322733523650691503537595908350279428075571722996083721686084376771812866659905107097511731264733205312388077629920131230451948275557467703060508059024631380137941844333792170375307687443271866227865513767530302848510054648239245109704440383925305093611286410868168546694604637558236636519819910947969692232904340118275376696369082268299511634279060672407317297159226364283987289398622061708807565643595773818007307816824063204772501906712842393493516920172288429544521304641525387050634889080416824276848488231785027155387294134415262099861037099023382648568197545053472272312579263078360854913047678670234379217008822573114070975324653472523566184043806466202677930565986119330615576826680252327012528179008843482950058974209304909713251558464134926135273398737068477554404379944358975968923156353051513716305213415102681985556043038022015659600174399464163931219801008624046738346104005065704769833848438300353663010634846227117476345831077671591211277208283229668019034089036325923252167087097373258335764864378686606494908686956347000687356101707948806247767281709048775437095618821135038284030077980329002061161100348612430077637231213957650107935441246304443546571014047855743280294164662400627453492167963299721463547124428144858059923641805929201349727859382812089763764073161446457037313892316601661415512037796807565590989722481569443954355418704952655109121311584298560666595512414608921105364848420707540762362700676139721001359433521408675443824281704110549211284946221619095907502929859092070749256466560227831930870127030855076425777077273267261091634251121230759519546240198775908387815361741914277834341587480682446169764398100336868829260527034663456557273477137377055691438329681116396987375544021903675962705006293476202832313690958900410052105023719267128715450488484873557523548455761277932356502886124690551051177642030373628252155737953327993265870187417562866253487820948362545733378159171665590115044304335071286027575337731650270726463332304691756309426236677648661435495114458334210382161750214307771870034096744559800525348738679426229339504674641020377251732396816262283072464401732647648408285243183374657597940414992306832187954073843855544872624499884485437559100687356163527224575615567713790248444695343555850083731441379967612088345660708698026767943468027862795635580716140853819648769545789496928003634003915184437071108186260262255530990542142020163208693835208135436622092382426826628394955388283888072833871243745786277776269977962021985449079308824722975510876033147364371492670714012580060621007121336255974810090055268504913349768858750935517228341336054220931526705738711095642021319761163957504546879670510443124390800379923165656433531245964175110558994345614185827537471965741385846861697265519293038218666727427913493307850145330365188504918379234474597397284693947365859911151208160356810427372157003843883210552821899755478399598177956018093709668980340062352781343686424617793122689404599734056196081368610517793180256611170301446599468765288240339685046085978452063009563508893386462873136009025854373621494321027874632400392215846926121312248886710586145010423937077806608630677236269078674281747745840073274056786386673168026246717702043559836056616997075469420383985769577342373902242095655273628172615627315291636624109706763354713742979538083421307373994183423647280204350314642443592219055723130876823984414068418591664478830910776831254808101619734166675094506800496931730469049431843881116755225834480823403811026371190079409801772214369255361954176717260778425985207584829722493513603968569273655174550324359598520381558962173657378168971032997048118240275928407803367831451591481706647667616861231717017097656701065390372072355752712888445603117898636217510065811109486889422697019658763315872804742825811401566385959058342941063433728178153843200728431373121226190885529366432203378037997643842019367101374888284792762946322981048428516181334151223332127041147102116707934184669478765258321542438789582400922684633370068142493019395315381938314822257202462172834601410290472772554357503037693447678541938483011823496503445252817483975087365622117643436716461291408957144533379288424185965388069105662868448585281176566201782675801364008034568716490959773429129821486933811184264012218348649015594347826757206609668842461109893224164375170071703335726676848012819463480952272021095390911468870936119937335792742018970391511958687933664118752315323579338600521849375779384191821022297524582286426694774345852449174192257957630316374539200840804761768565710901973309880800792097408132078433152197289364570997726101909635218632233152634652176158700524796504912962110852452289156811915101216163931293183176549937959782483505633021427016244728102269410495159961710298901241374947944167117863168092762786740807520276526557526575892880024986470050340433953097793236373609313116845344602445521544086169840410910009507890218237028034123535857110085853273297551681326404401362736614240247145656176258263670394506727527099060769300417207284418081451367591567608225778536910790982403198278359118527484738467889654030078617031185786122806201061358492181650316275363308618393359021052347121263737264556537166902696738875943258334765063518103580157056053990013076670756582079509450294701129463488352699518141033062465816252535113117811720014782095485103984460468588742971331548875247265625116048202612632003917727773063634710412658401895685415234687635006836021169360862772192653956177642412656944258298535997690897110901260353511918268898034363781133492293310991233026812889653472805470484976208504678475155965135733707039687535501514923145497102339789962201857410426839715025467001845602900724299796068153813837437797802588882744807215723424148842651457866913243135937671663834184207522011663154881393130785721326196268282069530319538780067948564299803034155412214802003152592621593107888988597214512573484783001442385149651634527502209626996613605695325756263105913645513041929990449268567739241688866662998924825063386611000005255127849911500683323734286683335837348782464819328390086390825178583408580042169529236224119835797282023241292114621816986772633264599400465684938271551193392892424186313991044180252313072199661666648998438639006288489810201806256980902309952876670153352367768807969197582774783529511181968594259136396416105915485117928594933449241615985320277722818976692153378175431934157002502383198629692874588006327232706006716689418331649710281518838980154350969160282928884450225075199145715451585345140231387623938677306310354785374855370282327893015078039206689942236173560914648686239790556383221171595284356268840203387876389279552563725789430763256194829515529582863987407606666663238387163955449378589377207107705403340045573634544889295359295978816686613578948360925238400300105947891046293668984482274613378576148157919698775408648070017571143685279313390236250186070994240142543028834231485125779292224820850073796771612402935948823778558594205741362874555558145371128739438222387091790503313868412974093869011367221934128870232315657961463649698296095121912875202950530624660673080927459825123277307064559797852269995985751848109970807762911429021732978345470363890701171486901330220482944315660924079134907152199395658545635798287256984435383458415767511051612820533616620269460586077781821665583256895912988883081548249480494484023659964858687370424471041905831194225086018211107694915158338441412002499830563079026382681375230238075321040892356260006831325439259592674501514205653233087602468813488598380823408622793046735881810467911944632165674097982724351716923745355864613180900544664276845555329507598748681018563782375706356009221326124327146602239987422901743847620383326439310929118901155358828532529985065179044060952719394358642245796217095452733055933628056992357393142118983775161446591159904462662923711044685306375530067038339090647440059253998658301274392995208367642651818961719229521308727611060227758946585800890136725784481886466443682491185732162243607215358334025003493790969586281407146689815498323490357903360, - 36386820957139048437286008080173244299284575653014862397427897018941558326067057661521144572845006511193021642146865062028674071766495391794618432083173671202681414055980778149095600596429175615031293348066862560147055280311444176710919287003449502067404782917754626461142820720106931640997267532366171840768486242430688849030509154274204316284550467734171451118410237241675574343211463319437473895095934118625218578642686371414236410438117072688170902528268944557071250150906431046839526974778103838334282478526679801223800918367567835962869796916478113398498846519120477569802128946407427359242994340071316420661697795687430453871519655966708222748260437170466747303185604304370237727377080544632377566575162340655489648950882266491325392486418772839918594282164245951916870952018825638912401660114692683732847085236542413144347638206301361585451289445909225189866446781093603723163049959189326403851700791645065824388442801242961982897871450519912164310967402270807108100970039587443495143227075448577408728802700745371135188180384537494740178092848602988205752578148573792672306453190034471263969041394116803937938762726748712114842933857109169403117618971028179722334293756550133355466841777608592171921703802854373240512598436101556542582138421354667045199037161674524290141555751703909738852686318173422655477249474409903720358634016467245749135762471212984540486543387785880255512605017311979805829477175447349067037922456503804963252332479572125518059561136790810597715909767608772987054314326651978072999795078565142618697085028884756140104234744350034647250947810540442124444828057766559833515972070022617953316029085880640740099695497270895145695113713693744476311899297300314108975847267521965121124844169184834661786695739773342957816112754929814826169647627461822089102415437481198173213572386235322837621657855584719128301141414736992525870588485605679564749061193631409682537265835247811732510396218744822033707060481385327492946291341641219857144654332345872767234017869674852692724143247693626416193239553513621488704690536674341544032236614939399490687145408845025381252039815314532115007986699255274340793845258357993751621080128480307106854680543654636278602958567980306510260246579300213344219171283928620874250342933351939840516592073729876911859568122020606062313621808611081149088531725240745817078003249089792330912588080649275691676488382864602275402817103217754387344364591669348824578750260465544735454928886362553091230337094399364146554391938336953059845499560430393038091917666826248394261763480395365322483545760847205807110007628454811591025131248022553310105269630453049728229090063380730599034143539168047397148019357449618518062617344572607800705879208406794206398990494235953133095096857847830398868699867667255592849469764345321566892972331324509071967366547828967189449464170736431660582782740255301924204881109621498757942998191974337546272304846914014508803668282733497055083359504361780653728559984571492755537492474854893762660662777663110235259510479621775224869871403002269051627917037321865424287914330412063500286812126574002253541821882950597199720166263018215403442470808519812239730436509983915298897963714218312166107845548884049542262053242371985438269840978160331103067106816726999720653154774635138280454677091361739678567868625253700262525742073909889072551525517002610696632871144847164966506316097545114007563203451670510084759790408127307401182068111975090988540810614979307918597311045373917787961133604576470567188664411640130176499192787954069635314008171723268845897062881618089051838270733094019096835689045407508158899760010293863498076440838023051368973464103665355111679718438434690174952627948194732426187885017124267318074815793359648179535312646923458638048649769025410764612006799563038733822375293656336858566229280140041701158248394124408246660627347785314143940871110425979569753712283403435033168448335944569423560310274046851951747198948306082842501619201241332980251935188282192373337797462003460918427029329160609820283085390034876595133908578641304779041236248056564711279120400174607534898101395499846691734114463475044028686635440147248122522039515128760791462013167727737705729776412961931864240266081533285666672063969546268098663701548665145735042643317090728602434675255291008783416158513521668449395086909744763457664095738267261958546506718088789637814584116519675800026168829961995345399125764544373125460015092076730276374417268954308039118265236601134479219576371340330664485303200298335399298255826689268840017349255189679735674240539027756504634104163680152430176406262449708194045617619115425796782296298189000176660482932244999171525200041577478047529297501921156112409107827382277744391765444080600256199416376885199204128375769523329757394461611072496205128562682731418057826783168878885965233256191928633004662815004699434628647958289086999370288653586928124489677720591244436202241713824372772778458925194273397171148846371413639926770884326138708990796945741671856087453721023881132880930885631837530722046661203191755522251579123278299695633918238623568296959150397823269071054141571885953589847936325227098218688002847097483513041846055399590480408673177463149994916469077922483428240234803113311819090687532640849154536160974191310253360815549128954814782080980972207652445852462448399555583695901688950393989592282547061452752096076623785147680178580086823959783510242160748849390786937310916929901284559928542776088609781505998470297201287488217621056185181565705203597826442665067548140859259693624259239779525874197870027821976184019760432813875706971992550387055530285675855418825197918769240991685405307493810755853660339436443523035812250979053935542365397528937238215594568664734279472259542870820295698236457365796047480543303198605491186043746321796591794591103790104089146577843472322271668911292351632526514666586255152613226921838495269238199647348211299454443311511056511168335299668621730209726578524847192260545192917680088972589615958064207612106062636948635550113658840536972816381112736303186145765116805833908471632921140030997789750178230764263053521110592262383483665910129006554662061298661290888359958774542536556372689876573545252135683957768080335413482763905622209252242348940800412573714381118934828315483477566212719885759936655405882569780870261911106603634447994111698533999493962741139159498632978606278542382231453039413677768670227238293758043076326691390531588682805935358532804439475798201211219748824866219432439079129520761911004340252226144695892178894949009084308711923128439703795257586034460039910540267585652919693620770788205163966515591240872299807533252213655905105502900354753609067572920853418757432638633293184533876883437077405966915480862889878994771070855820152907436822138985656937374674342087624629836234825016373931152422595536602218671474580716061741870991845526110745423582301800213950696240622529579006319706766421367918430488743424795295117268476673605558616569694682477106798135169329801944865452538792486235362677534950995368887880176340567083203499731860033285344162862047459018776682539997189191437380372039114466131145306622867607040588746396100717170302689206621099109388499210722219260182743277405725765337391408216363950983123410580076474188968843386203819622130916901250389903165455476572806631509382849537400451254131664679568241896780685597810075570975075790037126948224857017886360669614106215944724147117925257729940203815943108209618681938153758380888570711394277942017239786913355827242035888521276526152242195934252065775003551590250669073719394929863964652441189189235308239912191762841323843798268297613902582353282110718760002046718515310485990318636849923527394450115143839093575076503503061208390341687209876299070354088879658920650537331465647164333777466969550408114898586022020419113152922554627474611025455767722086444649395004602946761651580065531448185559424616610771101708474710566893742186237310136713417615979454635886495311099259443081321860211428688853112964846657338012248820566134357150093426580325117720849455888356333841516172466131156739516983251918133460640696178393468378594221087034777595717476066295422689169833697651473410346429217595679584675798611971107237294703370179179170106735115460796642503333787642212813445241685065048952513726360700253193718896800186622895492503963206108844824291646512206660073390505210444889386700869518427361865835850874183457834633722913383723391229300463940255661766100828970309422174944411876507463272182824429914441770634850327181652875739637599937005836901576474752155801606996040282491562910548235784129660011103208011586049952333403497455539391220654915221734616670733954702703827602250248351732999081693273281996544877996532728889809693646047425500937812274722077032792179433594629912421558794759258594562816938646791277480556305130768931169850241856474363617941700614492059308361130576867013675082978815363101374247672423692436109933717430132694683630587778819167971234990141130545138001801085762099678342143006272371370489708183419084588719345829398750602490923989728957657910831353403495542641995393338879788993697820583772940429290182830932513550891607223362064262629081011447325811561583545573786677968676112069170607484313524577667243753068707042817189702854863981933296705288494651710594413176616876240796160485721622488320005850005504, - 17605462168795504821367997568581563407648860338923928542370230742608593326494428659326464327158110183180477843085593367292389759144024952418905559307103160825561701849055977959375961280695968608731487686518389466804559951171273810399978006203851322761572392918206651736021732415739450638965360808206215770510802457618902061676517747201624099915950721446381593634462463443862211142741840394590548923652524010916363227214468306876543987441939624950565865005011569003797146784771258657429251840294604023053677482359788769259816653774203463912415357470458136052460625643889001905315586147614632136540418080360436341275453937972065626212251463742093126753905559754270628477374388318994424968191326111819582271782938244237268873681930093659669581089934906604685994586595231040628690196175768941794044837462060125342253205841501129146623706255027725822707651472435752475691081739524949033662674067755674356150509276842221922888845566020454439177988124145875024133837428667370923714827522409995264089309759593488107768752593564221132096995942935058996328426396640532375766843410642123245104689225796430867571969537457303185002698434126247803880214367418948070273019892134124069437840624623216147788434882170830467570322686477209249420877276972458911208203756085545303251906075402177235525917929617299031702050402322057635472939286726654997840550314954796393229435462134253629306347498218489148870202065008206798098049694742401272330316761575762248068555809463371552671716474870969247706247568672089509001587515670536783195011112091644059632325345889451086396442750287208199016962216749174215834427811573118157556616463910637275261583052753355804537954430887213430571556632314297454370068890487244969989346776449706552181104486063940500227641561347786141815919350664053054607844213884179112978143685714221268639889148446113518997489328785527269530911003899078969643179571112100124223506388380651967205031798525124380953108700164524483594505524600594499500625606870940451548083251360239647713248901086995164601971848755912405037507192109816371261286942513554473285422078895431029204362056363713878675135199753014320147545330674691413946025068707034249446942925325714872795017610477927571293669675772685134340061673762669702266041275521826232565203604723523192232302250667536178562508818018440997924091668718233782503620228839956124266569916895441554822659612163452335430058656079302547029040737786294004227553492959113020539089621671459921445443939457435259702342167255827271822300494587169957491031493387700671533363721460853496315902256473976199439953509975042911697949661017664851030604590181070047346706447678229732144509834629005120270245314781920718153095149920446774959056817033012197197578615747662284692005157666242322579520535270887885335140182772510743129897027227627640321416313506157288530583950500247957481017083622878816222439452796276773919038877985396712744689279198212396782958319387402768764417257948421743629873673417518162540559174508456173440400607517716114952200690973033504157834289985885660065734959730748725944668833382934715681313319960176014065466055167924221450038491603047905000192444965124197822388353650292416716830266716727453155070827992140234349365503000144126018939458726100008766625913135073557054615140338093276280417066854474908646041361540634905798361866715040275952257545189477958609420022619389993760569877434873476443486240534457888257189787477779670397893673967809793614702291307515586450445481065217841918399704412175317746187674965185651659800629026227656372732026222349634764995877184410873192951422989340851915675781528951462319398816864351550743726225126216286857177379436027039828448595341724848458302420978412331956829549186753802016519571225614219619040727321982314046357479814797378584401489129334644998169485656025727115776958198850236914947298483296342333941331428466715824085306552114106221776224389347620920691133702777232235392384116445830959838139458707960833119134826343989868988344194717324341063950427289765522658382181164023555146948215328600733797599269563960134397163392878860192449864919711572232096994062270269061750527806027213935416097424707942884047241196822442886262806079111199598998331464489173983808357460222170439548187164451882558597082198765086718159403505706106206064039651599323341480445916199432740226079667062774718461548159577059707720795359393561984271737001887036316569336722267745644135984135166391260268680851735944662326530711051259057665259344719545989616419223670681275436502080332488200607945429958272702369342267639800413852913838926829784570618857733978186871526820295909420141261361104401714769229206306997108794236862019073493669064426635463286462472224391816686768140703251273323223238673314061866302886517081748314229509900760685870557322102409401456537416091368435701334283004798957198458922420664415585526864329451554075074615641944360382538109616734613782907685956777002462647104411106038146441192363776907078422759915944646953752060597010848401754033851114126703490399258068415502394744101608371376423683636445164179745421000460213322330259710961810883820857384704690248117484072417218767695656928224873467600915669283386592276451326166029968935333951924357255988798275652913530654950970005699384347408104627553631012103797415387560706158914797697149329146018676227241412307948365952119630206616638409731559412643238271905873518596739771526597186219740149872937101510109245566706679359611601958267378752274137680943057476432748955697532128010453052150769956324256187427571696305766955013592782570515776108331141244154100542142900649489871456568773649382971641445453821284271799691928071420794206790175923222254462115119089434706534702617723550200165902275555161400239652005284904145484587018838291747145610725661919578287841862740469649694240243831983133590346703616007163305747651224923541746877219370797301200406656867479323405448974743768563859230561147485210610878661344266378184615926557648116673182847481363701937767745092251597088033925855122026218855924209731603228328731804496148900663044355379066968260054468026600751185417646756512275398342207830874326153001780557042747743118790931398905222841546910116298095393185264651243908476637319395000256641514469752358501473350440150582227323641947196616121292706105145334823829966912984564096270578948307239000930167603853069800252165095375114834362434518530966301318111133307414406916578843349153452611850775601021722525689647902989352474510038342022430752753634064936557497630262668818510929846648046698047992553043173605033828150287349088613801917944808865504414365977909955269452716251691305821874595403041956003984660318223109461020493258015801759666308822944483320066689737504684014519790332293157347193889378038308224459587263616772613249433254708788504496778969602472616888236123175769451582551453314269625773148475067720998700819842437164514012904847805253452621861567124631850037989349171565318251838026154613803509592336652618645403196984281342355781133076283732888214156250114058684169041097838128534620143580027342176485855433410961174413698561198897079497291816865243659502852687300820943634856134442952375706287255487412129682537910764267224812706075485163096508102073268606929626305814011617107781438802909128693846049469100228535375282457677858012834552926866026271312481263400327988637023832684959813902586314811152806185454735099603087467050522363075424072726935589328376219219723375260758904514623054559186261047533675048189788173141093410668980217940268172414488009339885583823772326815155638198520900105661015396062329377991203880898341460591346929914705346352641046554201046122753251577473649591743464767560389695145809315272726331040955632076630920555142267241777883141902803971987137871884044134202344462850074632350634014129643552890355610896335169961883261367909149068758218184496245518777132935875021150080293031762352401927914140434935323811658665525184748468274138395952543173456961820562647885699124393966773456130090376752553098568507073179358199527933117985442127754430918011623938684337541952457152245267453967402185280290090996140985116930840666271155852676308842590923123124966963338352944244192015846334580426223443383526030747739865330271055153718612881511526885778632639151792320291390155921718308715871501166789478359246305874293044938173868302866512168814310525118667996246009239213353679294433950060485133629632599504695241353919112802679890931623803328328236511738206441307087076400576115460242154364987102395104324912029596737914770102280205956764981240159939709313665999095839376732180273487422260113200361878935289158589408976808389343794035502991751269564925617567552869785284840124941125520196730146044809226807213464054142497446235190628432540957313709886961688706742688102179178089946186001969405006239585219988114088264263474924257071529722540558790991500282013968619675062657369883334169329903857378103253880820032935249233590264111814321883966693165756980341657572198193459723701882179832973047582035598127352636991539357022465528165467107053313320231515549850153380625808964899872431419394534852792647022630289927674360798253762757121141198072465390421270877339759058169528113548207120348530558441384118483527113010494108925748562637751263218788227382234232482819445538413172387448602773587395796769730966944888880468412290669003285452404209704279742309466112, - 7954169196714702612785223322438658837082565402597468690277079384880355486149045626883113799502132906390067193444562510967713586924707717847923569649010928467277722695184616545424047510099608854929599402881041784156972265121178667812772528562703781473244618962771032743418080616721322434298060268328442120401064307085807238146355794545205271064737807308558593613912682158063245725013449126235139954701548408858234419793921362296394001481664056299402843619234834833015912032922134478525023220636529851933038124869793211952691456782800450315212176078650868728178650701659730813175671366186561020011593189450027413379363899555660260202994089473017152585881907646265174767674263288852269030748306832350609497950231258612714419849900501575123619490333781665010472188695500327284582980996524251725036522334020681583153356792297371567291439842820989872428299112623740936900429241955095000336426260692919068303437696251874066090142310588693249813243251279374182935132438300980684842915077135749745039962625541846507985604518395678527682651347034889097068764150696242544399300199106748647281198877158624316952817967570679210809940181000624384724661594785302564434385785972662218550120448529747428002238462506016873191369045903862873194502550145268827602817666912079407793568739584417826868234894421125513092954330002891207110736806474440128173313357376918506341087949448336407376698834310182732935278215814282775122919884339961935136983521449757572462089095424036942228427700153531619368878787765993911383476552641746483035604584692909460990785616573814322076868956953060486652066850271365782309667020959055543944102116337079733779776345665873533984890939070337028182260683177116931053484565408660475234023927880452781909785599162219228260689960400365361274249651845753393667074809957287214618100005446658906122950864154790613716180093258877913304035872012459759381053777720747563073028889813075643875374990981862684248921589219608704551576541003307551132270293550222317187977616620769291976155844991604000376189992708310127396893289765266197148860893734555557739475421423262527034616758604645551962309388930037010609704851455950816593602319470848523415761960890932430226297761540836171805005717626888667397620726239976313806526283155184005843813076571427003804090225123845262119166665850541347621540147439804913394238861146885451802917969082747807983927092711741923772162513397623974107988385815580390301338736760426415609905486091053911608499549979508059280260323575612723619815586783110425456024723187958314793827484733431125234783271819492515412956830757399519581940096368203792348622396599357540685896479184717270939658228357938784695613090522488414157135108492828751082688073418047566826038074433332018892580033131959005117168581723441717019184747659407324171047026574004962678784322106884398582732134208115125626180540534303726662558497990819451994230578998166416954386212425140247990507998107407742135638198118097402022407638539818623179420843355026366848961357399309578051808854198837046582910555878603405248343342399442442373839578864723292678141303544586777206544816075898137516076768406925812309445208318150186452186744245980520426634432534583133325051596043161853932251983501921933678508622752301599585805894992726990941751422889753994912604161052944796265908200156665772591884287972912287706477417842387050489594770114847374878819542268642886813591624731629053810888284914282522350000680334315514245163331322239905244802740369804408242439311712498757351198781607527477033694257313056384358077244983247668561061519677112664871753580599137150169239513546409501309652685745116514869899170377946089701741690833942386602275480462443084123950179116809416369205854112035799155938564237745404666415080051825227322462250736084260008905563316621331205495417962206820126293913829333364803927156969610009215140516234688345368919314896973300663035551837815786454566233571189165194781253043682568118695605749906955592139660546553025161410296880844334891457241508849199210108335407269982892234521645617710560879786146844365158606511746988551644088356547018876319974802363889394862716495574457246345684036488448869899290590427137862553644612172048982785343506049555159795067294067689640466574833088207556494151559869606699423301310190260875111968047892224594046343270239188526512622621773610520878142304374975065335477686294517084374875388263593424350984271555493126826258848021902667367796989168219605345558180292512721139316886937945543719387239635139827724240934059582324504672440662505473254462775987737753657432306482028090159384735159831522604956734673982433446474915765271027542510410772747962887255825419384827200371789023075952947699384468369236982864849851272958484515038600087525368170892711456178417536004084786861551029587785525768708243986480552554635403761926214500102086757217584745445050576424849020269062374648244214498460954733008779432871698599306010901956792597136709734392484998608888951237582402356553410463811453914728346951082280893651188309094277035756275711610545633947315627488549488479822803887263828410920322254802957141456175413239369293513590042160757624886048540043608323923915493645381095183235697124754528059779428373867878629295205230045926605126480992994645632897771618921576968060179957380371133866747081498348362365166648624400210080881206686261259676941138372842394273327370284448041998276635003436453253536871784256500880962619330420506878860083861341496614114227687516747988133966836634869250663917872467322902771008693312367627610769588616069340300168941965260345040403126810554041221170294137599085821916688133595505598001614722755041760985243384752146411670952827719083207770795416179448912738718101681234457678576995841098864305815943704356844367958097435655736232117021785055422506512921336079615374471043845370942661488649182882551463997283310884692018371487040053599051339378509170564240588085680403772892413481098404838472501278972323172044129906911204900572294205339293556673646846782649767722406828094059537256566745196569563820230639166640587307831969185010585690157861383605774421720181571164232017164798285630696926615642624499936067528658500779938540552361279350388066207749770066852427965361133467701653239727897980518352044846540601757501776911321380013148208990444401398827673032085163632552181810659277928250808959718572430295489998325275671601331908198074218736815170364665044601980837653955540470374627606572473378710106338109412636870107871760592645035761537088419603530719834796572767933864149962380441584215264535781682113443006580757447328866594298000252948089250846540235331297070994081828538629632526083569904165221408599420687052563623986862886041854708925116378395407171436091269002685731117845406516632504795587411064329008412196147161240460268401236458685695724089775811266600123347512178290226812947955550262422413857026039824518594803933954344866026772013212154597121181387501807848747241316924775157003781415272223279998330145927875899074579234143099325893978895667100728213612065484997309809844788654929215544524668895078361600812990125555547425478629316037890676392099731914137706826203192863120896075097338982461197149100064991553833797104254983247089377117849836421729597109176886227266040486048282078543421284532028595537619687853617201983606879727211753895284136175748386950069719815565708931063278728560787070949105744596813091186347908698338371990551396235094693102083762752163152684648582870935101846302208493174971040616880891769686998353614560067796293809155087267471933264155892795597940875980761180090126754815516957458280416123750769795133716627003954085677120701037893182763431546518915002054391843127476181701956480588087107064551641661125005856790439496973895865533822872939872129096824460162990984697809960202270392193030477363632552582701152630229205970395434675869482401058236873317725914494724335426158427697305727210919547077260260038300551774454084581867598416651169001297686374009291425405863611492663634370925530681581135757348191246457712526875975906609843180634904078102283995080585792588170431606501902074859767888137943507995773555416579649486275022439081415471911405440997564354668000059132231501415273917318264942029150495573862593685779765646091109271178244298456654678298077009594567644768280645300844048515894206960402599246483022138126155830771673386083338952817313310200206567032070929455449173615577965084845925368505077457022809899111502498491630725392510409384856447192830038661916425352568587877157464298573618858027066490266787455435176956237765967375494280722823624126651797135410835250529429262433018515167184751934609223142115295526916576961346075348729104532363358934165443814254987839154800571013912850416097924403918291256881335750617419321307670403284801015852953399984594914535049161329256254532741377689164493661911720680856286821825221959861668279755799416061252405574625084446027377078193228633797408221810172656446843447428753393499006281626117552267967851002559233611489885470837836455739394261524258823016964423463873902577242740870219938998541024155963502680519262599252231358598308690740424348889544779029895773023930141189295627634045180734783620477325901165395630689476470964100865688008497529070241500379873353875540950631514168394686018472411883290730427787164717197450150877927878026902286197808974266368, - 3359733956297521211819110566850501280955338771346370457979268475029104433417094815787044357946020520858503577983595636975727092092882773275477407458141209003248408815061796096493005201831610807202639884046030908449888480673856333411537944764735119166219074165166772588761194534375095686595849486597392182959912045931060363972313987728651668769426950384116414778080571208701135398473389542095407997271348409632722291564577446485297201772286104539744001259252539437537921071588239092428628253549223523030265946126609861861510064408331685400818641226248900011985576243274710341472947125003258618871510821687257816652578470175327749100464474220245877726043350243365424012350059935677606211513711838774573660024406422165384470863354834373834993033452782022037227995879433955081747567735370313603098267556377716982373748043198249274025936696863347490490392208167738396696302633977177783782635425914703324764003894262374074799193998881049297571118876169496534485970336454765074437167464031843114768262877465861605975826089989529649219437232798049798889455502332416512096571237900048028962605642355362702983898846422956834017449228554518105524197210227176771129207102080749868777029197897826770377395869239364387169877598027699616716295639523745181367604130211382556337167757432356775900717776747465317473863378478560308186154201265688239361911041100249528412706527083396976748862426424223522009177607438049214113649753904337076771504342231534302927867140347037905555811333146681579515653206195765174980592626880659013113935751789164063814677651459169692110549398719228306730979577266911019694512220289065809946165862896865412194225305327683512100712905673410949704846142844178797334532867570323034052788184462546443403786311972384035460513988324544493598477519567603418118034292949474954990187329219064311226298024263318769752454147291109158929139101948083204823417554445945249600964975337146302198370328430664965847985022922124121712712792312093866138296063112241049065236990141421224216807357272045777482066693924035766461160684993107477957496675192389886797258365562467969846846755583588928901200245110576182126284745784354924828388492313989095490292856499550722609047491361759840405097899542613854481566527771491283154784138436061746704746393539276502223471642297743810679367595195119765046249622146121656021758292609653956885101806510231404314274356385661106800707528060208709177744356953277310494564322879574013594605660502225242523986620270598279319310148208866677470981048096821370581046249337985499786586460277936338436592127592567250227236354685500682903955193711976437766186032202076063471298592424358220009879753131984769340266225082865629026570740183064729545264235686314252495104805574400214342305008218319770339572313351751974077596636152332371918846885444150389986904594453728687771617246645512375693777877421253165954099869787558110492673255291552960034475533692223182041941180427838648787546884326615841758760773585434870639577792194212761269497273477564828362694262681750227860442727905661529119440198832379055604797067851080659686226183907348975478971647818422074990424149478456934873361178054318178066520015603912299373629487702157691133061292182043525098587311854876374689123918749506129775059558331121615425416068875865377106225748233332017474564949724630677679465771521069794650837120976198766439032066310850063452070212395776068551869771211746780678579483614039431104579443788931646802070505405681901264101247264988596068468034409496995275282367075649787181923809927298632289343440587960937383458631015485031704413240735417934799764987342396071418395243580785383268148475328224894562503903784058541688969757278571514678870942275998208597177284089745200058600862155841994233583610786345053343087301983239252444666011966312030384162264240788401721898415734752069318547921180912348412228320048939687035871315229856195938749548041455839676027200181477626830553139422144402662215422298398251228584450093298619857647744881035948773388318471497521893532180134811221347883712745510438995690252014398292463308908339206447365544184545174188005507492584265341077042357352933406286358117698090929580738120485667026306681688875344320844011087527571304900980842960061304837246766375463439922314425347857340629977828287385373900846140495331795955925471381506919924878740228959755186314956869938145712792461099897605249667595661197390268462024627558052436460833952378625902986828877859340961446861099323362808938203343077800819072927929163468301327912581043959827065129208894179839819601280090441405250183211553809672406070910488127669872958919585400402215887079941814254006601001782376054346750820800016135477275176440598188752186814827979400435913103125213936017841447337483265725052204667568388857000877536029162105816018677987915203911337936196452955856381931049174488551111727449109792322027765437686601223851391151086088572035224557430882436203751270651229900493551543089536892595136165387146211563966752592724227269511676792291394830651335677947246221571268705356218108941082862623339421519213510603194020915773979947832619909167735790903667415077636679810315093055691797878982223189363904878575596163332585842277565184594023245219883647495553671030823433960384409361971172531217957732198238577145849420316934986022713576097813011404043440951721421541820979533490458826137226603522115668202272798995438552759405125417533519875126011710487162961662835636506847094853230251546315104818523044314255324717879550710412512381007985196477245448479648758997829157584252537435857482452736513819655393071817656014181774022197642460280712713500463069923204559635147148248661328213724547936727047419393200232968167039758368009070459707737961148056837540951694967557961770618618174760268776510843612069527008571954101214854398925334549326231025725695273988592660091904705838508548753422181483038425094179803623093641653082694972297833258596297626526742903625674887346553645327748841200872327870796372307446063190370488453059318532321681904289059332935176528986201473117708098650959249884395605972199232533857148113892997233913338777176331365093026497855150310250130468715563469133067912887546284931629789201047336286689840524598551798422389980306744473498318662992770024923552744587946175670893154697597384272975183338092442447280064328669485842150630833498827935230046460116646347751023413004723496686029879571251510604576333449346296644671541133527568362798703529041416824299587816009949102336104579301042719853017681510492696365753741302579634533401061638843188685874994563475648682991814645473248727073626426288115491669285232125799013765600546419306507379672075248948961079088154457447672219791404701887587576981444364431008433813765720127667382955531527214311767344566113957974372280230803533500043590906716287813468240670982830311036183790435296343487780588515380972618503882930611736193350641714286438947203166137633016943745400217521609123924837293386989369184044469540774563279120646529782426527099120679052447836032527850490642093084199055197016459237579688535059453685816156125807243072193977719543975659393024715804767307485357805759229243313394938470196295696064094983868261435127882553888571764894081491604074768145551861676742816791507812737654180452586095660403012537317608265762911295959350877059954078649733419653143781454426002690120642173876622599028025682624515098607563484400709432396483540770389515800439669849664599560623362171910482189195504725635222944968305113108588227608389661217260339959840266062837689935874846083750856969511339453365497251510831585449240819068177670902640010277767099459130358668051313317786249979640855888445165137737588730381580691258347215554485045837891570391204423304019057050100988969960754467834814948826104444432778665492796861114662321968592402210138435598255797447973387471855998521998834830855305515441278008379379015102992888731025349396461555839406170233806017545013479264235586949859981844253168577637729907091187001269317825955824225137649959151054625067716121299774479200602370035167610397378876297432529355162965200802424755024932397735715909784988972825657091531610963709213373040463646417517342688943021526092208971315593682940248070692667762146734645085283433608793616224779117290671645448095905087125193599503228409491407818811300817760593678456587351750294189701752200819156979667664002521851587503426189346077064369806519672821386237131352740363300399313801541064733606943230800817708421451351782296018593744160723615971691600696753247175127863577029741786944292076969378470100759297463865873500633077761564216100992395242239647726716694152824734592315363690922565215493701277110824030923375576769231471782716797085878115267420336572808666406594072346560641528055592978891648362469553346123999721941649964221679590569760235455988664435611637073095299348964895031256522341518334393298908720980310091677258259050839501734620861703519736156330486782058062108920426082301780782313177120388791075009404800919717031049871862967370496981345895529066587068132713570421396866002474171032798828511534709015241607580871356864576765549413891105681467997511566138432827266015032727577050435796848684618950382196747602538988581505927710311345462901980552296163268135726826525235538137508550339665930907047482112157057307891236309887842831397027840, - 1328208457641936860553971810782347963933235889690273060321178715587500252896134203349743934644740866298934483471523298512483757257118134302058896004887537937620530947393888482262958393457691268270081895980089761221801340091047242867074270547388386740194669397041954276451284751252099611532859507766068493749797946503788741796831994347075612185680909716719360873900964732379263399332476300389212492083973521709362929560314073420858724510910825757338536117726378785704285212975390133240684490990445269164414696854637258559003978178796078894113983027109457524572325184726602205247526082177647968629450683738852557295042130154170864026616774598818136210227449070677199478485637441860725142044216201873063397881988483588325634363577936709974891001459108736373808817936680090001157416815012512353670269137044711281555917990327217165995347995524064199264471480222160080130911949345943647238294610896822720878813821091917517102058840614352180466733840214780238419010604477587953510771752952907139598485966793907279206894914841322301958231263004027551006240348975116212796572198732359207140440738679525666554132362169260947073358829925503625794577591892505002165531596664124777545769399415536188226326016956418263583345673087821853295799823945574793067014425416163020397457325389976787138327186209928234273970885792527537873030993252753856969902141409150817449955124991849806634093129465648657435818255351381051824273048416751514124905226171957173750122340632325527576178288785818506576871378528178508242487492244176663704106441839714174418214382323039320832990829023430098436217109646355997946650664220659007863626352082725975066793521469520007443572659714822206981205304633743721069227942693355833583423035046720649867120269292665113141372499936729440331440822971906602903020078176462705196120050170198560557609286454334697975096098910258501298285212627976422978580081890213901418006327960466920378378935943725037098789458104889804855990377365960888876411399215485891708028884061463698876380189667125150902713680260018040609024210819519143265961913462298168264591910428536176959656024210104631090705899859912972495566656454512939789883665350167120098509171041403020433726138089819494188448311715180281524577572020691675444242612284021520266146342366501235037493535498934523917404130544073415533409097940260860072196972142887322458799428707455669292102846598063988969780858945118743447710264281728505451282383279610409586172547538814729546948755841358552568733485796948592733999394557232511726903282813828124209684290980766844874843435268654790841053453673444629908569673127363452780390330871690944298726953859187060799220961323747317431677141788794821574794097261913195224802868945975406445880288271771501964329668612389560691471208858369627035523353207112245443377638117227355275560096454697495906705738388519780973278757093037016725472561512466333039456875443689855168760041395078035292276443871087303363455544937526384940689768486835356690910912289840817117518669255492176661463965422902549874560985929154005764899501933128193331809874707485227500629068122092981077097238068655000403737786721557102561046933593226751722184068616544570970182142618277394294920659929391001200935039483620369705268226650229200144973798852569302037362608479249130520705402450121491602571986457775388417644751021557836888133569358777992064586185428360432315000253508020836867918347665025132870890223200262251960171595405317830693925947986256127276055166563994753935296101162429707328767131736438620977277072173591758958387890538889346529157511785743285128233041602384994792529660896802960017664049747889807584868501818906527643410146787844895553976207010146041400464932661005004909848285993532023786353384871527541601602323236647167646599232694774642721111805045134438111386304020384857823512394668868973379190803211257709663050900209917455581188733746892739348004579181096300588087422873764351664566802802110262571672609603233019904581537188763328309205294665495665982421316300294686402542828428894080280732416047922086001653530014359996028485693853651374640494353307845799486750636272432642120853984298772566550988391690493421850547171731824688391038662479520830036569752588777661819444237138211915348802648133861056054598002656890511513485731646706530911133701555490851639002129415968410327737279320377423137610106232704288432474989210816399271807899384594043849340905157306309030428839726843836696223581052108444022473225673939732176163248372993738361813583339141544338561034472832006769413107996162342004909417259269146101532933823174926215743527759635157548182383066119831106208552967586830319946338161200367664397771241084219235451219849076817349408058205511962545818001228027091179584971449548305723581952114094936526722682627100885017549836947569119425413613946453855320760450309948015484174652927358621443298497724365943254318272609280042734080345332573201997402490956172759465382574259505886682855239012398732684537707096229991780675790037865409095163826889264862337820926826011622116182836665804796722188341057156197829870529972702590819923897105241793489299626940319239662960314365761340559270627822701000527221960699104028450397896954449008319428906120790879236591510378859678989224604082009554871044280425300360061169495764449417805214212722418819122820229895716125802090341018086016776881470167172843619345250727177010034369735445340708322383480446745361363496028549422260685347213309598893265952413459748520801037662767518774662386792439380602070799202803176681404868857405697944423218599207851526696562749774929343361451678298139920261008647947672259649739288942777841606217665751322751582558773642149064173175315305110240313624427286199276507790884239776731203761262994430907597190614311283276300075396875409667663633667852529453977224374253179505469306944025063962674696959336326896748998469427551167845691816053430469634366705413365585927464770954495261212899415619410459457420798220476316804052192817803983780589712545165486587295767645797335431520449104541972525510485717423947544824044753630550187902012672313705194342138871700504566399177326280210560121824020167540500314581659546767325007144215591165233084858839126361638776714837747802405087040651831743932690915696134663169452342973148134556375431850607916288069036498510190503897733552599916248212305639510667411895340670370124807285150729639560149582580507981658687638332235372370789986463297291725288861192435880402432842821493644220264014950911793141085526253109510250789691910714865820337197746505293275966467854159833467809389990388554216888659938951980070147589700062956511219684266140898655888362436099620154031367386861457364461326968187012104024342644816060418525220694084709239719640712538174199947747923477686940856190440142350048087219783980034728346913276300069064650458204476660460829733446145728757873689955016607198843254235599750132440811577901037821920459913867982610650684708299749711367087587508469792023028619337674863793588060464118860756007350554006115469972063897328493556105887687354658842285219858355522707254580971188732245614008175495523816560116441656468938081453263856546051713407974742229971996906521447333232035118457868909584220384991932699606017366961846207109319868953414515152092905576618015285133956519621790470167640978940727556963091232065177621058263933413206874302237961094930581160826369556005428392586182924194147682623794133475951778212097765464564939580385954416850257462933980755330206459455964074374460515106111042415633582238499064220801038192470559640613727312811029609398890311800696287112175159339808674241823757046307138771407481948430238569113051221844192527629509265687995246647777316768846500622687072493460346624574682487095790481535812776478431156373978791998341082315039705665721760650006979081736985056184682793339132408633855982639455037710065631245111396931927604401638160802789123182527759644526785472878401602727254011422766395782094892682215474920076541832825788595652912787061930374835354044288209584739677720308442290604180385912301520636023141087871509119328645932745809973282442076420003378523087410318674299662008236142140176831196829084368905420785324523275944116169602796994924656090383346613122637192302939912232383053493088121297981677744695241837430996815081994124382515454589607199925156841817199731687402829701645701087756969238481569198135279789069602606729044549548480605273080758302413927811324400076624135528546212821656555860701922894661015213614822553449489367211479963430717878473530865999636930780255344546404062730917939917535329475385827415025629137644844432864493670218394331639311555831153699717500955134336570191928028541052233520852835762794539679452161363115067540838655114253760905366658573851286522428314954333786616825998811065745815862853766586781126512513395698388520845838048816378531864471022521516837147742019746118147594551756733537137032326205613175715598443646499215352960987090702304673970916544912862369325867754276713781697662284552514991656810835101547453760479007630464491121738978104585302211236175365311248467576750106315670302240687337174753007664775697216746351167947636450688402815872075224942468523615110074667868528125616847485265027192852920867167100384577361899610810686630768816250528582746324336136683520, - 491970622056368670226892648970389712283764834945980501454435534909188105706017173332444773911108109280423883335845142013376592530386074925310712662421464848176498196624216275475614761566654204298766060391163850620536433730553547941703460121121921562730828099713421663777755832788590653985099718861958196323393404472101144268464240249795652894191709402546734667056840695048291935082896356926870411263270161640462611264212150301311617645677994096270605039599924341132648803081019725016203598061618724940807928606965482046464316347350970462440020639405477049610206276324772331002755419780929378330178876680383987910637094731783234002934642949673172838558815940011833106203097604539527904268758163079988512033010021634159922044795234453719278923313763121851448907692791660228036348309662432184863454426518579909587117550809538004933896819790139798873946590029648198761568617482308817554541347219086133066933326294742346844846183023286080776353213770679423410817293129520317703837686847095997680426866370233543955946190468043505081770196416301678608157268144797606491927368853658115147453243826360076444819259346272390829286620473700774568181549314014930995119406350184315305470980805593395254494527020251149552330384573286857949557718248573251565184129601367069730956384936085786328659747949506503726062341394682977071162630987850634384702086014422755721088655051296116995317602319272300902738916684277424729295542088385468004147593515447455761856303850266471060806088833153531425816810452704905442085542036991343161245250591925281915120729899055619345478564493105114188549854989541333317230224100475518220411126078906325669939141728782936524601171015342094911283850603151831905761639839963575681748986974174482218794472657101237735231705789148089579954195349607987489320436572883985608557249101825645941066363550657372082358867872702260347886756026287582711962000510718856323440941545439485989376912485632300336476616908035597342109719263367010388169012025739618432963408363129519842324096865059564814006629050507602113345100567979693318320899579791849168636345012515186474864105567280304727141307214256823031624581729058758384952183451674299681092460159729411145601370770115614317139088351046550421574443067895689278026385193969496341719941775780619474452065404357481308015951045108886379326103907057189044680816364465586062653392736792742213769208006634841352229388663751587116017425480696653214790037128260791976647616818585723317007883368547380728987230613929682476441842306777235735842180032071310741428293160606640763717200791422991760432853328942145851940918439948537156487549112256175886619635222223354073563902508362293743584905625082821502079846499472532804339826494052284659491348865501513897879858533595250783161694443928385987530084233243865158138421139184824386150691768989687739460665656419756561577380715728984303932851413890259857667379027605413710510267824423172789543914084364546988159241569871729802726407299943893203472289332299649887682186634122567658149244385814257065337425474135614615435107109841484490585079465495865635391140475668013315668252686523816406271850080312779195289232229979924520078814679879178860417542331754424585896283781067493872017878423702954320879667959317207062023897986618069606387945974959083563184663563906163817080778251614274658612945364432561098372576422657683484961592545088941580180011449079521250016115188706697013586039039785282704444835699647052945842422721115104039974024247786410466260476229862462276266518260005430545391019109187296187521937130232221399130711706069393993952648997895872300385704293348648155137083844746134744810928016174756948216726282332944789821389515561043747651012236557405411486492979745847215368670494810012495881852441035686193790895757316614715001626175347082974468840746543637770591852874121716178922640213763366466943352502682946068947625691286762379226197016308141713843868082673727035739406717861477911927396641087664550843299897991589426767270402376039149637052225304743713945910810033235844077970242620269160463141547628053325978349465286047395818240251664435606193906250640902819306362888528373846241067142951341442265300863557886592918737188700624265607416561622062275688156272878305771864712252084138635051581029277065998445273145280442237482884242637050693806244049611431218234843913059670741738435875324211183362189898312415118167606401419881945012919343747761282279344898732631758879312916518267133446985161817962647249069529215198072663272778206240106002215120204373931478432474713926456076705921098495251014399097973687488684286343075550745891300693543782255587459593087562253399546627515117606792190078586018465571791976164943580781292806329828756862655227614698209795420393153574611340678928111823020556954376492618461446695421062450065224643395723754688774685546453935058228773971305873747040608614181585046575469588503720487313022331466141124652991138581155615389402348254140916804588281489246028555457168910043784468701127989980931527839742466889749536900852692352715480990047155418560682822993080402945579548340909759162446193790837892363910855948100914114038322584060092511229942205306791467488896227207354626028149730164206825595420087295164776128384493760260714938895686078113511557237894835714996388541266757966980925403598391233613736177332486488435806469232372963639845365232267217738814400054064640627724924561186044878888487501905918853262113331039388523057042608938148902889408156397920182925059322444820017689176367661589615571933703697493389059535364352987965305085004051480564008457551016416591771732497935733018442279028046344885537842664338463078237013401693309605499276229989478687220843779394367961067395426117794957240479554271520674877299272744470942466224393923865684195810771073330096721073283218352453088798723013396082396668755341015097763852994557574950322972209211025022241872227786027766891896525419426672798466314149078810734024252098001298576032236917126191543592042901329787183277807589415633615877011193410687045974404433455513215473546331689277753214870572813665966448988421357342047514730835447813365397694664570402173437171472049054666346120410804408249647986400726909170963649979640395965486142121693318938380316618341368482543510244731127697863523149715169001383881942176883954507616804147297825656642409953692018345014735062804410232577935440009027849352984827560931423989770902026255841418837805562453422549631072778065164728721973753119934477884080385169534604542562068094428578250796278686473475523520618841948392596151011412917153630315828274750749048451143510227263790873704381206639835300642623747368224030053686522551954965326009392094871838248917948319989316040686588977553796065342694403560118370384386535477799898960112589855654830922328689913127180881773007390005864155728437493448423360990697022348263193239451564851612605782292333302612254207451402959609224802408613565663677793230556624934378918615540899058708784735012749847745131645215973866574186708041117120220997504267577113590400036471319491872244247601232921577871210105854685318154731008699411169357982196067136583149549613314548919893074913311810204072427441575554413577426389705280286166037749412331234206344199611415775273682110767392303283724756915799423233220072821102719997332489531152225456935821710867764700195689096695559952540702825472260379414128613331248776026234368702797887346241459647733623856792218496394036853002514927549073331524670325856060098409547994569196180702613951028583813209656529247659508748974815966246050549209012613882108213547613225959458792405379620243977258002922905090293827618297910713996180600169511512821374998885587554869765801450238568175192672106330382367500688409436149143815373832015728147185222317567455227305976457226330801310968362931385716979490795788867074760394306913800000322013282298215609782667257881748863530856981394767822137458640848697507193990004142929535737911875535603258955372815219887926243422616410796535950494108542852576977106055361470640583629420529148477899327072108459656432706199832482617259454518219808269443564854190181635937977879299092602425206185197719335787622574349105193959268403871215964273151806069812322155478720962257735089714096309739348563712052610260337541837549883989082104429779239019639707608915076318580774726020662575471070564956234474694639903123994961490625560841060171519129966881148637096745425261325198324718775658418663624601019078873948411120852280003671013887019322404632150241672759849590056931169687187160579923620942519789346959848472111024885455761080789483155547393454155234396362285432628331569771369342993875127386845019313144725042492419769497830706045621828361582312945411415467782238514055341092182556150033032754522919288419513266814101536780644758811944366113900938208134943030002831370499976508283499267201696503217783698953039590164894404716065039899890913274669600810303867617588583004883039069072640763533797374517939203340141057791545843830940265713629510331204953601746341467251356103183524721020849708245311015986815627328098484488334299962480389228442368803389008779959321136054940538846565483636619293758248141749650926894783544727102040037220907035669949569117967763121947236628689638362727861260844949275274534134480896, - 170905876243792784716048023460255249395307675149765882808871448676404716007016700309136236430021754739100283172171015908582915468631589300589021286981803589279997077099383670881427112007503712320727436042056278828163702144794065307210653215113368460170756041249275191294796099245291331372812267649149435537722422818869042234908126761171386240349118380191836083615772504897339650789255500460044491584870060327240123897163090255181423922586439350479413294847046275697264845143648641992194276258855979129699746950831695664797184541553289439435725209385432176368230414810851465191407421548141059260782131596473362764499289704863353968895195403787252042002396057372003970546461520905775517358794877264894933192012216904532763365078097233721062406151592307205970089577024175218865181970179088015641203700960778784346455125303211034388514585037353137217740449688832582905243991200125157514119334942406045329724871128209903427632476919874166235067230565992602820043221363868412384282696347426723665831978777167231615531211964792216315798940200439299143879600503467190399822758802453138568052011447563111244076707390663788771191084704308958333682857775506531883653455612494150076515493369161302699223198134531348093634948939471891612069161478670060678416922875897679449217469037442818689749242756275634451158965071727428531676967296316368173182608671338719102156021836805134155380622490147341538968345005300189177471455382795011818691826705170621593495743720486185372572983271983261480351804710135881531380046944566980678286929128325582238917500238427592476427151740007052907211916883569864044911971663673200112021152205565950784733315522604197006844830680534948107480113935753714008873627065891538283375407469612432996790503360430558222543754383472003824513534344598565620202849406126382348462598932836194869839870458828071399126900704184482669302433430307578547159589406839248914866307317424984273740206915104093642882826164931321620951187614048773818634384258535600137782663058363644221938089599931590646310054298488300567329836455301852949103777156979825905392449095782625005050328871527642172615908891174340248307081635725857828159305999873916292652163819188736312650690973009498512186996807315030808743869011898999507130143528008692053769035633952883216043859756996051707194306257476641950825006886371256863784595851556822467147294579365235564928190821724227053689209282108991076496003340607384151808770141680449378842230371492848064715560362457021738977582225049752353726057843267742173984893175288167581471381519470495973677019019905274131265227611584013765942270222079186321078357374085638710027533504178991780174653547920547854412451172033661244623396957692797680735670216153006198095157280184445276524493812909576925794606805292635061454677355155346790421353998148990423698867728356238324714703689662379467492324673026132915208326143992821598930085896187785852714677021943825130307863318480983779852026813963675241329699635079599624059344973153326152952557481318838037062062662636360556093264402500686617275516689341153661020867832418833802629470797760491181905680040317364927523715477678352943924499191328587761616964678757388775807307729094864926367130987486061863599682030437668267487095959577335025187381642626763092930831386587598945823847121551280061365226163884975717596935950018017389685469363425245331200622931246091499013649785979879602129695432821424325575257063180371888620308135799016112677585793886081608310487467311304695264488868555008285067314447896189293615461334804206031319350918844864262734699905797777601045897633450100273833545503556405172637994881391580573640105374746335831005318990140950593982171639174714510867519948629629837952748346572769887882690447336225440700619058017269031616295034234348921253795254769238391084210126816508080824582052137645366932391328388093994681057522037702894066622013520296550896857384151798880941130528357209655015353457576300829323607530158062810076002197512299748137815206717283977647409297643661522566998783035539268961313894867038405956207929733293096147504840416239120894941820343007113656057034252220953732782374371843966661675254002432338854767947609175017470433679414172617165207767307802460662700346679598356486454896772099893964707332864590754680754789122951467678172615039699324716649765484689808254811860976865740856793699202879603412127029093260524721508829904446950552952144975872977688303872942357513951877267310396415040528043599574684820194844614271095259929021341481347609917516352481389957964265450740259993534996517655117120655272915011085946174858252581869687853811562604513349533841766907407182376642491329082972824836166983350516034688097340018238466100573635358816739814788321070238167855080417624003810109227256215588205790440607830660504148577095680389954699244847000579101307994746771917199976997779771255317104711284026708575857539161869230602502075703520096603343215738827857917967280962303233623293178429571973318134970457426899141929354400352781988265415385713351008340632681791030644424341482109031142438834760813948920747187207121232517431871960661513928765524630013790678516020109078357550508011511309237314530080708763089342541624877752603289221135786997857703113982142976612735698660757490508876050137997306940322329606014151531662830686684184927747764261479340405099834565256037611926381807674037449060227835593596402939513150129021199743837299784373713199174011209329358943779390790422842744790417109316586516020220072028970580212126337389429674047333453467214622760435098929511911672920277491608913463710228938298555313459372532348315910823032255074468292414126036570852206301119654321893678731224490118245234306330133131603094300387534924166766195810571245510442048490675561514432046898537073278963912676664804719180011317992904794878115466003282810409280109551211129685441212151473651940035853943174115926139513100834536638842669285977059568231857629765844461706550822205960408786636871684747170885885965670590712214308965827131563216164116793841270587928054678314022073478213990806922871062810399465114434164222742738245872887832384273254018659707452955229541589301453757335700685884117830031614333490002963081159960357221664896946788641328650617450183952250864857047085325592257477826227250556243719982352930769773491313835771435213982382732831358365380547229375492307140942340066196519427842843673850297520598337629962067563702631097499027955179219401182207082073479702269610924441798497385978928439138981344114768242324510230129006431104660876348845431214780638076284921870106235999282371733554833823715481277815271298412800618201496915576935433176806465136506864344905814999812812135786688108797352397580934842458379610839299064496253313816642133746740900312705519343524896578672461827748457358016699657456535425674787090544808770121847099573870990739512199954407898560474426289042015097080973356145973201466194601558945418997831734149781837846956286071622789456852559545640005423686574503763070642646122152546198759754178716423709327603378516119745805155683597665364893149367284530992351244646051726184382117273677788487666743477845069695084115361066030911268688896552408707459559768336437231699463651984706567246988111469160503253315983971317480822474435892747598997592730532789442279411741384714307509151410984269885694916693477871022709070432352370927402616954536055815796107884057553549311566142514340851521218403316486296972510908459315139571382947835993885588054211277997426088250685042264698671505851190657824925444876504603648275146956503828017147341516568718120357464759048093202073390120158236573877306225860945526375949649850769625984928342554945317216088398249603884822227934301314310430283462980053514828449649791979921077045838746309508463225797639884263112326507975084635561491078964480703055122325380928419995435027154277486357699726181884179790915723909157977429339514558522820531693951207729167904105242627395418242490786145283866441053929270758955502987637741753810706666105913134730443132060045703957824989104148742965238561244493000250619767349514191411441250708212000265132048809196437434287119216091281109667507598962607517822395878675586734904520807094120748798706040406422914917827691371474017467005483085362694047246507758164324156740327115433388608634879978276505226438825853185179464072970751530684727104080323868876367014786343056387695748388892847803773871302146211635725449260465836222376352640994245280458150658152746735694501028848858478457295320143098159954201541560410353031176742769482623606559150272141454883595281301976593357625528608459731627001573563634154224763784069176525362951551347789061967431222908245997194108214380424418373521068041349196049833407808200566981829078390916449108915273908139764314506718511995947937110708975115578246441732968385936737797503413000727908189764750921460501507450970398865780854052496188905506509376652459938137237559496353477300832028459234111677268862745561930389408964573736655789646086625132692999625925928222646762428257314656679035774162932519627781262365726286772863941278526626296738408596777797969837581541209067505381251861658519766597295823401911781390007045423266870608374785573070848035560094552667698294210498909463755358208, - 55734898480921303142202193422369988339100865137798867450633194410471995212903637185490678091185874248718619619028548691268510081753128415802076841677789609697603439234973560295628272285525788220718693608157106614773087259975196036121152992469742274596978853329264981025426369126473695900747113061389809623637912659658966399190319241411604771865740428464878456693026475419920349840823782198217794030646795144098675304925777016798210068541521423077584230700238931192268569570782014426839767428473323798823896871349726452339644834375858037083202256636879000103860583485903233870034596167388463698354205675203740720407547056203950383062068362953295773795455097012167272797278391873174305878259971833969395005941149527846525252291291804494924489924248390847916877731493097803262914683884738253013553398371428061373978045588061410193943819975010484030889683729105152104392550567731385828195168971618969890434002968666150463342713831810889579255841523904991122500773631886702010116275660447782358423547300597159272740106829923816918040502090859131992582060619088520578898454428811652618158350088840398341758834845420069006097290834063014569727177929703361678253210603996038128587506704562586984563438256753738711857410638439517295110963195042710326996849703970902979858606592690802805385645017681878844104327095729260242587239939801964526369461762730879696824249074329809544857354506109897569307020181744208812086505225110749065402667325501601116688702413744126352794758075827077781683184767809290236077307227369686452316220128097223744238189952449219161711103494392719343280373383665268932799632700587963103649875449251347225308643979447207893393789442119850129324144757930048934896989194872448096733027475675456369549589300713488365737013989204757743142868798924755895034590078348099021672692095387588038049471700905424840879220882029971739897370970129812938220279194692793117358385116412309675303411065841374953029833346902559270679762122218729556259420138004337775300008271811991524766643015467013283560593304575658253328773650582939400117063779310794059497354701342701540181430855177662578129706630458624063560367846951502947851343765496780421083676045655123870907983982615046006617627097044277230220635983396118361520262878146631472674878912540036188032252856425133660599279947992439047870339105530181229049924315289351855523548247721213384365794433526152481093576581216119682469021671288248459262115507821899075728411844577959275050835340276880131507898473497500071053389375090178569974689695434807119385967357364756251976251210320418854459046708631378511056423748777299739538612391832362431477032615943260862339460964426622811554896183867786242083530129257618028908816544755736800313107345072301959901378510681882398108313098356194297206272928677026629595097167439175335054492712015571027340716722115336312455891810325632777227067962709539801801199602546775394465738474335648164417210362715213006179907356314136190792791971296207352591264745264038082716599170830183608495970233421020431904994528337442280025518252941874046050087179289366303870736711232251198402107412375253009199020915083215500845587328416715593886033410956757368597215441458500472153722944915849833413252505110335676229458419237131689025127662572838281285638307149002776806005869424801736661518244488700123278788874957106651613847289597294861252769312264747999734555409216084699834765583727104900612643517261303453616567782783197850823266843601074459081263552852039314848468834234561876111220737883223773713198972356059240939877038189735584079332587938122780176569632457202287465060800723995081968852183793871482076856290520359842046708238648050970578787702902623423800252257347570246964695976081870327657129046602917138430689790623753794940811519319546887665424081598885127742310735019552299128329383421003765527532804722622188301721172704902162042523768340227457597919999534312909568415149275756242293626593780294453674362776542518602145000504612281425997007705102822626061597288008394253335488761586586989934491413707231039386442391177315113930613421388086254306481915165741133010634984927219057862467232610560583244797798466967560267256968636560236338806903508479822276144401320843880430034025803707920468071531879895579458938342020432956091219406933872671049113588448445952052020841068301900294459189939649046825471048820460854308571648860236119179632571264608493232138832560514877268385371711589767675502757322662807505644535094823706839554035426721413491762393860680309559296990066487659222106868282653582907099814454697423107201156917896346341554354984211943014065136145242236295351559905823410855162352860284721485864295420234063111578752719014024727638021514423023076100211105008118283999542536592766396802554780498269115493226323097693389144410992063013092181817392371381685310620480041466620330298669230454523232213588014251544606296029753135237833505300379066597468403458025844082304943667185197701114094324988851218006120922100587264540725085970389976055015462888357622008998627990437064640958397565974490583204217859172501237544907504777601142419010080683926794680059965221201582721532787589058459773140218765674335331690537874003347132531980718871958786590298811136260749708180288092770182794930243056288895160845339828568583136350809343292634858159853197629363928770540217024576703827245290722517963501730763139292301091951957733223099813963903458836403901083244288860896627873620077894404569289511525358490514779642428285202786166832114251869042550507281579156598960171940569024459188786142294791194161994837336286585145556076201474560982162724698029807981424868953915442031732080704345682370776216857055418590012031377477210527843500493658511781405140586026455563198610139111038824386824218274713517987217442117791522280676822499508572989547150512852255530485612363858135724259197937556042471133094485888868213392969298554298185062237292016190423787236275493032953750439604014327592181689762766241127174677315705094771576119869463567713243822552265427287670887019123042598080190612582411204343679574620147190492645607431553041767154000417939421971223019153957704580628787488610518688404074517212308736582131146630811730396638657789233002908534810987498183017638051162220655463498536388480117606414453483713028252630988313663927935854845457762334295776160430617256293569768713077217174379623182867458085397487098833676652664574468274625853923693779988395299694084552241508115186413340455686987973298674648476833836010884012116949741111574165713054806236578356710584037211289760516828919656453273944256142773192158310146141029897488297839047201908528846676868732852378426022278786740420718697052647167979565133254870944525744595017264211822294552343468524871809867328355834084314096202672130604153031697889292006349293887714821151727650591014434711674911046752889499030872542963635215470321602540262532103399142801493292919017623044173573018794749821276818698202169312691506997718526871038302003432246651636637970218886881069998706522266679753918851892110578802574551934928603586391539852006584697735457935072521624202456648553684308533312993717951500459667501121799562177304546288452504649531828681749446419305470848187989222015012022602834499313503797962870702619810802688849505122374469332310026722511785960733390138310260538238245978156734474611984695349449249848656212663075546750693238363840447675287954682723770323563470121753829094753148101339827843438734403464238613846603960816705080241804285550015417358530334525734482959926412337416244705794723784720654786687410618620029555761617001154363404596126296879775496682870426742017106555185627428457221744245113673535240743236429648471271339449754938402784450788479564506362639035645527396405950997117743806540465398396348673997751706200171238378975757906669763481238525804557084043302944441825819882176130882488656906858286880714280878120218583297365512478238610870063652412048895231235077581197893570788355807197126932898965827144341569504658926413878212570886236219013653110148082114413572821952592458683342181282983261290712974835627774046068467171822870975004975063650814923359515933036383929207396392885945472774775578787486840949510969220776074117338749459308513311002329135031763764814693812535714522467372896764398977584766495664561550663989779952854046769620957239309716511005473046123077094090777000801500860604655845866261888194766037868729631325262171756487662644889447950056027062677615866121854853687504553179831360269076695449490895395801605876230346587505755640903613109137575069917944580229974246559710250780133837575759673489263857678291753769264544143407761400990476144083152971597100191374991814861794836735810756077494792241228018804050323768678531289430792690137717559352049712916831442346778850475876079700917683665877117321182866831592450351825071331432943577162276567524470058532447445358038087824858546287835337700744784461053324252509208833523185604453717624400123848335475818303683955097249187962265320880203245148498819286687654939053909868361068649277737569386140872651664710664040249708660169931800460714973788591881014521501983822139153592513791016428431931184265937423357503057274306682632172016010042635719979040768, - 17077820595004808842167459084677145324479866593846601894748683885988232730812036891371045982076050410869346890903739290683387634186602172561365379194678802086862966136846289395954546879193501358264503986152651122720967227819454349176985969712272618531863210552843690395049721147063151412874818513807683694930627615170237561705457117931420850089452390268221800566528405361146992328945009398304434205476789877884776892634204280002144388424977557618251770200008517875993803238117211735779154870364219915615621665698757798333469571947057672246912813785686842449889006661269435096903041055417917670646886322200928474549536280108298074044660374721695195577717190846602516685568382361274079141066662242055730889084407545522708542850154174260923738784954118679348384411635595295405049030442371499017194096054760014810539648754212932978910587501426185231376072105950434670798902120500471267028374656706640647104710404146516093599803500771003432105717460339914579281743438914280769666717154502115460865766076529512947411259240859219158552661355066904908642121724514800997153266986502877805639241431685925897465241901500641953042059491822878632379320942344218737782208114354709392189175119675049053734064336237387614029291689021875664767027632923056069056500296380880449356481442938450885594556662802276604919168775258822340098097934556638271901210373314240499958383870728365669292482582937053192661122038969128194444754921407400850570354204542358797607032070809776198010931103623324223449898934948536968314493428127191587187838502510966165174050131458442074320317321392364979617211611782156011692536630255215134816622111606304655218298738351734881867390765740221046180853481876983735504883917571511536569697521855756316190753012891092803525268973602210205873738118607156793104871393729791615408764082773045673806170277873913765632494371007343400068458616886348281312810882653974294383706367212931183706761150144158878043294832064945421189805788357621225372133831281721732548247879538054926222208672085969441300327421723322142382729001889355756431033994609402465522685549484966386562076293559150410132838023716529750316340106906974948797600173823512832667606663810104220914803494548754311220402794559423898271480716729999742921535464881447144137579832013105391552991039171276917971546977049789561124531560239782132798147120844886930264081547569155412851468343605324113113036868786787386110466056372922955679797627163672633208895865069139130907944013978568088017348799147514732369169911148020936869805369779199926097984191162055863745810645605803433990807101367235159547728781386939155287880480235453935444127960706005903150072500566538913702815331462047721675022293408109295795555895769367402781843003200413066969810265733510202704674150278612586582877743951796136098335005552360382185564972858272926819443405778383815557492131846954307093546991099216986523932136991521827700224957330846828529927214935695634329954077642635437112326575851847178969173081722356714901397887897615898838824979216638472771897838335210060522844005780207817984649625509778048920973139734510490094400888996294201877082090170962987543709854746416726434256235306594086349003397194773867457530665017356741156603117461995406556397130361757561655592712905105701053087210679751670157821848222712669722943368486761227837487073728423402924454755252818698741655920371309549521121978332288877230844936636207730916735663574218136713201853360791120094590008328783673980359947239571055970748405713733899502891841596130906665784937922961703216336601372674619737882442007662562891895308679790139129297618049831694968798369503678759457587403187319656214524545262246793202097534174019836073426598135360483399641248197354750837941526785019669915601650672059134305707770657769187953475249154368878246583569160981906674256777134070862478333969760345249290584281200285372738644879312796870690732109507320121563620929842286027787612150337914669400002886280398547311293155796559348265970470682711692377705618828349070601892736284328508522295562606359282700445717403304112095494033027752856677586688393089942279686392421675268972879742992267677901649084637218753032706514156139681387324610299477005118037394684821530678176101708805115420683015372807440443085380332691123445235736384404175831014164957764164925235967818561963247279513640837370899720099241097369088277636524313510499960576177290728233033993082897290242943593446582211594636255534203343038338977546384810450731525807111264068452937771659196335860446445760346300684625357585249333774959812372489662751496934788362495193937773606201412557077798992348809540752451580406391475615392831120921867830848426345091096193886071461191076715524498298966412217354937097995412713385746717032828055610258697570231978954093157459544069723996844914570928489377872820038003664643855392026777305551083365749916091912751565642943720517390393991357217411853561995392733792803990776588409928555035697676678254329842632777899094273187255123507878364329722377524255390574137691064732578121502165700682980071092581873566830513328848996215463138016613010084677848051418022249441187639258374875829599441220469581956488496015569737991955009046622038322824129568751089957440320046092555976074472819737838496027120831896573711023218381394785524788653866923371639420095892830720418270421256844683144425014728854173655529112777005915684507204713454775735097863939580234351951040672769967167892734989544241566101588912696129053662570375657301501578089847373669319126558093446207133535389662263024419764036379504669073943691377192018715892234351152785915376299202344808996690038744067532628511190031952242001037714008636734858522975472367800862717884398575909149259262005190680405269356419628413480060704125141693001938319503511884954208745883384610886145230422632556680145178655204466254018208913015682960108805227258012755946925048948611813398907441417830273756140995673813814030820780755686871813172672877129257902661426801412527610755033247586533227593776978736158992545163502066171250262058845239085839033010327388850838277992614823033203171027567384790342121753882438009703793961835132499520791643654148352499180057455180622440788759922813615596637259634513169959168566670682751494532643080567996072287032142297873535527405328462888598619667661262040465441116795757509518570651416126298900298427458643492235473020771784324427451302856554859373681153888172737780940512504160575425290715064758771900361248228313213080841647109122907365144077539506268177607951703197608399280106725491180652187698793276907774489623487364271989364552780964136452795765752785544773422130199197560569452361283077522720798719958650353590724454839553863250321828378426274137168952693187387961740794180129671103395946718206519272118250249194082018035562571044100004927966557191068594628871382431491699013023369325565684318560041122191890682050624041276592160351869476703924179500688681291727177795001194351268783764006768525495066675656404508289570936216366267879390150289960516783056496014219087018345001389500758281646319172400008317956807799072780809828192137568776942310454222708913820474794115875274164442189352750801043538579297635956527073678701636258796248444251653334478203562151320766951327120755646301269647302233073677291177120787189358199809018239684725692828802829221889898424399196878393421220102884848242263181407193103384688656111123509041572440161216802228838314421606608898980287041242102152614547217302986712152065414489852664031211597587894098306081701489960401118643855625935122402690047717508514024132595341709039454723352589703315130551704834346506505609227363212517733568865760543221587779688227008969804556911706678646607686925260160200914469726655050355238183751922741214872338119422755736101129596650158783385817904732461785354767828366294905207789354125862335296344875624403876858967517076714351552084219070431783572989795380061894188565493579385277132284960179549009475025328158038589699315061567371200545837797278768987293904580771494184088791747544839062625747550327738380944679850914728397694403958069855331779183667114363595497580620539572200378774982950356122729464501623889437082880253188892082376018630580396165871415448929032354281838982159942987383503206493836850143670735790774515991666069039501685852579766480698373695405348542736763252159272897467954995036460438758265867953680369089476802753031060662897021837122906702520357565348771079761440224543884845373567760174114452742062915905849746192436740166740248167821509427312337874504904565002983542569850012845028258827230823992775334697318361942918387476799834424985183512680416052907256530655940749684485959587607370282832297040702613134003849448277684480066340339108490997057233770726516713986014011551621847993888552557339552289129164516417840457510412173353942575629047477740970796808430696497192557598900905152104511237140295502995373727898026040833295115843686766478779784444973514675350094430296028948159976287949683524994041460122028070013940643732523458131155618336313984382466679150949981574437698268558677906073416128325585516797867271850055649436689090225737952594019595090120714535579738982928685512525873152, - 4920749061789821908805524336762168674191624887544778015054023194556550766252164310846785253623343591846932202943478137688025476615441395986022359635961480028251637465277130819428533947814672047059797125361565559584382451498286610794552858722714849674584762596304235213647880013572289252406978424187947131527677171033933734463110117318600585172808608218667192274482254634157809013928792732194845420276972646687768901578759758232165533127421301450466891734609441635964383104201523789173507910053787350375707582086241471412165552809583955417799094278537257496265387768767597841669308986584562305214094119031805449793803834206530223044947894720081569286262382894815655931361536377995046945989194162843874425554665533579453925365062053809217455061572288033605508291939254389081015322404882190866770507355863390434540686426446083401206532370021725626249828251004004627631449007079000355867241978334595521365699556769246284321067284455911667256885966544999256454747410551113870898670173733254557764134173223995403547844780934409841882614479802301567931906378211916656626144468573016085301140788179829678563296676338269727813834489794340414677469693723705546929077896492348807172808938647276935337259583682517224361408996035625831543520045064318937288720902091812843881696742019245689742733502619307794715614874029333941559135548354966333789732194659472905498436938331591439177172200140457517490388570674452440696876946912056964095478208887973316007622735933288644007892843985748930021384220265667178111101542188369869396088632561860302967026251686749061726557450164872449674830604947493991899486803068163472476781898492207710822429836193817838232865267155671153199553892943009996057707426949053475013521494636831218816494217435762780111267815941711765359327281202940605400549964659741702848030233903303468916348382120216356623832079720868790792517697857784245244069502228387124527793694437921467243982401202623620341849015473871703632675006831292736915709956890031179600984476632347582312628224772595436679232278608262211209841985095157408330902343806747180965605187106910334294392832269241107183768440225571266566927354159553619375470447180689309933647864308418985436252676010773150375748011564050225549860120066424580361669488706577293510630821297973627208471284851239364592266565494144177931152032529362557582274475392086068708391510794175416771388296487849296487441390722820622338143808726725306982558634096705306992411909113431367047906272609720116953139676974278706536001339550973805920913496684557361200652593326064877685617074698693587451107654378865193243118825602007550078971736174674275070808524775554532361526859989197021235356898712306192478248197761871482458304711629942254755602610903530326972480985946610397904968222441153875753076811421734975234878117455937303911509894657371749801366525211807638855081642541777674056643676647970001458981835122410157352363544775485122842794832859743171360444500336455525042704066232395701552096855585796627791603285619504701878749935968688263277293397822142526122578021401366745389622718739239779234666676827537758094995872768058214125825524799909424136304644537123856638435310077541637795648183088340528915108750486099042604423619001607361477419779630319803336638606681527416382203743927993684946437195839405853280367428601923682913369902354701106140794050634543844092804368712685874771983058492740714474673467418838096313177675553827841171245741574324368288346961763207356434748227025592972392117448285466883954379293542163773764538738276960469531901962455504397412328299422133396043776972807417560571071310532044135757936583301309282920314779736168545484658693664993603417430489962827900683008275843045614372356149176090472495562354604017854276345260834890889795640656383519624775757198815370915527913121014686564082170924192102059835432715781590782703177001258743232863096911616736569084886424348482010088391778487665650574028470012320255777959888182325419538233045233968054374710642986752773347626540968902053801251031956434457783610248178270381994441596204546545776826661112457764754747491595026497642042369022550822454142753960108223932135772966569237414399599004590039526765638402746024912873242179401966061433703960219149693955456360422896872871165689760436475716116440479890154355782144224187345193856273601892760365261330254578868521258996492110500710818174267366882356278868110698435686290217107148067110409319020746389978462322519390335929724353989399158361997104450358282379087777488447218744607955241597875015267022357670191626588126449930603497936919914303918044304696015683184311067102756403020530560646294758151099774800105414820909811946735066538176563584494038314425622832016846453444498399025432776971541983908570512758406899075471391641743206747678465099527453870036786064983787326240923241496823177136362458824852298743093356386093122049336064680421215287760403473102245570704830048057553275041705099764368578164719977908045145226459272342620713164719669409570673791612185785875264928471152563459948833613386014898489724177754435601249550662479112981808034704804597504973818224574854306087597945404430208894767298906235810571710375496708943987319382406737041250788335690439566214382580561562257871014414433785556689381858787927689663371147336622083767679530974618642871433506072991983586743996502249344972069476911590759399341762419518750604710034029208284078028229022304085696174494653644320025862696649245581673705156378736360466148545882221499882602053026954211205073825895485402762053687920388307797962384460547576528479152094495579176103063686270616832856103751178865095959192550990855252018265506092234463563345270218707288786906914286456585480525908646394130220599465416176091748741135407847428000279289936694571651722277268658631373771503876275972683760612008994547794226795828055597250959562551755557128625286532778544675875068282694605888610963527359298737267330766043855177657224913876455993915379310932042828768920046858933445036250478749540247839195412420970162192629346011945981511973375694170918354387235970029833382894332747897922846185784809484628177439789187192615752445140258880484159090829263725842729842732204869322625430115156015021352652938824076222763197281034433487554642209888379279391186791891625368861932074099229137710056594834673927192170766409059544927003948513016640084684470662566014909505939947687664102177929377483081106865028405708116373325195937318056119323108257958719773119168854599836967592012954398878909309874121483914227066036801674777974926945561412075665691008088856830992754043662917790756582748279763800863864741290070208576729522938880184733812487155341858320477922701664279251095563622551179650108182077645425568705259846613709377773434741660905743413985022928745094823381427368656645665731540798126812217970186113287326310045297445495997252167356666559431458711400751296481633259542258970112928416253980282253645418999423059567233810623184126779726376739822537696693605309719466670890957417093173138831781484145955059956515132563367516371250002952837301105005291064037447628726181636788326680695243505887674424978656095752806603499752282462306226334794815382144601267596521321951693566950307768137025137394382411817217235381972451554321152955232563270593235020079483345269777194955830401916528511787428016328391649089197824964389825861205718300793185545298818827662822057284602133340825484041029018148981697550742464719361898279428128038497466377665985672906523326200939318789043813533744935531522644612303964579248641655742390865901435391170454412222050658205786211783166719829202382263985476601824944994375815833372462488067094299016919187084261623824136008006509984042789741090612512582401022202150536425422238044830481264410032308474629403043095414138456749333898538624543755435065990646744413874393166588551957617213302545475355188554680360252145151468208302344793501853110676803834862314713430352579303707986261863468704035847930202572692971272177577144343158499756342361791161498614902083775468383432671087050950084515468275603544789303917164265997958678199279844708413860054837455731309022964179501973672514431280133090280009498696511849199825713443058551428469593589132881863462103397567879143377325655000277909943126331611977045937843635155106857908016102838343151018487380087895219836165051927924935652637591679293351105924744174359095908650340801487386520838520757827235303770173353627485257517472266151992143196398846496975193609586378918265039241822913326754868188151068408239498255563576238841363858874737067821710272572245063634920607857366748234269628528380126070767179394073307826712302359824305076981050806015325992683175784716491899575352897424804331980178058199297674131370912429600623638187990390252145913540239492144405753543266339955020094601527386727251294462067195828878586540369778462976454730790541727982116380138456227048932637390250493671173053065875523413094992789774503871528533491961669294542029523884833224795872194838905612421682244503258452456742445331144215542950392772534146221555521737565952477362930586068289180468258093630622694897454969036182199305324664922156033141714546851840, - 1334315689204738281893617573642689178374227860779065235165723928825455514852477357427341558900974651375226226701104619133341491983694446984919900320041981245109502769455082775437892009871902806478029057919889682640125146113023691997883778953806221257529822797473254271029963215343568962815792975551749318537544907243397433385401073886362942460663117192781337095873766816156331933085096984546141647182406098017365192286257203482234895221052290169078613615199858800144816384374870221568943758275761585642595812458018757798324951371099640115890828439181496157632363417617923376513607343613346020328936603990769767254368033096722667759117546675391457513281499763637283713326779117370354284090001048046059198048309911173510849556297747510579788698382240903688238219055801500866735054266763418635845489893522120810217489977933630535417763788118786570039777894476677191922189037538301555882553484240502014997760792758026048629736645501042132497404436449866641176644694356999314924212758206449316759406743522627528351973054537207861293089822474183420814729614791821544844932491355432428242071399920869540753746200943141335403901882973495242042391561406511534116475054641162890612587954971541335250379462293162532958889554893365957254152416481400523874451058409677605928709523709689179357429865333301030402538997535161160035754339522025509020770239472565585113067300242915502064946882632265496478415860149517042386746945763455654523744698667318931931374861219927500263479850080392613260528492979329009006456449454217544511736397889041101666369254582578146307077766103927263179458105302448630279829339063601892437016742375714868996941647778740394270824386776737282371825333952234541217747860138900945370075617732452719897346679863499652762461332431773586674773344060352282004738804754760388431993179337486783097886279009391973168895051937254788125885627100495302783653345286992005167563427463516075698762364153122673108231929615074125620335801440838202021692669770941514639192458198244474372170049740972161912578010085433124306908667446433834155313024300633186975985851774566863613303721520041487461551016819410099961567066649649323551099804884716581730069624575833410988923331523970693256379116996125180012487620202812912749380548495805424987338712120160170161687540219906854438293475584692524048117271024551026674287287939632539391696115906345610876864862467587611821417392873758714927320070202612166773422696043387596507555512581341091074290409914608788478932024729945936055399995344871305578982179397967982088757796818853927118969424783869301502311082285271972403834554014526579726791764783787370086018200242285357715199429068253621486448572238620537326524226204075834983039615082073594828239371178277048825718584771779893901504583100213380940869857146875716056763849795871426821780556201560203187670571342072285020654784532866153793725568870877868530601050366909452149506091542841037696606649249316697149443871969502174421110247192684640402800657166070650538858560170430503810164376565661759477199569116273416191422090218547053677058060228798804466168701935761501200128254617814443640302344069451006272408824816088478863644780750993584218564841044112690321361224317241885009868104892035374102130583295340123458859572098609950151288068635448365058748815426667872466625826455847183593962341255457098933915428549796009291896865603833051945166937316605773070859672060957104386751118909099259157864936357537128373236687646651001524791545911076899797025530769597831887638554209942690811661323913428698947662323186942214213189791098339015367297365581379231850305091364360643515704328907816378277953155176665393439225323753355216508388103918615895308943511172464734312282494835375730325962547480473602352089516122101593444956714685009658494772305364120231137139246212017995612595899905091973810286257726351678310350871237612794404205491436883360729069999135497243594569301715110455170337845610633271906876435081134852923178835136457121524177865031561892596199109915129603927066200045890446322494427250669370646319369497635230962242828738454784152594091520451344711187847871757428239262986281229744475317269022693255551612797671079328318641999929888769506144587340182948569348181140170789734064142394658618878509439869651060833607117343834230581936331998697670145528654501473879549470796859775269316298030677942348825989059273278859935954697028179164740860026772548268447921977741001237354835618372540803835148857913654048222512402141613469963350575653621529411175737513896354322748153272339490623235766897368902139924892678590695683533970836118313919986647924818105789264455900590253050287306876337779816042488473428395730581520847367492186422839719091308009898726570248661350486409492039933632304537912272827874533473441037835022923611357306347877161189514060542021336337116674795528076479066393365983744022223745793424297692336227707235942097183059498085241146679823221874493069372865296360853644813946920981780926646444714367266868949946426134993468679850145051909821523525703070458138042497639726602119109563225178430382927372084471554866044561421623727317924749368215787796019567688241150931730466066467921791065590368751560136920872029934389521614588327219583516098668723702607197042430391470278212582711523714515302081658022029466509350645865340900909479168200857656753461246439744920059944223690902897020475552949064573310828033728920456447331245412380853472093475153854297699139717618276948102551900763507410993336340741345477907982439140187670770160092093838852563616888120537358186234652550206070461762663540293330642800941221866985118462889180210423677769473655051557184182385204032199072606442513329804515667151299661146115430048128259149884881208686972216894024064492088646987752918042697334118212245573846365230513019305093749178839306475126974540681132642924360834085892588738538869097436096870514131927052514565432219215476799968868040668662394155827008611739709431866312226218120776279492597227427935211295267544524533939613901332398916027281470069571494416286285872633962347001693389984383675082771973566565737065614717063951350493156359935345154270030631478553716497840041662897298640068386261750421236372912354183451156312146161887985064041705850060733332047693008945582110091449355822053152906643449421165951275293760390016543700935124548150015628154895237375936866772002146073687015129722179248929040278081974987530479971321386024977176612270407489948459797893165687491738178555983266248175281855363975243114601378345748406043029947468576995085483005365892804900381631023802804083714208414025917724172734460740064602379613516604605703417373979757961610698058053071557206673514963286711412128311406321221177291959340695586242308251134045325434374752246874833526332420135580339187016438431318955378234323657107370717957286408621381697540546111719451407106953949536335539840658308935597123344333775860810578171304924387862779958909365661881980976259524906878854089235048702816291037808853151036742358818955222046817187020210852737313280582763626285031789767207899691772045025744681553187796456156033855986571763094619015331969274605258153359457567433325995925431111885399710327634562742817010240370759771762265056769828723729733953086206844360351363763819475577587387405326266932097406012168758908118634272136861618389695381757033907057163811285014467052892972595171609583861820141695921178375749253282661089898106579898050522959332821431186366731688250565150967334275940752632692624160323704499299822251159781631012431140080582863351050121453357276168855101981255170513378674499737969925456941735767065533296639855301542570164458298292693726641004545874231242978284661433235374138997723908848118480237638730555902425595450523219444651433543308299891429910937505856472191759413342108159804038156494557503804839137078195921936303499808243012597477089877687400162250495078550890003108545676333730668230826550356866883618324943839328265031573855077692242539350277276523392822308770176778835628210193986453309878840080906941819482202583637790441737809093437047946130206353588492534376324457504734712634177561677739500286271111988927452264982310552543787670937491672770765812187012103079908000820780819684854494558193577372104260949685217034198546423757668316923605643451844575496764495663516792602352064076149896877020021837234737133617112438589216906510140268113947785881565323814822812132960954160548928669023583734771219085972107749702774881874773992579218015691505061715018169678278052722424003601771223439699125515277019043190165708094117283153726007388498950018701970887859277387939332070213990691705452300181407970631080656956099542272151358132785338528931360856837049162431779470290251193673669720045944502668981843769314257293670787579505161680316828814572300043333760540856920746052580912475361675590723109968283887563604243258366412694667191675784776893505187756743401989808106854149418641016042783747590785965058026824473175694761755750782126624750530090586842459185211982251741444414470622346801306917333713520654254472821305074146215834557440181611385564368462566815109197120570218256028139520, - 340742782254552416681025294957629112375094035571195537147881925407757161099831114945684269618582625618420645080124327115883983231239597826374436756633892325482206613119291179610012816715185366809163050574623307771084133704809637479722551781227263338062727911757640751333970645824145918295323026215670239110201572574990612893925963582497561487206637948623083996446970232930187871783452067487735026019228906188554286674505575681405111434832563809312455767669785875079490408520447166214936343368110565480555520273399017164946963624286254854220978638204365501427360783628320754558061756228254939701634160225756047799949300498140149782214626676738893828486317907185228782854544915761283669121890250530451945452153839773840655420080750533283285363131825993763821970609580695644709181399560532630652010535513014689476982253845037011088206348255720265073630194799296049962897760084057584975416280175641519547334334635617563541045966251291343168631267095476727571367268484808136126274560710534444403500738842377751939517008172267267224833098252776035345831006940276333713470030049184190981790581936427166976877577455637768758201150307541028874567124430716891978060994919527077520175880176708899898716529930498185829576996112543482798977209882921381242820847279749561330355246372295244564313858959555803378496359632402412333924997674103060139877334551640646164266720441649656622273296179471188449501089034038161517481017301330579687931604804288084281794574932865113742705155986424015119839188106854423765583197427531956659724267276410086724165877742165588789837102825671287321208897720523101370211515938956834814124748274540526329177524283650254696504867785259159745430142480439020231633888233984515209046527518059490886111244378995451252745205841441966669655529884024063785481427649610508086295841100018000152583788356152198708003028435203595333347507186612799271469044580626436363271477167953769848667737977179328756678794765007609967478737100747450678176722936421012180926677211073798721789347832080779858750668716942962913424545157040350380102606876184369069993322489272566789784941444140684840787922533903981203548028880631026367889799302142327172286038153658515440918572030822147000646968582785368359354024330624760288574425453685643579453323011215732698640375124248123170726334891120112713062941074161081167327802932044559025713959061961221684704728828334445309082236942033453684028377625636139457855298301135572484076974833644737146337637515669761210079940774282973320845954870060867786875886353207900617510588270071182204652720646872573508395349484399785869004393152792342193259008017570362219859644932504663970984107113208244874806521573097924935172015436738131776789227328629841377973490841355281573029176804950500239063787642251451588801389737440420246125717519406283031943538185054948179924131082461525124342621236474787388757858006537712009552910437554076080629054146373658943380493372380068125056418357084425982808313739813008618651549608208890633264290562505534853698348923548295987485209213482210986195821557298490650265871924070609646828943462853111411279969338390698032009485511967528910383401130130466647518071614228652497755175237681813830410374180393896949477478963982440750263719903714890912277805963431283187578315645114570694604584696561133773943575495147231629459430796920719050029636244545994682585856561415555478924403305316843417008746476971771600818509345003577108116923922018259448729397609157681213175723157166373332141812822505675792938406060658541782398622794408794375759793718017504137136685457342793298957845699684477195873866682374157219924126066359037932541156297533772215309719778953714697286338780812590606142585126217559147899979148818626785128363297893273526333266079638180676901414385388464060158282332685688445752352442487836726633325734507599254510147130466976517366173296632756905500774644740543592918977636336737976976129332676632215573412383019902630383364443453347269281803455893696541486905163617904263957767757051471171207488663938313392366153664427293311159932366262726541294500505649223722345048855463370694409184492124002841887757277121585062315212922179779811004860203380287361669411590085610889788465549753538926016679047194775862093776593363247609569704115052758346980687292829484771470826798234782651876896188467287141537020740270300921712504930865122546091357576086006842262761478327712742004822882549991672013226639747102271686297467332594041737782875422289380707104205817313979160773564264950790545186302313287892840604332410459631766820879031934832331714109625349785038856461441070599650816390847081847668906472120309029675464889273245031965108105823262055194277195674381911779993763246113548636566611224717862606776772973881698089767434091133645881778440364358047357585597512158886141058396009782115840323120255281374328263998650406767995219024169900035318768693854117615065459220849458805255533745477367372006343397641334049714947401806412382115400417451370713697373199305627116430655049083213597497148890978500138291078873804302377741483066915374660404194503257506022072575642180273611659608538633338042518590989575668162796269876775325599460539166048287140687757012168434506523573445163200362079287243589517431273881272918414342797481446249750053243328291036365063086536231295436391862102529223929072411977296858360165023769934760090500710459458111786866969347846044947865666842330396481887933754618330094880978913593950889181932100561484064372372478840353267922164881428287125941734025563245123453059599216335036539245691786949439686388942242758643796127815755280614376914561284405758668470653875255608015851775970800839301083766978038460576770369669380107012381024244408916299909562270085620706582929320371742292601322106825151233858465385295331684674100469486145101579359945648779302703824979439362226142888176314345360928637709031844787244959820430582269218567972865549636228149518857119736663707716188763432253231813349489378439158395586625551179842381776561521066590000508989250809662895734670137084530995704177168265940893788737224439670308948113229093484144284037685916815764176156802600640310565721303026290397040836976235406435984295441108337128833243556740588542838135888751085669833432502431160037277340090591887286603868291351091635213674701242936403421150858577140532124834376975172862120252548766520004520501635948607799311178760573756322240630264211483700068739280926134968604858314097059112353688657290541901200039699559093873066809670980303788304250845194010495559093996951193319113555930534578819055472471635886875444101441935643534439911597504685008453984314610894793666854243199925261527547193343253961126252267519266876636210504449379365680543449833588462323302653802399051181179111902663242024569567604583941995956941561423505391468240366547185389544628641734003602473593153592761833827793893697826102352143752400869954866976126607042776964932805998476547708078185518126654099932202030949398607920200216106084869566404537543735795202054312351933507034808307967154894749246196626464531302134732965860240350472182633865682223166895122392947611117470055527112297257154838188455274198541368447299083514161723555262231843784404969709998336532154551891027607494296852504279459107614579302352407206742427737917649589917345388642092967211848582951296725494154914241487773052461349087587384833841964491329295313280837545032877669513087578723310712235827156785404454617191811673774260528992528510336992732505164060054093463455329231797522527412543560234580841302553254686330696731268432507558874303391490004872183103114027826605129301000401147861126479505337859242007057198287676234622621232057067730251110425633583928973405507944035326642427669795850866677386808265101095267470189407336959345705869320780363643487985451741564868830739244274347169813622543592429539858015848080874584955117297649000644653319283333273797475149340284545604595319745558842406217869112335719996462258470690827618667925941151431127092665079142138291679167309909662657905202411446058896036590665246248689193445613723184493728585825194623872147829203008476171404306368030834938669689030190282999119094746481904193607808159149834518444002280068224041250696888346708120348004834586972841819122014881728097713742980436877999374541861353589875223464244824743009786305485965289950401449928252069392997959454522081854140434906836463320659006893859967546986367612730684899693951832333099326973651656599213487271563197080154644688906907374167696178215190760094836666048180657855774419153914874950397681021327935981306005473111158864005736037632865519232706169264302331661438009600431057850631340235396211426566073895840783034499665851701735818641303599092840838435014911009458776040838876875993575342536075663067433769446076270216311022435432199855464996266006154868052554678938724479520405113563979624902098421726159065201205598608434681558114734848891378384972597239181551080228314629937074935108765976066814921879912712074062805631004192218861411423076276784793315718703067164671657554261550911958845156675864891573880611524696103670104719360, - 82002090047786005431345642443946388724056209452799525483529713578698305956411118185378912875399920120083416273904112898558044474671238738806391397714247906438129333607214391688073882924372967369988437431458275620768298460774568880745894449670727463759136725572036590105007276294493727414664079538024331502798227642435807720881897825427241817958684108831420630004542033653794195844744726435150213264436622422128210744640773885089865885079425246797668645654694021859360051235069504832080565059878868306498715410093101775779814101572988237328163414391502126386707349052833169112171979875087770075377432446515360496202090283887204639266108689596134820541150188354867447099952364462147637071476811781319038425416950290428191300210449115845200642116649559868138031785111756164053108339236692290192810991858206017413599582428250274972499468501873679662120606536153478904435085057813097639895428948490114752244377573288825764573732912311754744520317236931584979835671917508709138487295621436433970637048146085309901748384218377079861101696571840807021728714890863223986430771859620611039996940814069362063925943863268993809093423868157617698215956172605389184005585008172121311401229705837755091913303404132624659282969988814654650641735006464960588217715160327068634870084469775520790410012795506466896944702505835005162804505478400697004187823873001695758680129811880606081497213428694314518950900362160933030692987854483514174451249566421339951282167041809789768131458452980870498483627523801015635523933782866874102300565776780412053086332638114535743213469557061451802515590200588305410844772941994943976300307315865466378310021770197847386234591282035687641282285754173557928709245518112320072168727370185274672523589227579789078892642475732887702845623987862705765396256028293863647819808170295602428872559229129525467054648724557499427501989498528418873199643765168759802279993973794782734580285882073059113250478234059135337207404341105636181143495781195737308306927239878545362666678760731057730959001214910832325890472211209098059918442745873975033358740206467708725402486758471340529566477598621099022598658044295439127784679563161091975834115874845611120342337339895535083526114517190730027973652844518919289302488932237811491635398157938460410244749588974845663306495673435638969674865264295652197869508204218069004475811307322723547298803451340432403530750900794618773974939217866061570200037600727104899718131535472928855591622928845676195716291878195405918242129751482380712444482749917701252873740952011477294960569452373025079896678499611258043067157530587437959377241848428398249893874567747533831169246787157686516566656119743995128865495072223800595027071748531479002887924050805022597643576200615807864664554993979158006054265385392234036516411395030360218094564309813680279362507025684265184326646538564663535040250939020174365166904724844622292885613924535231869750881507018963873797127809591635149583665285350186075993116556450686761645257112205565951078130709006814094106943147071057984702728872218537158109477720056525429571865867289415661280819206555373879783163359770692809946977538630534856538377093083397707363124205357711539390306732091375323568240597015475536502322114074004093076666700914432130085531103494943329996374573914960607312350764111208195088506971352746330376379728191207395937887025098204219424210311929658708277905144679378465523772871066465957644482776791925071603491222107880259870659483343911092681624625172587734472774389136320943175207827832161680695743618672268534309504249502142432347648087738989776055483306822782984673725036574011590029621419242823366206605220144945986867828098327511327070406739107112076544140520247959910858753342916870766645768097153229145609643470083455537165009027517547168532735327339913883330227868825722094846752995167569621824109586343459332582922478951830114592436546557161100876727708767908388176322884247360534053337418647412043062377734257132445689477539704854063564465525204606213671108911013671051606960965694975385379211454057907770898937726678032129032120910562568068997412257277233519069877949415571796089183195716374298458364929382500400297045709196344429488727056040857268007067618027260361447645389962045482566088636834441299471382169757035141832208289662032919975353281427402494973063299479588815389775507588912766505471026719836457271295626653122055442116461050029446586679130441264127144653677270446122872774782000187191300612622661261082238593339059919333217082099525777526873747876940872224093085775468677823471069426871338348226881965814802666721279042648276746461485428064934999365037302194835899273876951116748102566194417970210451783249417011921888513645606078904430552012990270203778788756485504781710809884132729059779051927382843007867854370851286104101576526765976240792376654835850003095419594319595572642750879470440846437231137529314280569998944301655697904487003235060781009902276577749304084195383335954090979877213139301416679637311815726302864108061239376618149671274533401879970649932689443362643547799539739495137116505089582069824778649740467457176949792738085168286526805838093087959902365958837434654727718339199567710011934611237005231732494215368387274800358781181223627647642471997500635590155708486210514044152586740126117629861151716189422258108385239801346172602811828087107542844427323013290812810661276658808726793514450297480818764126197015858756042020520249746908878589222348163594880844033081354392237904918681854557856647868745387587745432848773600438350096566139613974991380125894733115519438407522633263981572291512692035529555270061418591650112993547565764935507869053425490767145402898887321135405893278528393403726709733227667491014029919163144886899504455453767352970474975465474150120598042221241334127044539403682545227457708384789527289253310042763375286075799576745860023438157563017202027771979407343401702014053651494114700487870221031121967134764578909016958979109007594657432282783488167567098507827082807853082586668605150784560135428033084411550758436635458985911984775032571561143291269876452563681586089038237396591965683107643761163203967481505555587673825708312499693267093879019522669309825436288675943999459671268988571718697291009490969248549367616101954292374405555241925139121469664273013188263080854606736471953348983142190554877578878535093079367641132805690427182766494683665934801853186587114560385131798143573722294641682184234351784512864922654255136771771424602924190935386649388103921467231025617860657875829567366492302860648417528930485022933642489322671947807798569666698438905776249707680130925070021770421491069182585087088517607917763960427249821978481430081464486449524962866304704737387571710107545036305103567529127785236617512791942157157522717664965636146616636445455869442448138943441773025301780200704184326045288892991882413973970795097593292180183673320552973644971836993298876775065464539534199346221177513463501673433391075876532406485852510081390852874456672375579190271272684246500210024489537963913397241722249877368470317716512706107216865056333090304818818566286325721183352613423664750857519778489547949481103877978501255420574091752405073606902356050651163403720538466546075837176458560074982525444930999007224991111186003228848835772725945246739609476369866730803033396281448569345648772369679117779090525199820696111192488733523792086913467643521613398387302458847284695872152373292985215326953092234036287785837990318347581898521698490693372251607812189738711859011991998877689763197879010010284728975887026130696305498094496834006582325885294125822247636173710042172648042706372689496280071033380435522829513380817595117445481824332526669472208884541997932469869539820696000285168266367770088986744257426144637822312086417512400398376437431084649642680043483550903301076141472834506366942610773911439790377653153567716374413653580967141955423059668417995983607669451261159281002438200740101864814034703610663263564118693204901205052162995806517676839795616062230226854419665898515727978933887512427524750669608045015254116040280989092565168416778653760763899162140157833460702436641426904429562366009730162374503026150016429265146460745159607297230152088580190769411289925761782523702588240586405474470283705380242936949134159128167285414594611614708957313328184480988750285086876574286666117824244714971762238789879972982845010058568223461110382909987733125416072266199996180285472017304504157358176739693325670380389464090787579630979422269159812309141957833137729674682544856548059090222618918885739657915073431677859943054608892067647395276486749574426565926771208175422509929038965312354263080654492824978355727113661082925994149897119753571099939991190953589220044818956151189826061461354084959351086752497655468685639002703100618391198489185062886510629505430283185917193045400357749848019329123460075903668103034815695014435622915410920386464683177527067898451136705868667295606220275946151729067695046804817504060871317531335723079497893484558112762817895464960, - 18608889635479384540567091962111962088609376995344238157166787837143014208369865456041138591215479863352148002233904428718709044758406043137573173230252065296572209078521184170152083947742120463197524813146769546878459712372559342302921130210978103527054133642372491883006748380902509523912948266499107895093048096071142054530143198900186446142858242144987169345234658889285706643796069252232079165857650224455954801139900634531555938927379860868065563347857285875408651602242325565033561910452832576725037739748752197937511152109353817715563783154621025113622321789994749125402555791964811115035182727644552933411490622160001749936961740507050692660679027301551425430374369837388127384959318062858496230437677130185429018254598233258538572390004231801909730803527704956488786013318563156192232053144848225403259943569739596651731253174872287706777899961067516847800081294595057374238137844973407707507636684427907281781814969779718771080131356357305608092097237428764793136265112098870308424962144723058917835583031673395504743749879863874160582578868102370392767932709924117778524172181442666942916043599227877638811242631468806774996624007761267474667929833300977343934298929746165365550118663729659009744661945895751846152035755241492165155974986078938264935093351914534409697825351257630467482278249721917812323347403889592604040209005317680952690114997648808832750235309734997927746496714475414120872342401684031980950105454524107189756341511798023077258938319363418276028341472829100781858757803108787831024413957056776178056720607039775674010107996336375943092142119105881234023409658653638913493791197453209333172108745711527842397626226224824660605928433694428928037500115504660584990746703011976791883522322528294873349493828270307115544179404164207641194693314158502323723746794500861524758238617818490290912138661881703258839396200381074822579280961186491439440216188103364093632559245517562377568463170628423271593666399760877965112478891882935567775192317939499039503440235057958445419774575383729160691505656642379351748589817522211471443896065333286651807596890146562030531657515940294675921447210055734339122296778542742331585705255974180835235805899651919505995350590207594342370377821353609799028733141431188484989891984917097230026765591602109375817905960677533063671997723495028063452788459706483181609827401713465233268004503067801949858492305823530226588722204909946164760178516408234077671950884176783292068327058224918292993549211260518001902432614423999888624122383791021812447445788032443059297772835575443267345671653919550416138518170221580766853839037890260288543048674172683546258241345547639963797025714525192593347446638140406150116308027822451912981266960538716051069163039925473331210336020414734695515209547683231778645506652738196904800731426798784436639134803448574956669750296175331468169944261122826636578135714552857549586856265659426276394151926191859016526997736695694909223754173042607511297308143413767077137875727015460033060833322236551598194732186642936377460532005546238634411881502535420041723740868104585822395847786472787452264638298782969142624278202685484659374620520453402731485612425048229421837981823357599613359958398689310110541530106817049112830111021285114689286824368201368891382432170395552493984326166467064324695149657051380190239297841200171748248987713432623510499393921837813240320506141361724814913271038782450936913374884993131611356353903750501999425758037465084919393192949089951629556032037348277739489676946716562657237314052575790558206515387442794743744666340134607101001252279809022785620550673548091662064331055446831841520267390926668995982612980783792398522417649384204340232273298674154876726039287287094781765004161587363759488667785522424739076066632135139572384863144626948699962913394952571727336445145366729541711229970691782937826953158004870519925032779580038203590100918239423803331879040351507066864800148758303643684963108917510201972811172774144029922759731012105655550896382209780005657675766920128065920536861697030312025278770375414855652185571803041816369521688336845806832601644271273988608590101719929772521910831534970138154757880058068588536634052054111315829764371915050685630103925850071223666189965983186400800407249994290360893307085325764357766134542947651601417866682343336930621948634722236146245100009855651725210884199874739681620814392755964768351872335969879980887350601278481644780567157107580018032660478077093477880527990983627170773492079374833617402410954501554171284596775835871695746254691635081131515883688031700818450805468167222864039154378812656228468119109528563156257245786474824345504860354578691657761676454435452420493398379853774724506592707488226415350193404972794400454643411665027436789185860819967142465890810074386456801929004997788120581633785947129605475694712369544120920887511186476988065862449814266316867195478576012032891966190174634388964299116699381235654841853969735331639993924056991417245772218603561614019455576461421879501586488525771181125348835508186407950590523394581221189066620850981768925227524077493515800026547747649922622111798802672578583107454047965660363506245068377623984901396791189599759832847398434597382351385722825455184450749092565365332333434392107160452795845919914362571969196637459435679461173325123519631460401290011954316575791122468229200940519677943760177288413981052126827988835384500419463683806300115479510185510257636203840510343873040124564622979770470992294205109143339974424529599300902009728415981637129413064209853575707328801679950755855736201185714037730837989370437178318990821016881461492416835563906829744559702664360736202044701141428879647446511448104050086722495283604351128738487021315046703950534154477176598988779715869825248690175091260636239080136644492943978400761321661343575977666686474784685141324156579473297985114145312117542471007325776257194661260216334376491849278072575701911841485524958017522719995438181217319104680260547548718504684420944055150943666721531027627541964181444721264758450391570562029327159391023798076265776749271887486591566367014552125348226097786056667111829548064723915423184824536423514778009917759084332984576237983255303022933521811764539073238768043494333057599108434996613281773340236456589145096295512228955749552179454380056771374347334581782713363348614752403908211314635394989246035501390547509667681634642787204288729574807796776865650208427309338939925165439377898498523078812238486232800974704520595920858106194435442333448544348344440169189681328207958618963361287604617966308159693231260903094013102385013833919511726246398980622534463452622481074403082023118739943602788049134147937385930888089551402146000327859677477614715818858718991304180309986204978771835192440850431133662325982978177677918010707263386070807945632863245841587676603528964872941286658609982522533235681972699147357313854583707304997970205650879809263426906602925889291907237144543804698030152222346435900657205374982118889268814715157891860590028206753376452681689246940286770024408451386481700534956090064837084657647623082519427489165414861609466608662078430433842648132345171959075347087978064190390574708929357357021006176003933380736528194147242921318306924342230171241432495984625959046031882065877897570602273933120738595781798790184775901924982154650342600627663614534505559644977590382666508882829553972826654843717664440882827616216971396614272646012044738431236207242700673853267995736642343053456238405908904415717700792634938068545506905875046255387508761962954426037864625701446909461266035933723481057000536306496135518330199976171226575790620116755838825772124437307133492087078361860559173234009220883395488392755402442501425460458992941834875139772634021110484401876091676826984639056147525962577751255235970508938387091307725011278885733867273021151558975952555924061038894496291463814240281710255535370481875698218574532537933486971089441640019097653359782730878091471523043035043572298388129382236254130998020464024412106470355803456693746611619084706466086205229660578859527703164256183081096483000739286405212279746589597299015091576516533724452184706691458848177553644505833033818337283820878681095253690559465492716905150513602366006014578938915480464107253983895861215251153595512151466270979875811296229340636505191607119105562831716391704791963997944830810245228181737630210352024750563456205841585388088859576944134239638001824485929139487853191818041257556888514116259540031271021678091066715137623229483662434322007548658075171313074844223315883066314529043147828945114752394419010103825305993439554693365425117212254688918160536124965814803169540583642469342280604163348937536149640165706677040134153074657632578646046347550375616772714408573517253792722696134173513601145620833963837858579065423950837367449231811555250270488891804336642750621222948882029520786009024957946943721055982231498955317558472295736232065707807256341625520822653665858187876267156678557558693452316672, - 3984355425525582509073405233229752376840060357373023636671077517045049067241337255602083934513821183412834822700243032713153472833169642179470347594368662448844851380340136272335389738596883758275795980349117298045457852746338146859887874703864381200955218837412720625574812879810537068835479001900532600199950956464031176213398723268188714935813203470006624111289737039788108131042829247773216366352955951961370396004770381471474894085386067397200291246256254261063950665494609225511252495591062189538067046223831194561366157839101566348447972817223614286665914481401786366098026654035477158514124791594164064926277585537566782764236316241693631933210489522647083547899848220846918940372439293418351386188286341172726321926043616069265584992449461155085572779314056162469559349460644291662186000017574518703008882455804296334209320927664194127053114821567333227288757178646165551794710107138491909422326000598800134296704556878679736484711845472322339817267438050807053750722392987934974790029803911809063494244266928831519915236237447615367868738899665616195794596665594342591099752115146907789514098306470168227060193443947113546848004243490602119642368773634568028094942956300754887165090392861308166783304521660977371700414312998506521127555101550499062179387472992834746349400899118005743924637924346727673697042168774047899219963593266497037621457915129009529016682859509686588435660825905891350581205288408963269686997364481334153848261636504545252548812663191911781740927426237014481191338649728133629183036968323939958521495097661955577026209831413308220423244326197105152863252124705423378230853734322834620885522846558720031160683807404818056821191359935033878948425552394165189719776759676408400053757177038514223638624152073376645285447155261091943635719488878579395956403664869007681839954672307658469392309737118400525775909573833884049633107044024142817397634835944289624637588832849236904003809062745560807825208925087673649507338699255562832195355778105833996741089487405948235812594336892918717281079107001457614007445884495244076590270509690774046066041760009224791938081715448232688237228369745128503819805441140641553660605565827501724396333060284575753735203958929197979707717743339717993298148206898867967524807864401650858035383931823575552947453892578660844725102767430596163353389045919482200519683718128249383687662403757094915550312834669409820619424017401010243325009100638575413056523571703971092912661993967040480087036517672586935612517267641936969757746622110571293978480632138634244326541943273902120231662038646682082943071699946286115616228185035963621825030799301742091657314719229694333788711652526391655136259054206738379198315293570461339049900494391957579884605323391619960922194985490934858079908994891168485897607280596120565341430769211649749965982824476569305749488360010270356433395128902127192593578460086973341803252790858883052710373427442664316675366363602611535915054479275751831172009264623896235061586299747693461057127564222433364248902129323038693101172944384658446844326581949882522760150697129084083082624611261250942385872933103551159850497970957433015035939626292402596207831132600266908440769952016921100993483852917262182764243905102123881699937496790176177061506052742699370174210628657148251626923771723088105845808735509680131453569828010796996594203184282828796557141610940582058318369686240115493840894285286683990755805132203101267084254807805755745825531790103720613453750828557362334002128779510669463049050280028047783744944469799821303821159871213015331008168275755981585355147199761667030315530544932338112762514366133566019161615895907687831660711210559882904121031532154896921073939818568861812943356764825272879513431202913596406071848581863115639342429899586396659964769657464028380151636978528076372949958091869555071022112501648361726783080200767097929935581699095357713008928265405472452147402228216429640750455004968325412954733942883151798745543749813864468394713532684840000645591136349966051450559983827385181049734493783867196727408772585860733895811401170557135395458899695408209219503226397779609960398743165650704337155324910414751079656617380425370392769380307517855649290500571997307876534679404839527961713975401666713227257090503588846842623324078829123552606660078186989416731318705319673107282386669169313864785511678140431654329687950100599149120481520280450569891770319489747189292051234911588535733664106573335624267145366252700146117662583279514530426888634047008350163573001563525734554729633394887622870809052585925857918089352490389941606349592164128095671747239123873638941231731812896894907260941410242300433308765628529778923267882799204030562009718005388859096215078164553226387729616078929977210122650007466376322491177933784271108695589081531220543512440762474101004017225603743899070608994848983396034196761784702806248237494557567086532661797024929467270498937533076078319321998967418249058269048521462341383505398507956115051046098867508729519175773970442644669444963542141974185151068368599532529075380151967878858296637444230077585269761178970221044069502987698306816006148537886752330161027041446074994784422024637305249877333892634041474597102421755245716860438517588104461390426696302150356755566011419055667151375054715470605080682485876321801275069909904182316330897744866531934582168871619693243577214307161588469968406198392918262467498084072283828395857173809761159224423034921813391023407499730935825947833248196747646010117048380720520746312690868908369023438835733967990341291081412740918474146345969729708593738336281303040105955569231319740749961919027583984719725512602094117251577338690254748452519440544268652017157649488701094732657529031225220745771788534967678567269173528792312573713501404880224100257311052563221764575678462672399392192578241820989588243602897688720027066765745170006644121469145172526730826296093627054672572834816770355125324589203847107734434546564484985244270979939010202688027065998918159880629169645485135220615113865515810192734474352064501672786161124566091907581028385837520021140696306804222318137411616189043216381523864567349240879346947017842641876775500392732903116859770993148363909286008401704721420082584695299722647037571325560963612203900372830898797867375382309344944621128619931205539863134369554051751344000822514283575948804221610685016026926347920940345185565918446117179761519138124458117699051586713472549625065657150218463904616243356475196372723453880294452377365801296028366147017648134150736417515234162496696247853354610918211002127178906183065119015363622015223837758752865422185435804678333526853193577151729477812200492820652031285302731190691251394003782670165025765890832974281317462874534193232633501281043598149931423626917238661031358023283942063395287491285348396959726248353816916789227683267999017184610654171282127163307658629330722720355391302666352971340597902980303553480392230317810952905124929153723251964421131112069643669275378390742212892459769985511413880264422179001790336687917181357573754993380684580126421849281909167714388758591332329706188537968774846223267688637409742149914448429068397226367765542136152152111904206015065305708919300404469622851797087760917965616778593418296268741116703660830728578442969031396755984950194668991099411447284144873696127607463926197742245030003000758320752973715373225553014210264596401411070637876840888252822993848718203714103930625024804383398699267522502237653086508695546187713593820768913544696325565125606419912258046430087085923437552821097011894874603518350808400866097540639078279946662833677140798756935553622194781185745022510542989524480184377277742288983227165082325473936905090823184227293712314774038736341242003713032767442332768161183732547666991257563396335187415900646747432945082267709634019060826927183689643750049741075616376705262738778733497222014480508571079722585983235237873858471210441463020817956141498822794679699127471140159637468818196305863288084810301015000606501750112766049893419594122140502815113584356728726213839807493043965801749978390036797287722886298131945528810205811029285215007230689515641663617936098399666314164751717434238628045354075597106701014737159739030339917993364512987233246498621469353398380212303057202884175099958243433148201664472997789146661397840476196828893899689315668968945554820764874822636789207313689782906072724067179122614068775914678417426977579508176026405066924557558069686263657973085751677538700629661955754709747777104271135712216291217413605316385792591870206145716215849454130517002201366671362554313532636077540087793866844189466367163332958337997388910523489063950473125857722388827583976293110704334964754038709705242920084851124439159444266814010397407450333606592017476127315484169152171439099954680849668258582473293344916612526857181222470031366303821493027544843762985146143859476435577280018017320551913972799817730504521534023597974160464028577590292850881918402560, - 805304592379866196848728409922529777867003859052214636240412138145793795643414762776553201823911264352733869631915156563647759829287197140680242996129504223744978754410965459657633067212798805200538246233454176672496494581014294187431858472935517806970371479634509057965308518575045006344514685040167662784835103797662506950532934129210164352590125909183768403940853332257606151962138446503830890866984711082207253424271654460090522071267939300903967858449855759952926006293471174635596688550702128341766553896367137625865363247074055104790457304460780828725944820565335500319296996679859991666285897270076240541505447302201601807064437900372391554418554347417679173699319178364322044450536070120546356405531913927956844767857402763200543262434796984578653174440430349361118446367139450726663319570306741654493924954279715179637089483466205183519488269862667182130552424815414735527243924350846029709364110517762886345276240834374928010914213769912467459249203958685517859676779672936476154757759207474509035677431893500688696071264463986544867143374596762374196814156535171282995861065230777678399935458001339516035769307269297876094541880490457313089783158674429519016710124889654533500674530395774967580530720689339205829551914378758536810818944704256581340424297759353852072845234538800885628248444980499351458520653923399362066199430242733345413867946106757079045531603171194677635910270454140539662656524523687615462776051151541009789169190411305474799470894647840160285090952518748782227371436888190709176759748462810128157521218749873317694457800138599097483428012051104655581176858514129471227117698960355839226490105261859929212892288571634725174395027454750013049651302782066104383724905103420171046992522844351458083804016190671189363548727281464630323235125371858163989342943307052135856115683272475224684402071198207478113618652348395145641568750158970688365521707419144122741707038779647537009200303041285272311100994879897033368815289398300774336231990456557536477441283239264356077695000332555530244315367844440753885676189255842797688577562380745065045971321855202935292908367483268671085811934933666295522500536308403251066295613084646703796979591137433478863711746626157181459885625951017391467937597426594959889906734205590547833040913372188866649852177492083865585029423643134079931274497240982571220396268371753830306550658593284698287928671446284456713586652682152411218523376684798714403609468789235478293857358652065900661947247204521236040563977268209480336016983997295191468430774838773482889521827163752659168280586371725822830842055283358931285137874029315223592029930391621101617957677044828197355810369454335483548013093960846100538273338573622306151683605627676394813277620514352699767155907398300016651030032505431079622294660471183158264017004852404488397028841953750402370485833333701129196554049660639908723606270191338558707374423086142774336407787530701319186639547004513127115871749676805156329611247454058119152114458807353700400678953367696260042738599494520273347757245945090460533911700314541552947183606415020449617042572582492684804878662700508031844818608183390965392718321780461757919703227495531486958008224399473838287676816137423688284666422313141171942075815521413159000444420317686772870477759649358272492443333007208897917461537341538724763630162187489276866729293435287614916083837138398150197396947582588036896939046021441846416537744909031883787008651885144949818905800089680279345941784630954151954643198840160843035232055202440853839732041894635668114846420671805851539215719983921961397124414829002561249548093381774437169247830597446140849279838725964499844213380910989198536580848302477441030500117862313074282936838916744884280390431320044579023031397710552416394464150912070699756420035825852444778182134061639796415201444558156699126480118458713058161324841743563902969306445782048414224793172749504884351929020513958585331053813139032894982592636292715294286741093006236251029850486023039466548019877741226198827417961411329759610586812870305319947461527741029261573079253146045250780868055425266428704499554438589107502816255289994974328636409971215426457305561007785073485644253986145787848606425976359996947922138912103128611772525829460900104481005925361102972560719320522764783432035119156696743563711022375504085499120612355937903473426476757838187829897576691798857596573331073064909059939183483298853023327013002761955198136884114069241438555505865702049202910147641399562774296395029524019296581935169497293980433099916802257046295312220891201382797676071757026805796964545397792712901827178489475014621647816477428871302160371806486234439647525264305299863664123639101868242377229262543631069531223670953920952308696380928341685543939930402704084085838593417613751825788682103028428458985228187464616809466044118712991915980527327951166194298065365414801794489195783897254402593416196934109590469186132510730704857011965827295595381685048185759063068251481666077288682534781738083018276503780391662065587215062174424241700616495436749480557746949488366011601998260855814318911149742796798526385729172604245727430615466750043691577912921931533154848418805012772136520212648395809962393812414214672008739031275855429451918077894199259228432181352955262396656245064011786955811570457785498166779863350554327864405145981543193126726807983651620445798089406784103056275848840472203474295299054754316619692059749336231060939976349245238546024372465013966336932241404358437334605136411550319287095577826546498529519392006991038391675884224268373787923282468758926535942749536451115914816113219243837160758135818371862129589493745916393465694939133914735515981378462410857259257700356334916967904597778453527252889739597851220462901814499284501406089918457163480708241948677817317043007578976681788352657909685934246346174015639774181782342808969220885267368036749847964282424305683636659116056860713730549097074610648785560101344985013662030939009861242639379665335754399332926888854858963581255341594127189840922220897618795562324701473835432165923177680991546292674705408192627761413327154046827290114339252465121146396028195603036144433950300197489656215201175604630770681532894348404337571598686348420304509438687433369936618647769783719209740754603188287537116248894038328168225832070873027918713005638077940627738599025909214212090691982013372553789367763384743485386488183684121494378704841556766082864107519418300420621742537571804737455784229375933630393444853782666848038995952713653570996201431455592635908411524238131554556016092915350182772767085478178405381489899028849209864051313298331565911763291532377540800754875130843176873260863822184219510895445287274575443036981611588580826405366071253126077523851299755960645626028312092950167778550061304680924976685973188525178843275345887081997735959071306240823882922265736556989964957856185749936979773702125339033814038516926143857929234666827482954392866936303387319213397944584096089563846124623640837784504806887304067297206596211579556195171267803081577635333544300975211101218958548097283087022444513882241001864079157096817657033947061584927048860022487591565824776751937609081336159777434809255687163094721813385436657356038148793671595030641722500907322423414631507477296986870036848399099460768383987186562386874301569680569195173177909621793970706574738099142430823259189069484456637097013048552870031700676861507403123948476889491469879697995177810439807164604823401347822049012989506601064768836435456697123975049227866632035350839583436740515206803743947935023240625743220457983396412374533684702407333491046817744269326803047907420017064783218006083293854925406552954403007665087343863921975786734570898245907376959690082669075466590858079186266767629373481896669301283241123728925619082992412054309878791257052900312305203405868654200775081020064857448295842082090220625644712709128888683928477332583749551047934036757925054193243454092746683828672836103605521070936705654381773935581007203512499194492947405910627413616087306674195073992594015517804814022237756039688516085713032670528868914246518449750118878751263699216417951327991385178557914579193000842674982076393562297005302598925895708234599505809960200761199674361002357644218291396403804983240877570377030513938182718576504832655147436347352827771906387896699730337610108777990163581666240771134676878895335914521273339783440989238157656192911937294862574501899119962625023668872567235763089481928702276821206173135705271268438931038326814605833291964361526582774113594044697666143434279947125317557427799140119545392405935769302607528686983985740168439828751975542921861977894913342948029758887371545477274514604286667150589806970863066013535383719479518121569716533807564467508749358552973753934419309274709140137065628852686214934515944396217238118816064901512004813798005236478870454375353416996039903993849349351960284092122755113311921174648669076296040448, - 153718653680947729715969639531296872312993139600725212704650100820795280234009388130517655230104373979462082703788533487595488387783752213337664136082547334249323272143835979337955186855537222252230939703605351488727330523575642511849832015220698174867048295259506403369516653026543152752434503562545977855582030488646638765536729430223853120451631492099534316521988192564474478959566224041000956352426718716972716872433176545959240770660413716459833319242293937680271313980373319545268407583845993879466124731711492070855129465930863654889517559752142806918763481563147751513832693017051302553549016362933202746281546177915904573309023223961631864394617491909870906892013253778369952710017376101729982049689539561043092920543098198470417256079695922068760435266630601442988372828990263547505898746935000623745980038002500006350711758554316390422101014470370398595089470494408272663872103186608914388708343017331461439161070925510728009924498850298964609190296634418776869803770305844445240418219052640416449019229684893098286209401159495060981220108060440593693359100407267840870077211614249063650683581554635568097374302081518910226615373822546649068763245764119372573009873574645583109990337665592499059972983052598122669368727243098556190777625549698849420952927284316244419086394703766036574401098772622133852287175214336575897762804646058385471300111016287940923765023654754195187090047557641264957651195457340575340617178102278942460103910121932518459922985982281463470693522116162488015015095206793839120522115698738676187628855596440355109054477305929522223231975895155779310116738055044207019486718976280259836542252778738140537957719520885645211111231189344255168973981864147629304256901640499757126537286424656125442435027812255351833780268495788763206124780001927710795400923326493264037528211300406288117632467315096770565712242854039455649203742755719624858724569984539878118332292711710388672700065973930745738295029435168401104459557236817818290845416897942761682316808287155359136718628686353505405892759797192441268605641894025890382948047807389456576415123271405885392877616459643466254473816277985756609436339535563581816043358288123954294902182874781318841853845913143643302653254388982848315096144475402975006396197206717210095905937238056747552469406513263132264796409258095801201764106480950606503964093941714536846827410959931657073347763312650792569851951618902967932313665613030171039265350852056588764476923493917247725974237467710261548008610983689226644083735654357005843921738806494677097835505950386393412940886786600763813892125669055949885010672470031026008200269688846519759620525155774057755379896188724602690765895116902707085922083663590300782257824211534152533849318126168560048801238826676632965035059926394500292583904513586191759648027945401261845716854516533158643127000413667986319317336245832634007311878324074642192041572011385442350888734195543063819604690399873778459385639278989957993917802463478717292672707132236787530852262776351976036026650867813755122184629005519685991439833596828954614317008701924504883736929840048057135294926792437837754892669760706533090230584948734082327976779146657880905053875791796072557240085635403767536171305494203054752383437362208452921311521598103873065684350476878023190885583765143901585885608279536575897724815332549750096567495255809618007430915304293032091723883511960219464925316561341782907869014690490729921805627633587268878997414554936346997933970182248776638502477594347971347424653174200152622739833104383105861766981441933553379525435962340254707609288132563892411673335846676542789512865854105827469339372134646505331209380681403177109321718083689701061227920732908430368615668141631441746872888481225231832513292355960053894071144731462564108367146578730640938581985303371106253673078912825864786835277841668296881068943046543367435610778143103654369002102165508397815154656814485927591696352839872504016416437694842024111212163750618134817030829206424174347522505990145403921539463830248764882422014630781549370077935851721146460731621679064286786690790806702555819597107690960973032219420235559039246510617344672354082914349972516259487285600588240980755941035044749476574845086708268176827523511136737569776025592839836875732405681452767665810980479535608016976693654746038208156183220865782492059133690650198125829504825979879132707462229556767101381956841842000452887264862827981256094402066171909007865151417345844421163102237869731768051912250152234088406211333740507397770199662635135756706946213822844485233517200079541913705602712148254221779433243133218963131662237089945199461197150112941573319757797539212887856678940305494392522796687766798805993198035315139165525619865995408976866950663493966899973634953354034604438413397953109614231766621269486675116144737420953163234618702700057893532531812091470324693815314700347004074397280697285476740860100497660609174295777769407418505732726052512168849428750378352540968113483480712452290215870615534247502629516411149345728982471142809963779162795644232862233231049717618507502336261468177969577946346849569437616400335866953471240597554929614183574240347388597464003074969822688521239049068450061579433094621870839053014644472048945036908279634303456693056497845510049954296772216619513820572311538497297372356591693442020282194147520553645271168917810172045127664802064878348281977845322820609456333161864623340938505223247748714184078286205766786468955821122359524417215091000417777327130947750564558338062382802910428023395412609033076777868928907636440802075373435358290032201970453339998018149798479480808922007249455330609568328248133283138634815077634621678127959144409928084041022358376011114267489578224159191174642360472831897477636835266555720340108618547333189639683944270286132527407301279906344142958997701389552647129604067013793030219983038110981184389173538668837132564822752349168479028198679918631566854253645750393785831895678500377840667235875994168832511600580222329630779408060532684818122775718320216175849065606489505896110724729985776323442586404010604158279492249616999478578490267235624234141448766679185349372255892999535937825975561651765554016055709121927209741632405188980921058207781781346476823222431869253315752860711376665459682463179860499078651144132384371951563917405207743731061905210841270034618454119887354321227689790971277574013252506015211513854396046977856156486458672953220654084272198042075958046403485312760437987096899410247501954241335322268670422507865823055980313895572823511604164930730262929351196283450647971511656191563086250663996385913415829470166022376216667194923279990143060697830848271174959919462189552128169838311386447118987695277046024265497807209865279607074621674367354688301336158177311623615079622088399386624470109904426277087499595525581305208342237833270756182939148232707636730335712468119963901407121054858108037304176142536842983741098493179142487587490758831384670207996503099066012780893590690341258930181344649597934069534650940693159495000837673440531724216920465012796232150378538801280890684618391868935335784122538914508771355948560911224665289639508654811291610037030990968257335455128448561766850632599378550699278724568864552641532390022732519816847801061761151078091462474061730487173817877079410810778948390969729284712313394096924992696571010759016663974812546596751971376147814104330017385057462661783600755200151740272471432249618995456879719377050541835744687606532759484054506851090310788552785428995857323003294842190935365925306164171503178387784218299134445825708447183756664792985521427533049802638579951598495027265361558468402215629782643723517588988842237340545835286966209583934349765332307697263268145553626833284233165265070518729217559202002367949347409395002765654084273569411239997691400948840046245072465454283055621054182945602049853422297341343308486187577556039294086065552852122561761205611771792607630833072649697609376306645642328151325418937453048699035320420743000625536185569198720006460251995170169578902714016257739711963182767476454890382222896532612038216112063128460705135491797283913861214489699234978966280796944296782197276981334523520160714768628965740226933560734468611256084100819231997837441928337059218022493057612796624261786720288033676409493628506709691865229860456776837389287178554320912575926993148064443019493186116555364952523589784709717471631335480551286247822954034073025868855336459026931865026521407609031568498644188642019237244985793322626246185753717996863735331963220312325649212102898031286653156610987239108565807255045627356013375398094501422561306158752007025901665179850307438259129980375446241978104456734463373330287845779520092373686622430087838101786837066604987640731266234883702975565441467545635031916269420586795876976490730544215338632022962839490075706102466322290981273326388444469156964954145605068356267703235772416, - 27722604391987798570820209960097013291196777370369156122334222170555976234798721422330249603801922866975707398910999439158420962508399228035790482174624984452972273561108732245094653923493609834859307656810852921238868021956938433518931541100215563160638245861156766927847794457485486896471048023442574753274926753903979158875225716534687538712025944384634550902824224700276381280548640523488449906046459063248353662537432261438687057867238338180626500839814065163942811704027595509916288702960352850118959314775146598906797135955325649309524027140606518519186372983368062196593677809009996176961566021441801614925734269337932748522504471285550777013190140959733000306251815631591995281481137099949462191438050641729857435593232876703849831933112289194250520107366906366334752320582626476505809196760470884526861272634941737280106929225995487838127607985504391410828235111226522863351166929393592579884347423594197542694650888911513262702377340372842775313131567118875234942508769448707481465785608555769722115730558939051468454013037622920750618670092646717327658698853003409588356661152782676002414098179876128620709118198645424186735581659550949066270889846212074413213211030851466964813106954525376836196421947483167029661779773280418722912164189957009343812411963152995762110178003294614520253038732353697628660198148964034724545002995490818505377149955451091440916000290844883009822878739007609066265337299164667827923903634771687794673966129288366266584869642692965087172460011195675237096688106311758163437301552897999360007273873957952399193770734042661893464747858890563803671320867809157932419570913552171127546815293168366945745613619312150241641160847837274868693006956361708369784334263246512926194202905591409067432133159620030269144338514009952032535989327291128564947436257184994333341257418335877834763695587740353328294934343034801933647923603766596628467402269682209090568780568510891034608741589562552088824195749960950175756264451334948680781213688988974234946318325835721962679653016683223930985025050387441876920700071822493472294781618127161294007648799660555979418460459198729716217415858299974725775191835269577317437592518638172912974831672993533652257580428733934727632697470528216407880321234952907394447081360038733172073263267096209648396856593485673585144631778479799807091936382732884825435870435967531231590552940768839690079072838529782273161339217570302615253330248983052017617747639976208546333047887147003665184722206347958971401259854852022679494442371976553574089909100601701927475106729500597190028847510491653632884420509502337788093358876722101946171186299319283925640045631069617877380126567783738557085934472011079432976347199349961437132959271936283029194792886736518020923126805511403651737521017244314056483896144782674523024801156244206218570894936484731547356156971153817232878875323885967637621585352907652702404711718731908184894397231249140853993962075968216358666008400748531773572563767364660202030357684692351825167062779550592120055025281302876541277065926044629620053089840239875674145725134236623572475624655534032803033023759229622304329346531115975255725688178684995043007304736534813107670349444873236513037604774410358983956719081458973636385946388582521068592160931912833438857720647314922263667658866850286585008809679644271902952914013032720496221521050636709933217268555950351032230019693125456477869278756969016172365549103830073231070018472784216845021143777479863968008156295505218926739138589741158821197915428672011291807564854826022109083825003743132265772361994007912645465582294603957532884225891049280483929186259478258831919382667325788102080596327474096551018626363753065559887216723041699299827669821344774948262229487856247792841532147982426805086981682945026285017520111182668936596731833598980216654130636854109128243584000562419096103943865434981355573173195679706971110298042074795586278847612289640842408228751043611782209345879425801133654659311220357560995657179870259747839947299987071477676598220931262308604902666866278560255445644784710166339481696120959133032907467165970858654009412321726770689526435833257498049865342571124422955118939161776819974405171975359034432653383409283824551346338519265160790828506477024877185473602252022699411756723618145586165538413635301780848120051995462555888766413213337820884382127431270274877935744324938071673418548221009549249275740642301897829829620791458060437110106128079997220552557811799673250906428951958902496939155889469936423064422661159897266752800403525808243199706702226367864014659195691220110743338189684570245813896157576824547966941249725205970619842593164119901999280125811233932314347534662216001403695014291728097399379577685171537841176470743179781602462175709592898687699036447307550937851664289007736026505170184051135870745213176097974862568783356673355453087834400091400565128004903831203695512647172054471053390706673491046673946466189487109618451984749089376035687115671459631514603490948669256621163063564008871650670188777010383976734889456436055422489810335311117992145692359264586238146523965804712992520742608136148947739751080007944839492290986145919522205969535166085322895735921727071414028896143888876473841215514287375017133993939521893107223357382965694846872230464073106707945211273327908451111256946666853949810058460285262614000851536380802651405879376068805679407034042425737636000367096022617874002560449346887922001687378745021432781316306617778118729262533188222312639478528197714445061151063243542247816956375544613157473578887331571914966662572914568329363391421160133730126004814586655573899477650315861591938117622564889998489424181473155375287612733208946153809787029170929723625717285814048152876413203464894354365675050305859308141097913482781260168553914566272107021752971180428000323199991650480117092790773200943864282729337377815538330973652149781482357947110674253731126356570575836574945991821322597436117980581903105634643117526030203839394335686391929307608594675735772265874841279449717237074202330388503880016756064637921825149504883189299642272872776543528238241354162982304735536028169764034762956134900167252908754780976379419293215467749632747206666377245945106206402764892754327705597142622136593276042977565928738722710642878162102184333550784600270767714563558826048820079878098356515322973445053162880466793284294056745633257138723787091507002930458025526803914971536439331160051378964177383207531999606586317463338647100596267977179530200038970989967489574746006110556348167964350453664030266255353529113679260978955447958511333818750218484611322300740784880626006079483617424709895115106687970702202490351083983741541333922400349411774836478904291496520121327738406660302684996766385601972447545198372500169518559169938690143838255280472568200276232652932976904416386467249768141117907059391504551622641833043428575524705610145598180034619140763116742613630934087197075216021699184850120910845699715265650626806293313606416605579355133782118485700568190515653980938902269285136503179525659988114186222665050449127517335696842162602186244789472272254708559876410199284531539484939711405897263838664088702232548948030132510891768094231043957201377197750133930441004893136227861431602623370317481443761371015405823886925230614692907669705495662491704556715712072561471226626696096283679779007175433549657129405572664195573470542091566557641712395471615473204448495976793566873401669333527965257610467600258804823694279597702843697475317856825611978404100484428908868194951357894551610337142475978432573194653680332713920600880610697696862457280857131042669062585820420903350920462180966615089103629802830390693025847502737260661188492952911328279571491844423239162964177968274594092263734423218245016383139604181596214448137405780991306714728230174185699986872971131289368638145937756505481168675084730648969700178979224287796254446255119358193965799274924888631475112316673734203014769480008108259461982519931312277593401534310364423308801693010477787566215636480269170888537305776552182387356618662732948487944093340366697090223300313409713999994024741153755700881732147406325654054680466906592039104119351118001637394052392225438897536606725548068603331819580943441955529391580423170883221312925286975085823070588558562810822321319487030232082114093445764046745769866481436937081138956297630634483282879387181577879805638676591230176237988090308597334928369185063527367818828085154138258632600115283749749944679098661074421109796725911683257944887241898244700785982222714767437744003333798798559485218074145509258674723020906198084320727759371673788270210181001439733200110964501756655343843825185847610866928149090587926343828060968193298520521968547894964109263093787013690223274009588949342981519029345047200572578729672214570888637889988905421654279269336707293699830860373101252164657537922952746819936845824, - 4725367926666020040105745126640417034016289017545210841080175685800333545026236217397311213780910927037828163941420083777260639014926478093553648829566529520016114594421247150454062663027935607129610013624699609910932046602626740793011351907631258157401839703707143086972218385694921681867721593889584342892482627840984774345554943268569365651837151910939139758625970676268929447629663563293995296003777147263143514169407739044715151184280788278112340235388752237046428259820519833629984830803897913360160043865471551381954103866132059984913318435210022393506876088652964013020398028524789322729801326128880000131066907175847350321805503197410909258832832089948847401019878345565453284752203251216977307850922372920871205346806487530403263285903220616581625498053702807261301998072712818550548878061828545507295862803688430822972355395174381637262501702506320675244773155324738226852173517087720060288424324673909258348668463845598291382216984660076448019733656432026492346373024324245494881047211802805957993070417763502993971215433562639709134385783594229750634901367399852983285013944325411932768410929490377996728609647970165170214582390335498888069556327715346636889281835204174286447261378207978230475793416903843150039322730855871206650374553336737626992669290441025518832786396968590106219123777577603074058775116248659594323312079882847640428859200534576535254547924677086376337809178834736863907755877578333780857133960102979276602571294916881269973737962492026461766045534653963739265892237476637651061288385601790949699511158042029704302078981005033854689635436566289892905630001353839132554299393172277537621155721140294407804421977326102869732749102062537478422095141385037829701698801639586001168299533458877914692596006826451844404433774363506438967477207857005503961266593546123836667004505345944423050675163684630814751611939225958303995362970199936725647918245268346219044661546113288607204077337007205311602137498803246528658440341825017691298678895593354636809523564595756046990471106188269120649534368645132371360717164802092190000923722140143286230035527879770953948867547666171551332062767887455969715073160569004932675325763943943850342900031005630457919969659392320783783673682333180440731644172068163396674980037500080376650373279482019468050611561756053701758706219954971447191898620424223942071846389541499186124730902339262512223743694454049257884005184119562200765280930040045283447018239373252269384117545186710187798945111107426924083861386671480102536299216804448277066301007941397035810307255029844703607601803224096825540900524344523360063897197592642882864356079906900080629250553512247557516074081800555525405845385227056188840971595146779333478972203067577858590184808703464327473446273860304955856302638193975024287667511811366034964853529395468358337668220211667197367543602365039104750651189303560899376906995386861838840754187483371779770459648434506426196683278543084102680252461008202242373301561512432236668667329050249515034821482170361794184143132761921172932384669225452967284604229411215735166022366408542778290899923978243099903277975428498318707348462616838122160066186703564669226297217861613818903903790908568271909777823668800437595086119998056574048851966395529616910553561654372295662400124668280413426491661180501974730326199418717924273473806183072072897513269427520372504380491215767311905931770280868456117834069744771025804492788157924275454791311239872514979323579463188245961734382836120424321350230451667461928639448980303875351111793336254263899791928621135234685327177454474757258317305097526206033428188558723358019915226613454288577420853911695931181643140915722588875411434163968300143852985094717739064325767130714671036498926165082949909952405149198094363763439539905614111335067643737997595177533160168414642861396981741841738810836400264017789105095568897092453278869469430415809326071920110511014060560427062781512861403249410453756992315619485977957680367436770019690295923953557192981285595045178630499510855808497674696075133682012136539528737595010867988561429199848678332490805473530316455717857699423993752455145876918711899270278683243688981828633517276039889917832008472879765768049579012094782555667110748665131636881819749200308967915723353853904008503799900124862101541357999897042060237003373296379196104171861693177245952570623785788010888899297782942313487058861631880031366387359907447989047725201658078282714187505900018257709704143910043023325653139632070908212568505814641372257602560826782425256462875978488111831094496206688620137675525236563808929422351165380194302852455722032709666693331538231344524295245531462475232431149571264774290773589224351677273254233115549883370125368318404012018893351469330461603296324356209246656771072003290723837589580887999169270955454484069495463893185037960860266861811896390699130892159161155531189404402634891098953886682655145217702705035290176318688645811127787841678855037405736022815284431719312019976133214093458851344973734027106971290010589042073049049858385981749889481319130112105688881099590919716284863187043288164662469989765057615474165865688502773639863702979777564098907187639728053662273087470254418169078141087932051465000700090179386254627410660420372090024184005846684855803401460132485754051742666178534862112661537977089272501866859437397124103041290601940897687605485561591828108200305217330427154841534606896227491736439609946524700121410570162391814081908849187519343222834668641629111345855560532580142868975152398814349917332957375847059572776854109061867593917395338623744596430250009778805551006527408291067231116837481479753099711566002064361764871285264233502578877571139242254082180949981366637245225842119282579984674623344012825391398780321798441717503186028893144714278972325565998386994216405585989204112819857034910563412105894496462696480954035445020381466212492703657794893169952973870697607353442278905076922941860544564274659317823626435306453045481727650936876766571523825683284664847082618617305238265220394618934147890481411229471042030325788574939305252023806128234824263158430111608158251620057582784547146329890622283646330480517046181143805871785172242180002280248286405170361346375272350660623512256621116258569586752453038577997389037369148494385545505727531276079439488725122758547731853605599896763904467897733344635201994539394123036082124603629401281817050861003851006306497855148296032389496793241815848426897135091374946287731556445227787886824871975053985209646797388847948325909494452101326279504370556270969975120801108573605041493515926905904136466940144029373329098096607094507236302044416768521105648067872760545501920288580288092146982881616385751060519997777053222407540224997408883880190600470096636222365175910883750397392995984659170407032933576233025898032454329489904252035559096533182739812657889551489583487499478328646387754746327102803375237997379454598904254816455912207626507351982531041848317893727929385869024576905641966494265219228061832641242170342170367058257129930367454511677197412834699350795412695025499429401769048119861659823618283575065497834375253607542472587333200973832695058744049745422333122394868436183040232515140101961142017274539987241189904522263971598725280552280939069100652077997648143595790610013742094667251026559975680759988658909037164270042471827965060755974225796686340846881187588650601318037690630604061826504217705424408093152154493398529059809368925185759632604293536762736885577305569086601555646230601491534873617726828797028689972775168892371412055495292773435065978784593504400140747653150013569228780639661470449718204408745796992240863463591157293610640244091772713544222701088195933995725500943262795747515926125287831753654784097111913632984644772033293733570070024375393487658399706444144043590430195616135320990990782175242943769471771348467587202442823723664516938264877956626457315530507641450303636805958575576056930621332750706023955861472278878359150279439649974764276398796039068136505590923957068543683376322293243204504878380752238267595678128949150108941710515697954133037661208485750371223584943396459462695262831499977361977205814252657814041003569378503727170797395180621504082490564338952604869242107390810974386083824928733166199374923951567373148225732084313148483817195852727713538586899625240153233086802241453750101714154209697896391574011792886179765911455796345659332046409907668456234806098927217061731222820930174722588351347670775216724470230595027218412414918446520015846896530580640379803907383971347313987194645815381410009395656738781235222834509791636931748003739420318670131706540421684202716441631989642943070547396529885544839979971353551816697088764254666757840874490261424627741086319072524883133659839859245391821589640003990430815450815143673556677421980239555948488916930874279246986512825118097408, - 761482440488234734410715914450814851466573155792942767481071389333070618665432499568062498613432641715536320531527405339266642454874640942028773956060210734373639161704767298290459016376557086827424996737749047733391251054217583836920748477399566827619571463686177374124137026392082816575999078333725941906078002397443104277533664938598508928016614693641367744083705011283620544751155838951248523359622522169158226159383342467821505842061571777341721684379242663220682819935682744814713684591867308605561143470702186556646130803147314215425648398770081462534086719992263364463701713618348484063148841430744737313050220060928892647479629187515120224033961002593183497473824838113875895023367438899023833611524319265650002571752732680520399642242721370906791082923549139062078423986211127692932231829079528027250429150901315138106576639942073421186291623381872310058555592284465002206047712216410714620254044350367994542342563290398477507037268672569344285208492747067121914675613430937520394862935789098728151744087974654780115786757073176231210195404243896906014816248789810863266410982404146938410985268468548360777362996557979812709018360018886423977955276331224987029578605951654636828199476981895372281707315450516040563877672544141347412395030869912889414525280516260723303233365467158268385477772621490710996019119498857650804849374212471947045762392611882174700393806858803848780206865446911782857137175349962674259993463660164100456213822018382821495383520600573450366924015873381649476321853177226782210953799897421280163600566053801916363738929716021863816227772369116482387581545389173257254637935975225778472786001197818207228036099448721766431036352038381527328842577868397126768738285826278721115303011546521595881600158342136841608223358783823811011116790000210007927246815164145013707838000655277061090232933562260127579940128323867322955275601058177856128139413367640127266344807206008269676821024972971467563834601322318353983335677760853340170308063957857441562779560690045942201069628728362148647089562205821664540927006790746192589436568186287281715796307508757438016778610546094472325913108238984258884079895420623037582121370998945628080049996464923352911411378337992746703971663343782854386689660123088973322964039753226033934254134653112740737828987805896229731028382728157956273356735059415676092879605882961474982289613952366654706392757362783619372651904477471025508889180491963756775656412093154898216576394500818208052579772644969119855861097311198375233357995983960151188880653401768005777884012488189501047055456283368436569287167292984161111553306781664766867800082548170155649027039268795889806919410955333532902253874791855655814710816909830623677459709504668563434158031860896522967752405947738295334067442030452006152916309729305804872107286793059546752402780211063918345073234153170867979011804021619524366623829090053433907181651255621794440824562338936169792027768231446069564905639934908704907095723097018981471254642874638484163054572265748350537270280061438314417309719383475863128633573229429041512327988680452811859278455606343942243483970172411540222598107766898081199063990944021678335681566412260093313725457157490878303990993447729325058816918096394321149221948164333363495707822854278459077819779628984555784257777859159493074365459424542046895344792549091814615810901733552222726929609286272984446836550965351892403124928881985341743424728827279829224725416074895069168094530276639217028248700622109159755236882636735891076571597761884121910142553673657169404967432190658769769032382810845143003021291060754359864208516504957437598352645548973325529387288802440469737615793014803717884588434522960074622477065325559700678682987003904380547337772972236361876210093623622165009267989855954481726146669957853292813457803109789303658276520897276416332373868361119927220714436333760336324419899050968149519772576987099079370252679047665889501422090279892774336173728037695165666441595450959915250887351532065813132180531529284081983630066621220539475799210671472292183279325578507038260010851564424622666249777803685114626960626042020762031898932055956574467896645816586986632224877112284690509147862435032945489746324270319071114211293519971227564286122741693215868164116363169736261283396694614434563965251792082274455497440995830300313976633621176241460197973799109823093811922181953909837237845333852485111489625633865710984761316464400625004900536228991346042783217498645990312057757595117580597298503279085863305928174395753953402904062311060565911534299946691404466456168138111365805459494417677681798237722178723148750998730935977085752283796736946369422161630045355209344872531164731686893871398350578306665457718516152995560111571810913752210179378647568227655567813636358309757789196062493254282120960825738609193997519660960829105037184419914511918530088867711016721045527497738929523498737033317266154271520927408609705980508974470469385011763058413992539680234633800623199744965783709400049569965482257683943837909802714155147761895128477012664959979678779428673121559818570783013533033459167857417994789001595446559489526655747663538080956590482874975711726090666788347823646442444528162545931872938665764314073273572961504588483576559998305261967834304006271795932947081293951568852888545942635919158469460860727746570848131831121411856795778940029642328025973305628597707535098173069340888507440221894483801087531425266102554347524318420690831611400751181995058985814987331809343036457988251568792173165964020296264803412945600628056297493430084448580039700884482659955288984926799801653746424063267072237530883518791848291993435798129450865601088346722298179296074543981470045347750582100010755462771361099272653272008611283195558357955415112529908312898723090032973008164609626627987349402550454920918507738378119155884894586397387289092601655274041805265867641708414360924006134234062136575829804096868400211099486888070778618972270924074365936415883496120732858874434581247562932775450367763607539929244866982202488280982679524679948835049719564774751834370634401561755080949602604724519956936136357107151682821412280045039351354120628812833765467127650515744006132380586871232909562260082090490797011748734876677490914887180161403306173750837012027379870946421292027417363510229530419042944411410696575094818506537331358407222906506025762090260237813474875815929041871977749148750035934079291073799529265915699120034017928474946857423762414018174816100965254273180591196234675924403662297079023279549699742154251594819322785295389012182777488614532167843996438643057131087190916217138390832931668515605727663836873666271207800933623586692335620758177418453043553077034678221094705312824916867927616458343267747377289892545366748968823800086749456872687192373088276694198235977314257091112526438341894179540587294329991430422019891760470397775065984075360667412698260806671883865829242063611890611307053103456159437178008589244774520601015372362958857991985325612592605571028834555002058921370667304934814657628416766335694000454986840944839422687399458970226068549219828735398868334350632165996938398354124456694578003167009636635461392994115084312042309115490637308595482374316834976349136965587630747446373605328756247366225136768835734403660794077437045498528902165611560419571794948840486375111691717093745041515650223930119938278747811220035426455713010672353032945606176763156181288786381367724249017672234692058629502906598184202660719415690998689999377926087818157116917410335527958472354391389537175368224807698880798779947667860430737891433479031662553865308585986181064657939173528464362884471037701010366870454719604550234533768441083981619562880954772495992369250415788311087342682724572421022564009240720935316205931000139410941280447326472375415158167584857465467973541860721198420537725379128173554519653716697670912492762412087679657352769472617300421034586660804272738137221170477489989235222563830289962014243506581733580915530913420976651067701133527987943466792186902173185360250710348939834535154736987600350382106746255723370585747111183976241137243581722509009113687274094910056433780195520219740498492243009907600503838043258359461483095005674187575758977646720246866916470614959581219071380383661644615729579982373111330604636681919696385890507060772903185334620076228981477114081948254197051569788436544795618467414588650384394172846576099583621333873981293697417784095032546399593038553607105967758310785855726458054486853917832758898311434085879768552464546293326229798522482601575526252709879696155186102737304175643375250786640243510943602441104450880970329996735450364251241216099496643686596063248133649679818423359072280786696510621029179868449721877065943108374758294170662523595269115949987708458439811995256065989503692439239887115005192929876801409253376, - 116040494591229608457674573305417410512556190100671123909442737625782236437858418563434963522551281240974433428855167418167129484061857493044319500178954983476412486677226730584956626800765489930834395251014067835943544495136715034140872020392283727193053506558389639447593455869007618369503512347032438726908420237233175597736383052785657056370910081330565998123892526975034746563507199241703053085659882669576634184020984967584250604009681750060664662481863964935460665388614199418482107950121678732032026494360062218359449682304521221294396949861596111056287850062363361164902271427432306608968151655245249975034259628349354883285473840433879734294886257519737317722030805284590797192023664910639724784286445640258022405238712062006348954979733300515241343573462296344617591586158006023289296346815083085899298989011266918044558044251197244312268163195337460326285837903663546051916223077970493272701484936332158463184829925219221134078195008878219642599141080627300021527731223335788232111771683726597266131765907780449598371840443680039246247303424888452354779528211194046174277879385355933160338415161901579607348373438807423576301805317880631815991505713791682261372906471759966532448533633705782180419822672694366602636808601681953298871312167332997352887807851546094892811977190522747358596366734747278857058483689537818796941158756001362723648325358260952887723223463147528028671287104552209267214084355405691068045218786044704100283402646614605570937432350883945422335667586129998341574509884823071654406903704593358505943655027771781017260534365363158030866484415334844686164968320022697369411616491140592218105394665627539152992498148631356103033540500818852502073915506826883167297784754985005661299213091306476517213969401962850744881574209305708361299550760215924703547707468642043181629328445726567119946117419608886019442722717916282601687823272587677299075024634060644950527904485307770897161120887171568622002698053283962856691088849831216575185488500521581600534546368096679507797876582101844514096710750188740953698864993546084266774836329498023278672353530975651666544945033874451013406155912422851239376759246479426958354635570810839376632069031579832660088510346353599283545788281656464299312008044450324748123867031255321507766924362007619433039828745465206663488082509928209988481929003143992987965352029664597661029790636549146909753952673971143164750048262162901161250897075525903713091344632256067164251055008215713735870706768781927794694827870787133496018599053111413192102039387509825182016514660615471700406496526621013760079678470364815940811043712508354529534309713138028602275880781497324810881771625810858812183188760075902011483721131795265689183277358973574165274168162764364579491222576279448138123019862922501286980433049800688789022312595878607642808533932656344071872798588735764312670651729331404679279465439669347846255972574634214436201467790651466863708810999953776967331941095013040242620936009921585602838169492454928793281603077913485922632102071281531299545698764447393010085612954738342864106135424782846566902949320374741398907955569330508975920822406958336872343794166984625508735672715215783820859071140822165160216646586886816062791058845290363835965540090021468918431794686402010941892624488697077758662988133462547199240448973314263463683196574312716998615739512801671320881268789127263317518039313095214860529524651212918640835395934201061795199647024531851362740958453423802986476109859487460406165207601356441022519782409354439098444269637047366891006958926433038242714326717338412315711409380955081656782596899002181012709242876165897197133405291989177109304417810463054241493012975529255593303990379439304798678401544441778788397605405371857564001715904047011950785506203181036107911541470457224078206657639563953149022636161428744269417322699040603475140374280577590393788719905673984896186992459208158625969291308877464194624041431053117887187837376042633660704200465790109599421109019679301676418131920884038797791360605439841408781284150784027536996764711941604515026834625294135748929195041053701448829151307977821001234123594516152598019351005944059003480581247368355830582154373728918375478938919340878995453646337434557369544546685791787221758398731391273178757853324803494933577714718994167382692289644075391453518290291605472390265903552576220616094059271318846240059382406981742248106173396977822154372157667386420488320227981412525323056102280049922569534443143667869483646613417736473198929956995493242476841069180839412048902518521656334972892982715500196034955903539956301288470268723638803046504745925847474472285382129372742259674758477444712513218120312501635599333693323991048589313808524350704246028331878286985332669508813958577191371457550500311547028715238858233095060004278465853127146179002205189182685184263741249885096055900425878500422063709943322581271478809131544597390149482924726526448836771909242467501420075011246666651935615124857105373050013505216211020544690722985354762868473459556126629453144794598029433437688125942851905073824742624714569476530836405443159343615248360490878353793155476145550884133800017715235887585451753057226101455351914043633366446529730020342750259836269888528001916414093858760556497815689723733038484992814023605097509363464380335262901819236364925595072780709970604824946045787474108735871856541328934680989052896695310664422704854687709671253366543638696280579703173689773471902417734712443356511999931044887748631795424268662422454493713214011275784386720412803784416822955162077831258921433644836699633391650579913901406445672453623331040904168384274875779525644733339209162129484458385383068545186579812365016219322264384878914823338489163542601294190546183190121410846598126966947285382676336880988784027853968886087527971735297715099144515895306109220148450887548608628707657491676077846119466728606380984765147258296923391108249508922081902471184313929982430957156688267853429895067680072807928801275307837242677683225447175931171907873197259601015207726695819437528937107397844905591758438592779950100470911537543538602704894905525990026518396668896592941097332539156163200623949501917964059346828493093107603688362361092562721245570649304401192845192762973896993803759199074958841887156666311685755040039577374281081884166413111703568070334991505804062144309831518193541574656343850984516837477526806359453764788692578050174829729788414240766016886425939447798786558603582097220740865289918616522950503908464955078619014561041552553319382046737745170896308842607859693230102429163783919072690247261553506216115358296715977805324326806086532237952996085364556650450212489968735997073797225976546796566575763677283706461153338933991991738013393377125066584415855078923000205931912974087173301728814485069151564513787084022403376476609908672933329054434359223434208384514719249967868323414604411218063296606283322201152775830957526227469692956401765968101188481334214398212820673603401140566866481696854043314627715764346778803543678841189990260839820450834253109553561623952332355161608325602139588709220442547558741394269854471520855383929057366042933038624012809248434281100670967985165776745308599610111398521485855969490302784730001215681911840803414240521630054002668467461318997697528495983273922072130219791522571831723429088011160310680571831920870885187943470377859803410671771367982834912157403320694872308077297334923253995299436052961274854705418255438998934189051120414482742716966556668660909683286296738573760500588860313911366593176557158330373434278919855613856606134609246919877432981873888572752870978128538674801077760646458743597101499218365644205805874359738490123173528020085009049814455297836205107216061413865960609404572311634767602289763272086254953271474591688066133837388374120290167777886674248454527719726193018310254635163534872925988821949062397387715926077455640285178753607428770289750066514220804574675321186487667260216108554202664645259816314849825306001800442081882076693792471758593471179947974284602826834755881607519913621569018496533717522787069351083586669510210489864531330464461954996388196846145738222256669655407393024672233754770430384280811019471248452599042851590232881021485907459291587475111657089353865352754493645562110390772561490040294755279443089774587146661447980597271895357178807561311137233020709875023607051853449553300276300040058698147878251048217546017090556891999086120089403053853225169554195876108043294137395208507035565772284757740880850708886980403772136969995606213062593762789339580216104331504412000399633882657981709637266101454455668001484534826433027204280870586994540923040231566345361252360411890479545267219210946540903463429769271749709708533133508102311496710710473714031846546459459873275810811671644118672474112, - 16724767807469151441724831271189039524675737217524186677210314904586082476559728016496810271213269627626113757196126703478727730517212255362477361463068272945745865956299540551459757122242734872665218650381417413337948152831930641283619957416643401992151724615994199643255651648610905834357623043440154572496567359847861818168965130480916079553795026845708184193627988841094413108377203804865655333375452651308640819742263665059801440190236281561772629906379752747703630702175254594309878071893778162218490171490329132500800163081294799612913313701367681303374816272599762877336341397074716773398526763876218339435944860683036575825658832962019421462345918303030098261425952195084331410439720697166642584510585726717675470107920145090849642924135198371361471527306350408778838303606631708368803589547630139448590070945805819554453746215864792081229500574823347569298917245970518180811852919723481499182830662740311144377632212202104798846439427420982553366918789434581171404877152874728279810232150005218524320082433166068469792432335901858079668398213163148944429861488212677075628333777801932156984064574974245950175129484579623330237039883053775361791382758679959005622416229790141228690530079430046494162788641142769369810881957611250934703797529565278077868995294540861845322367175639848622195268344288577542985347721004235452365473772156329375203239644117083227132458316820545352074741563723601481145018759778393301156680331730383751974563516541126376528853231025628277206930961323084325416935475517401204892772529158590812897940264919305632479004414416395676945409538660212057109313921184208817700676449516917840680064779237373456822468436292066324823147590153422810542450437369093265174594906969161432480827823175147318639587960802977408657869203654713679445421897919068224433054961195097583885178360414534091713938346289704314142843465988403431162642119342889386088499331484858426260656479005454728845215983801439109078803132344650826917634421539059563402381172980704150078853602544107889455810306448569016233715219354795692610278026923159643607399832841842076326986916033639518560592866516928474259308690187872622831356746520147731604602869900160202251486892968447809284039988951578366368829587443394126821576384452382702476074112288748098959960563409748611981074431880156200283304230607252170130002135172627635709817337766073020320344320476656950081553667952533445188203163751482721737035461893592041883861207013260518472455359156031364329566834786793159807710071307782149985804812373821252585713850068563398532443043445990862378910797048843791625995681851781963440627192008628869681076012396035375404358876131981224425949788140535740377718097689036140738375941547551906238039887778917390766860740141699169868819655857054631449775866448634893185147534281175789234805829220050079063464363369840522551002814992726826555206404384681026464465644217260830722054914740043528000325052073978807845926106264481817191331617757781346198105234685551397270795682908227883560992342642776671649776917621702108573792903375682453241684668228239916913769793828046697285367079880272632779541883637396421108238936394412119831659464369764056472897837887050334681441926065679410975923442042966725155275246278921870968536307183688097403688507630421006605580647788943182561809971762140111941271434293520189279825653938557993954793210823423375312099240969835083881617077382702932341208504600279411006535068165988774660003795500036365108286069706142290675209983484815667817186962657665970152780370428400082145273831921648737990469643479331449393071667367061615054684704137368737642861900052680365830765891738099847614674195488469586361341003875519819437166569707657562119169166015621015327132976901993997461209589417458671097169411392536228158256429529797680404769044366398743762529119481840275816520994282321454750111056172618562929814570142212288810664183159552472725817874760798494176731545458782874553449076093959816224023366775256849970578373641702741295746599867502098062783430154999558514574792650899445002236512346555808408161848166761515312857886006600467497105016667998978154540185837103246015247836376431883094634562001044820648362380042238949960448100751172219075807425798852370418654526357877601651124855076388850344417829231318579829912234709565244946599375508459424520181921936288340668435633242764624518586555313755710421340338464920685371397046395785077588095797094243315291313712850993823008396301852331612766043971690818727938349263901536124922778811712565133922155130154668996870424621876605629829568293032080373622338184911011880285732417474171269496164276372030762571280983402438093300956463887520895309357386397530235584619520086157061415704941567742588621960543239856843007483400291820982935000786096048186436571632068001808496142727117158748110075282792001440502255602719994870685625677771387691083669982053382686064092320031606055025208377290812578420007971828108546405782376893423570711799345272441347600065053079148236067258152407758232246030139406156052362016226073149251057965223416568958953864114889756161435901361655663653581735108079248874689446056462058833850697653136650772584929232562864460035684872206900495125910113760501212168301080036395725847856372296424883189409343207263257706642514894524321751702952975800623511362504608342985028602952017301265390438757183286237902003936761433720700472912996210343665547151303932544921216488262919370760555832249577665362781973310761018408296593053245065563584367749177446422868807606659668668667963034644995540705133649980664237128477649569770216627487052511913378311852448929322049858120799662894626291982325978968863879258195799174064683662472673304803943660746690866886500872488916076862889619260362819002944881023530649584827400543812045346778652618543207772730136801137398404114842080351822778787292992585851040802850891770908214645964867634427010160647650837026540089953970399476492908061727471472996798948341579163023504393148385931177629043939225545177602406978944385692515532807110878809278336797559960570259380194399926582123940349772362739501193197062413705660402244503280569787171071912434748283931672303010066114809034223329785206730686187359693436844735564478377214443851845153571191011585624350619167232053931391445389870229669893321828173973264435167454011153599892220934539149563268576994946012658485665510949290840788172588997959549222175724939409623584569816395031875425985862078823119866130371313615514157827309311450184590087336604843855002028371051129373958955006505311814174947114427808605988601746172489563875694676455260974362604721801268819759724979499663490726139735221654991962351017032582943356208753505096826101294956682226209657025455171736782630562894391116195716235794223819251261567170029910690077025707296382859581348830346433750817648446419984870754873225137225315053247660673587436111780441607551634662961124780178663807643200984351369509519894221762573698488508038711855406064072611004257421032565164257955512071811958659121322667878631096744862590747145827684018009382555103986988913864971616794645742014742437337977171593153293239998428064885711548568978312074021156240407544713008645838175750115899165315962157473302432448603694673155689363850919392668717691601467081009252813375175835243828840087746738921580288557850518269406112534174855091412296191809562621826149511070758495644188626407139612946040370133308390337158936045241933530481619391485449824992782124985379053994695699438844130670448795719190159309295094061097136390735587704794905056659302834095677811104571390093138165204590994532188296374600166461980544368525334403720127667859790722770443905427228203133069844830649200157673639675943665897402558798597003441862163859060975758167961367915610375161266746298720453734794351751066080606518002021753011717390353998889357571933137495565389840250043268865184515706622339058647532721111684953809742618593798103786224185332014215115620584419269074032394635004531640121681940974560840185861962588283099830120539014117298933373623711477718653731918183385692941452824009652608687900487366303108249176208769928457930373610217236119266330557533112050113564186082853602414137634550736299404856174600663023153061251030512405960057842066531845243219812307436646033514314063082970639676625374460625455891679793461522698951685110108727037563829559842122169574095380576845531448089866347466590168809721261215284231236201390738752053412547778114348518799414256267914034737589086414292862323443746694029470960039729254790462189743404357991606962640011723741223515626973449639599991326475972923057930146661250875360147446444012999069337828771203414197736409866344464115073549919277531546263498133787517750735275841947291333526200308541845495296682280243194429037190531375949246559145843592035834486371385344, - 2280119397584546951760902785083674076337131183567140694253589045926565840673340736224594319756151554194064590551797801587103056436936122167225687944661893348800692762665758922523885673930842621379741792065206896890700798282574175435304353275297242612506443745532723392864625660288741706727002972129257323801971878226244514890090733762255793571192136076550901799682085058129631790022650177220866516090278438518758331037739933696495015091955950523563476974836455625152427221245468489678639570389344648277999394012636290470196400181626067203041304861532012610143431655053224187315855337287436516947705808893981278684064402734169515259548891481422202982039314917110692098466279117778227040699791077209609196379938036476590436205626523034817874484972916986984551421477590711606209150599482044479866076674795943543320744832511475833780202284914901097396277976973259598122692142353509079219843481585066719606019230892104540993711002258602116905558038846102149913284091594253373648405132327115326898924568433900446904418617300935100418052292303515135019327267825699069566231457866993961372774475575718904873121510735958736737816351192912961461060655234800853509526845191413302193826398903327369932915438741449733580719468787847455699759164075810642001685692431813073987997607500838704188082822947869097893340814254610988569888768516863596884613394994581340882990039331120124375945124546556197424051423676966633793623583590640319706689687626964606195410582558211065006934133825591735552517033572430400232986666772475499410217527716535732593664497282787020676889255861409825846649158748750238489436764346658136368489729675956365687791686028528095102023457039557674336408789455929737198386907680038898486954096803332199740943155847365472647993916783376822171999524958903979783463569681164764311355496351195619249963349078593957771118908319224331965502532238863793446026355674700864628629837133111687656786402557264761302696896900103280713292373076609462320374503409940524841565050645326248469518317133581954523692244554277159514789271558181624084824291199886735319176110874816828474475011866525182188506978194372533000082263258407974280518119246328804970684837872071730013577247516016082873728822200354234516773368176207745868220243474098329329641883770836401606996193226331141624382503189926510177950857344825530070785308282564561098019570856471255933256227377376754143755158004898292517637085213780635501710331693319213751626591527870851367193367451754871123579585235961847780200973476520904296041162247788988653104726209226413026182920900506868796273048331021736978868889458597009362828053002638914890959455608324540625863894543326502000343288406819285457972990395940607296371793821779109721643131477462800718724107962764060841165391462947411684549041344595530120375444092616080898137866137953565278580242556732288903900258145707806460801813140741328613613496094852898293033835719200713067922545222568624596495761171555916261226193123199247246116359544411011381958046856326853187086137843951881482856654076400450284802855871670868387391888258375148583038583608264759765428720524360103654242152217713461332489398774868865564916650223477225774833823898185290017730415614378322538483420938724741567422574242284595544264022443173751763642904032064711811158397880772785299681959326604645610797160504454616726191444712717121447127276552858406545539634904506157540131426779890461205145414572277663778507220880771187076632215350756273004715055721877186729608067973554883084802906431018297767912854447839817929694521935860182134498182000852411391435037185462803702849702902804401781464541319509775370621195169505652262620133175614437286653731001155440139265956500892751032878602647060635164657395764244304051286569221394297203219670026241314576389624799789545872103368992165155490504107485151016846386623896742683514256409856185443581013952682893306712414747110328676287549859785336020591125510498696205346490473903813263228514728255775771119227162605537908106539762090214459864912901318768956631955230672092478302016762719468546281270261143638851111606516215873013504223318134199227594991015960893450343605274608547425977695530376260925183261108131285024666435110788529249320089774895540468232210972267795673233945910434256784018368058381018636549531193017600392414232469899468519413738662987810347605979587221711070005008089755190991789426844190969877186985574714834304877431909141451408761213637281318022562429079718252436751541290226884070453149980664020646952715042461999430760587586337079090921986488596939349378977698379472900838956210668968666818322554098126307732797075609124490668801136066068015639043862660522248432274428360257549503906198324515442284760310815623506854437635967118476543408879340707843428490893393550429641723774182040381570426708145697448523664252981144156736235385671619814469253146975386923999727352686285078979751201336474963189210323687052339656407679145807106560666149963695740258217403643934217248789693957328583827541177313374438238847036749953089595798762885980610843609262639048367905650085826900938972875829986319642095345040405361855338127254293477023658460596950502358407593301024491593441913468327966547826304714384647523294076169545440272407586427538104766124870303602371408875503709017085145403225393897091002781344111173246951540626028695952103116200622871145836752685474561170682005683792321039161594530982450543589361347377329440725143471846720435993482423157117032310482110597791170161181058939154733373061774746144266260587664172874733602214972184309955026665248455072821041018386459674046430973077375969396136759034510064083267230845896074898919898148743127173341846839082447919862606003639590089586096315667215983055819368265250222415357506307665480435462136261550342760278712394353207604443797750040132657962661493317607453546276219817736820756051861655113254695338614007342297092501473138817153662339698719346662599385487985357573255963519329962880571252867359868918894948715726729404360480691635575481970447462900181525728781066391850520064273301740662699007971116901705804265418160864313375517995283015142265227730829155040563467971367531262017457450019086207358418311882404491935280118943461166238877705753483931555953531314251949440801503498146131000929052699462375233795748377160969588013213947303042204926553914658051872962177792387957517492413314245143889384587142687157273690164592503482345115263249571566870945389106547229494532588122826191139564935111471162881379431063317813705290755052907776496161131952206277198133639458943384411373260580551779617877124299547525604487094273498541172727619179673588285520075723159024408611143621287314215579037554497694587632956659410740381196403384066760881864431476928783972050246945560726213834878084642820924105746636849089449113785709351278523393608700889480747863009416399809824852330902937194132895158350104711624811861399089946746989357134157546353442023979866128246102175610748029911775178846176647117175593430943517889881013158540362154182095800547538986226885420791212663748336918118706557758881457864868988832071079956040048376875172758705086450169454687640851766420822457885632089322237595542807753210479483258402568834133996060160857823339382733409163888403060478639999146449230333834187860380528568714388770782538280572140809736082085160215838531385862455516377499640262820356587389140580828015569788147992106819678877929811916764580478564682983570791067204346782753942476459303737645916448754464706215451146364842241520859186875140739631174177562588263008665734409563770278469557847849926853154048284728319429417403699117808443913477271736485444921115655250410129060451961420234938557273020175097219381529176769385653052565575478198663819217655032197259859333363612489984611958076789244480163537415088043885873190866280107144601375856301708020615868745053670656064348487854565718016426924066992300008605827912714742739592074426109877873666105267984559817724396859788686740360399883920328557787643819057472019502247545874612432815229930040726526099925200830528616813954432960679166349639335850503379079526116674054828519210520681257315514516706386722735458211441587052702571508108700402695343789545106842339579271342451738207312179413966279255349448851192772025965556777508655283655301472551759472845214196637991215601182391967339565864070174626791908815282019818078085265231103029732898315416255763953186221754578710888333596348060284171566198789342564392435796273282675162650883000265936587613610759457717114543145464843937180517223968450165634080930952513104943549317686118542227897024940211983026931777432370209092705458372866919901518627934942940442993401983352465055560785952961591278197528145763096140826100444986164511631435345366509531152106685827472783511318477242630144, - 294046696119727273667287669247768593366865920386483117595129068540486853398817238406496921730914205969605402562482648541448353126092781361451573712757485878886532584389623477690641751900321426138718463682268345899456002150737384558325816667065855507714971811549538231560492270169072721162422663657447195116645139199186935691526800311871673876214876309565296191699210581093871328136935742295899356540636326089917135812813405568700385377179012700435910434151599540907971511282848165862376216422099795735676025203072987158038805833656535361758404285871416657945298894604439125024431909369323297996946502864772289271131680126787477598110794878309872406339844835094771616989095472762361523716628658793732183318838258986429246592780817606613721508887487374026310870076247104376158712363390446928466884962674711716586559023339999703484375795634398565608145515433142119405847053874500385740372110910901981777122007344584214761031512177699487854289362457320358774997925327580461461418942155080287274602719587219783936434980772881991808989551197882581219515390808076483946798828917901651849641524577410193195708307284666925688705644761787036727414720957025606423040199429975441324486982904700488308339729525091736138059835603429670251854366801238738684615163169223554068202624892209296582554725555396423151231063012061106355026641476421549478501212404887077566779492545968460516622049223481690638817203453620276511529152497803384765523635828363003008707787656303052908439645524593928229514525183274639462602398212082285199962723529302960846410610959874286026833821574593644737990566133346862258685169750305642715037772375534763956010460757711592526656200243890772966065511846858091232561091645284157896452602971706435376769057645535201998353136760899512007377921780654675852448778024382920112214360964429641956102790826146666175610111430977548167491067737394191367932394064011002605305567782065383888573167084012684751261811177587511799634009313239263136302131845060829222847379412094443758135198340015364245952314976379000849468017228148974734203553847410781097557194376073068640855439027812402940549036116288317870175222391225272136401402237949000142687691937775032314284119977859404239637846560614819451756495544409784027991510496067877896789581632337854693759796668522349425729782408486145466792132490818869058755689784862256140603948486959789785843071286185485703636031449349137264366058166256669017771690775966310365019528988861310637412167976730538669913731270300048388836807752248724458203948144975626187797160388001474883800121253180285733427086240170964678172884690295019964449994579886419467886898475459023727272117739416513471619089452008205093419413884180720411893427743482040027794869796365374534538303217263739600165776744238856775567823367467999510675398747827913264105853677563796178287762292944795647061131735370309544264859415670532462946948352094011240974557112252715538621359581305054784682333322685218292482594522244156429532445938796344553077276768730894796266868148605428868161227628867393655363795688753946254404636379772109164765833121179911989959478892496589521041751285998661230007875602184048633383830309335031581989344466230107395284682580027741153244700158714313495028333960701559965701547321365459911195669878510490070310186240873297453825769940194517173807510827545749750375332511711014888358926557352105282080172710150881919512350877741032421211317969450827984946428894971405008570034028100908870333927547809767915175655839302720565368710031137802112035882128275473478655178108982499897145930926556526103387015250232351273854794362026741309015357069738960145488590541793937482377185439155664684401070028272584609268714851089508097604910463213012348188742314444734300798243571070652450374868474073942094319701995640262939261603574498434783030328338876928852582624386731587135221044100529079078533586293451630146983479420409367558438419224244263730364601116329888745162174916968451104758499893450538805737027967536604977551671047918156511696407315081313301650062994781024262128169909347717510449504101132677333948592244085075679487631785125298373767475699807225361460335344531792452430634146178959644922808512402218288852492199280261280478551235544293956875492495620750691481649866966979699023934109976141106745641578044495128792386002890709152202073316796254287128472312755821201283740165649911539898950244042529200074484147767430867026816621868632807543748749602898278117987685994338834559154295694877799827728040428786479011935118543509120352650550851057373163601621097884503567877924452930091320305142475627190703507186466619874885199108786972059438598246145054288173882301776027799911325421514541273182941637775580518526650892205298163753189650401140171693208863040058561446486048166224257828457463956088107581850410004616583350121435946108288417544854206054183909418062258614966611258990002318861939531800867089183501661782611074506396603382927996808588565764824473658178756642775139305196910614003032234591295217846566600447389706986381752371944852899394624991572310339880171032834115325688794057890654415829247196132593180408459957827538960965653290265907441513195612711160863485471352233512862071214764045136773904748255199622371711561219974935564275665695129448542769025332354659260971442448168701962659443668415230335815952242979054224565369362084814885570013466429493916016032017770448431634095191651118435305873638521268268946338832032743277993870870466852544317647096664486198699914626641662198933446040818781758358688840171169188147559565343976102940157923057261244677897044587181117547663662590585822851960928222629080630275608912560352461499206846293030889247882518183907186228854686938805853726011515256430104113083828175574385725186435601296590960252054932715320360503678780820677660835128278634940687603068475392898572556240556721980474286411798989024671255626148072251477802093012292232009801342769541136522291368686008521636007886129989456288532877457439827658898150904849507780764697580433172498971592527052728421192504115752813851826412715437775197846274259214735723306491515821419190429157134071661729059055321595182623860859679767959463330205436051995390720955074687429092618271632909642803947303441836295034573222559524240090444674916676774679880576113577170282421413468863179767233750333509359600411194656298497983122771112049292322446514849102590823369063662271602219498887001445532591095310337166801940874849256898822520765175531506770142726382207510943049202638392361536086473353489251151458951429702241841566395719855476991124961595531757921163368303975195752487526816839393171304839366344294254410760326547145553702297872901047287016248099604631425973486078360397550410205046956175190738902084492238307202911719579464510936846637604936594099368901208214883895427918587176327598498490108267457044800426636017530310380398592017961672376223480178348752792704297299391291625424996309264006480958840924193830160585735494515091229655860285006836233357953557992252101566699287023136840411565008064225514479472467542027359021311128022452764634477857077652429741106233407356757627537192813875989672117364873519903017153250772784431195383953095338462116138041878988146005836844412293544804138514500534134719759107505595215199670145656629574439427865539931979076923713367375865449886815767432773441643210696382735288061348498869588600346128515481403325333005368172304783179748447441257080237338504250839129951347126250702506706254752721544226612410840810100855715735627329604081044849705153037060502076056179264907872799920041785751434862254773318408634974214854250808274384798234447886387771000281243439805748379880819928882701919281604004697087202826050407158298044334014084358192233148832220313700032559181729967386486407916854094450813832671367797265421246911281332086881347218243332905978738644101297251062789008352525899765324796722087795177606669249101003020009857515095516983197045690558166071420259953959039297912856397983667353258643435600535715860107767046868172850423673816286169926991071860363761916108439671128540921699374619109049392023938885551477976270325805104505229724440026222917836132439196046734452280042952980766514287513084836960495280391112094340816363560686974955397036934294367522893218921389346775586351780606649861218921935269711501038354456670417004505842449243672654678126582047641782205875504409475644584736356334563876906272017901309920198498455865533543717982477745759739346466980785312763599043161602091613152388983453552261943662282224180321402313900554500311645033677979277970183634795147965339564234369006812778954504982951631944732497834720925729640270149494074435742119793742355703227304325335666884959174354507401382663410699633701892420941236027273191899009122304, - 35868680092468634892718161883933887097677748350006028332356773454477228957128739572283091036570561537537746045323712558427470320295941779339155912965433691249289021410490459209517752946026104122250859193264740083325915312731779213793272994015682552971283072384452014501559936943582655413121870822131586715889892388862733407909455406466619968589921948191030116549510135261182945850353381721850867461089269049216008996077660268468308726109550352685691995402538490272064872960506974311269768379797460320559249547345992230624036066795872976531496024464089654988563199601194985641481616988022620861631163361477716163521825427884332956942642386003538202726962261072620241045804549720337335166774631649181568333949984009393541683785416902752327665077275463148315244488688359936784815754238005877683009490441706742520187183612242676473446695822699872083205221683813296008580827000845489313805601849604311037943786723131361416807825994306610594799569030053873255107063433079257146919871137764738849105933569261179453756485789846622589411432446505180743066786166505991701640187758990250751895218878135118958670325220321225915632491088400555144413051339021959355880799322121168526928004967379096260235270460371957883744819107131134354553054639381986282610311878233641343466276206148552754745334712768365481381754825803028982650779254198530133653726270639287238435171612984992732922559736222405037748522310656594133703153170670258721751084613939736235786780599705592686857175623593397459364157810039066293014828758664105445251851783506936545105284634014641543703995251776662287164620150910909943866585442299268844483316085071838409082320345263567823054030487463288534916604736406078952994600970450483059095530690777117346963251272197316776294321412578364752878082053235402832029949541547668767012126321536350693733530164627008081363482490340252388099743209713363106224323967005155880221237064136025189618490863211770140780880379907455367236198292350754076923881104475973294124152996377849044519648052628884064679427202296382672984195056444634894485100525997707937446685390129520577195167699721415731560891495870768236666936352123532686818345059052251609839032106128479740246505955130600623215644522564673049217127346190898584732381816413183583877496791336731626466707440443013143180512417054882692429655019373598012706904879585316699058077185020949827408223691387883740376918654432075684651223600171826882847091104086261593860903204174953699466610042354415275118579638624925591164684398170410223242232356824503501819562071112443133523627003493068451444854180363501476044020627347285791279503338529408848128653555280119960935145777780104584084920413585949503430310030880821372301646265651880642051424111879249339054649894736090363918183719818101597845406916713989349288907450993811332135232947404448283488101793456144832990189528666720348693765298281590391714491336136094089021512515778892560622358674781941580764150365028894913068352705242225395533307395221938927322740788803250420105745994170649890124909324312717358178049266032320974431822947588520355253504060973990536327198105393371158532724698142254150484716521378868451593796319143233700627684391152763198932073376984318390288665409973824702266763508028122062013817003782419114221901037473957723536405448454614302056679269246267129202431429594518210694502503882722987880802491773657420906734376153029456596610796151585135976640385231793972120123390152398493025708632791980346772371383803136007828371213317238483685026526674168757702876550159747006866308425365834698491627354013270534937177555510205308103865270418139683752723753248562914872781826442126951656319195380917203144104361870871333676716617606205561840255730938663848090804170872238602408131743821982152408293975965681482145524794614458967836420487890991613716929071089444291359277784913151980720818609914521007623593394720962356253642920455115191446508409459855101013254701170059635673348360999467704521391897015356697193168826768362079584885626024641481258704115285967939069697139766073500737390163834262963536456662947290720837161921191052999374434586423795400789009671499176612039189166939613464724678266227356453550795362229944118766568156818112334246074154926954834591642135029114768788792594463452308111975065954988438198048702935361659837166506805730125663855520285817359954925104124109774150328259274317165334003475532195945342425394478278244735340919688134560246616781784251430357974496256395166408530809102835988029875629559309745480213976098071018567950704481560730246706723276377275721801838527897959284587909951439395281621759555104282171300395096589167806666808517241876735754444578477425845804696211934420988994075599793856119579368045498334551115182545138551078554084729368217020857117804769986669475802090421958921077216734503453253871090227326320769192288939146249092008032600367594922840008656722686357631704653623014950145979877607729556050312294930310749397034721878419890480179385192994438728685577734594789327560482341827606047339796396079548172358919601910990602518487190342521579843532195417076855716183408544728483115744860807398986468512457425523071496677848572502549171263621900924030050596402283879821252245331520816915693862137829642249856536585756173229868453807611618329540410459524868699773715521027734869483577062573388225582063522649518577827583210314260980658256154908690978253738823623190632948733574681643474154209503512780344806819129871642642799036087727116985492774603695145974048295483312605986571872109031470344380426604878290820682763782927502268323099284094566698106829072527802897863135879867031202245145953785343330805955498201231195657841004994939159077270916778826440286807966821600076013466129123454220815995272442358781193415431119030792424080780919382434256746949745714189447877454324764020677185148178052924877472512822127171845884338981378044105488109830099188042853773469747531942716679097384428688188665417335866388125832441766662101869454704874734343391874587312561964978783209842677350014818874287966351844484612365176429951040360768159693161592541107344634027861086732013898499622801415416049151021843613111926473388642973994602131066197889559888337775086969087877031048408614583446142808150497636288015070473694150043075946350512607008313495068284375623539594902135536986034600887009774706424537318271672516480578183401105222697102023235436936445272618146048018825267621364736406623341111911357889538169848037791806723932982158174600325961935751390952762588825256511695442780935312329272129036519136653401822369019243956772969454137826894143101060824676470413448637330944105086927263363151104941098835643046302330235097118098137539815688071653463870184494116802453332075716680227080823272271303547059749894565359954321193890076718987484030556974468396609301856236915676741981444448382471366101987412466882389901673454976348339453522228367238414411574540234921231744355636140151417677559744196668361986118340125758126486179444321692988332758962666004866932380902627090548279713083545859888022768503372859238921688075320921913288674056108857017010483304390002442076260538329217812720176340961688606796601780004502901564307538136302102291562192408301926689467612225601832761583367044907935998672387426426489442223184782777475893836815279126827242821131949715684290034909411335630586016130689924641777044694372278934492591626815767920458432522997279694136753032526714051543445676743162190746708185360524561161031886669936681181701121053831404477434908645794795754988280213690461711612539103438490719967918263615696405337662933193287940844065487104526726078521542780831855093701587565707674439435628875209168080125677419064121559528051321836839541273808155589944625442794766649781715926944244291457143547505093451972277220669532962843430001249559939273201098139027340781224671333190777498812663979354436693138053154540271180993860543624716007463900786468784135729257785296813447172561307274699256401236871746721404364920674982781316419731806988164055959002614169789641653203014810413537576178645383550003177356851644072376741171696894697702540673140632935610931109292040537212617059036697314050572537205057081901935217054303305228881347271182034336628563261156450839788864533493214863224224174417641460015566531265917648198595949813813618746524877471314428187062723143041659328559147019600496490050013700589530886227872309820358121541722755310542971721180347998258487433988458326855521309794524918983126233347077116184011135201720548015512182992399855928486073820855305575864239915649580030686964105192409822337283012720456877616229480700016899624357975664990350182950845715786051003720472532200366596445835792207760362510583696621202758422147235891573430419456, - 4138040980799586719967826189205731299310893406569088161219292580220068268713607581696525453363322892781892708481743381743973821652276547196112153822722532131544839034266699749809431191940162360231887668881253252780833658437078827025888454141748508270501531678142304540675542071658270248476647156735031455487329593873722414489672669958055215233731379584888535011528354256762306126230637718578257721731151777617372962865629869689075751985936163624077002592755890406672782386677228712567492108837684452952228340417897727905638069578474584831512656575004840465981981367830348875448574207323909179740111049652402473148221381231581958579696516971507408558397396346111004751110436331212146726601853419389218432300521539830394474751285235003690007987535695712198521464569949911096647760327387058412159769380567095051367905024690857806892839094764155157411241047752088958493684016241961713798290948756906498604913988741157027826308587315660989607374599422411868339672500019260300805526092557940853480635139530907401216483389418361741417742843045242168925404484989890452429558376067217392357411696887905073366797226314543025729383012674230709436952662953753394962783648608806530540943908964013941621916249251698023137019422226735327249905361965138117648584500245712535819051823437000395597546125262838034189677065679869465723386249942763176937785836658960655292945546912151503082501882377656478354211761522163741928735960220388259085326300246616367149565952348372553354507209338644757980370650010499555419646787157823513918515976584617427563368620606138097433713133322041563504982800466172212928974501279931315400396256753802302050324012677838593432671834504464170344000156656166250152732853199784612970895449749491004741424773888400127506328927745795537270283669942928792295323640166830184390896608310168875488912930110569709678703040376176826842916959672227873290876326791443502028632802723107064159103720131015472810732939824328642332471193380895710692376604980510856117217853182660549640995691183082438768094417096516974727459991893681103566494960432379596036795978195803813124857597990488312269297938439869124281480304654991549223612263749586429261603127030563870857768711716914258648812588542345059624273484773937012940329098170077314712098388209887888302927775059969085824565884218684764492506542510873584074475403565560323131073304237520263959558982603209216061187307339396627517412617656322811789766753082604110406211933957422231750770733431657971085266626156396708023218950186766482402083908030886416637519773316688218465758816593032153961208153444536048616504825863992685584111277398783860609681664563430868494736043651824546344879804835339492867846962732217409218920948995236016833203252438381837117518719548631727280761664241287931500167353175910879677505293421063203132125914335020338480594618831701638554308704464202882017608202134029093857376657655619210858601417111262730979066904262908351380670985010367560170868699396885365145955742366883864472843057326173553730559591974992897276440595814799080845128949945634873442215976449696170057607736919627778547038909376770114388484345629763562410006073006797355720248127834425605987275211917841501493994607561748698175371976724766422790603638351605188592996096793161091715984967683650244785457643968560506942840012195251146461967245462141560495758724338850109254819575256590207549442298722597928024540911616504348565196232934604664270393827256637871905167191624017696749688865217426803349327312470088587816431814475733176627372709031150180289039287545332453438192029962220574350847564605781594435821928524135063983852194773619909028475622995911561514518315094927818454356311569046807817510952986811081981985049983356848089299322098294584397883521425206583423344883823332452515214244945832659520478386757916165644211050302746247717597529318084709098437601382365382448230665274164198435432437831077777223943417155834814191255283005781512519193651986640437330421863650422170276423802994459211356931555863832084159983670215819252926286937179540466156815268705499242014729674095674409931443517300501395769738689096853491131901687127945010716207519349894904917306362292572995220735876245935119868597290808036411600281353880033888561407722124378200565765303709318785266632757840926352144358374835009257107256367680388430907167947371386217013890352430186968832245863706374995623952307041587422495202608232726489119146025001949392504815580045068877529735176634446811276937601006879143269201737312950693640153373452217938452373656780386474294828509915723369566277618456629123714148859983883464211756382550134197169838515232022438819770209736457005306056593221366145109362476086400797572586439868783841254172245741747717248873111960861206426191222607112523035580207775348034219019956190272402997043641974703062653789374957893086371218486718847396926188730564665149554616863878742496483529107888394877624498882099530100844218554276529068994530046303802115542813161405947573261457456110867069742959161568695714402572006310771232445999262608495812982463138401267833328775010449455802358448430242709298554374590455747594418036109342526524928237922181075702556850986250684663973025184512288230754921793447981542534869947160944939876219074956928114276010830155167058880255966388990606469074027416905795428545946730370676008688018583108338300024139950142018038386526715769093341565237751186367534620169320534419091426024056462288179412541347093888335020930572619413002069601049648903217854133707699466860710099389028015797599216815138979325127891373523992851377624150437536294941214573386611406246776119509709241011670687239767877558953418338080362051155059306403004874372995882025867734639411225165893713173566087095577100103695729925609733795406383363554706322274322653084979569511180881192513024561258323264980721806841581959558699398586100302634926566772933419374319868392153080500270920062682500781631918047652764540859654337171957949273335466968544034821534134336043057131005694731205420501604518886123782923820244586349850018313823787704670491659349964692883499028563863989450710102554471431281067720561070703958376883134039541632555217239985781802859640166547639230223978446769993014640816520866578262599506350436995819279009673285707237513320057018648083719711323434774594714542855800252574882659184993497641956676847933272517429956242946902180246607439407545560307888458348195408972789946166322627666556057941457682605305752940460018484391869000924618357801180487475096688463412794386293457965428635601380458459934383174105611628215005743180180304473807492065429963127027445901091032349137854210699692694909907862673701552855646605242065560232727914958503982921404233504925525347305784676551330575672579818929770583114588181272656975732457188784597537336305058019344117071152256268469834331970279949234088583566891831656908143243598190889408775482756991615890597151184737697894290602422382517046194670909283196513247995700889487178687839814199240779322391071131703076909394352337117788108413627108082890295351319209877335236316638968251645543207805848485324229812157048288174285258417852850601819652620981796718467610749102988579340547072500197192184476471106020364820892635640027337780184418494824621142270568772467505769104600368777160887335314749663406090566314279213193821350769261903985725943878283550859429462316839963087366651967814533535927089750074154972897936883574636944908358172424346549346824680886872727279263375928854453640984593932126145491991506585493397181385084310154727624260439587609221810431482953153105055583438476917734846147212043084713683663375207061678418856217191502529360907717298298775725917476829259189072619872864915171524138235367057288912397884224457195392094528088491360207214900597211024285479471542391050633717558816965105885881572025748968715414025372172316551486473796479072984757972515963111186418298474326285553279399228092635681932867210341755310678883378889502833687797992310189961790409107247555540252035094778853911125536694552331977928165584513365652145721583007181436964461662279205403333070521001140286567529474571703647176640059880772404271080791591518866530861751968708929158511462023686017118720853154973336117233435351305998943350742123904835121553878895105192620346595101728506631179045234914903043689382274836687262514691797890109032333812515605254085424416149268283647157033143873820776723892662345540240521425304921686786294998499542879948409349050781044986914074726063470338215995794494426633155719649326151589318888111104983755496180547285318897483206398300905226541453699347435589268126263531915712184904706714727663018101870743591563385097978218017728722091119693539002914815936879617114112, - 451387872836432728015973868454836731440525105758384242386935142355791275998712436438441458357996561767089021537357995743474192667842222229403925592422745179247138723847437109391206749122650624786739124453709013230495127088046284331808083931428373409916876965958859521016979556951542653629444115864495887148990140905528386839759363659420076349628542070000000038776571177238022319917730526110568467315899329184263496375685799032516884968055376704044776484649615209459944899789262704418641401411451393654023263271640609474863642282926401768910570995221004823602696756273445796302101357569017206335132220821658217722885230681564735868519488699044843959792556420519126855813162820560606353570582940974197556031460575622026904872276026141242173622722497643140512934588330164883948272832636188217332533731883921303193003168678585089195808918486290729593305304198586839906678700889575351034854550634012268198400281919616438307031938132682920168693604143972313523988791064397784532029120041635997765256124290997455782812920270050079400126549148220163660579344877322098187940369402319103386892599514337776983685164852085383772606185031258684075596968457778428843102111561460973641902252935968738841459790776938182347363540441924255312917901166536491252187282603943878703200756775035198359721097340389797419803816867385687834983387184964819834834009558337556316578547593786437742679132496386223987167638916192501017964333611193324334298848677061218798104880127627177555386806757665124734718608508409685372466179457938004577229640284263014368534792871723112898325093937547360269171150638769403704287639687818104997117580743661641513965319951867799150786947672722144824236293436119158612288666434162814524511148335305575166628081684812138299517574430947724883299751962402904023045300727996135708644598385512707902036664749419836813780939869316513354611202703723759870565864354797371613321901868361097312475892597519723924156586098516587226603686113327600639376655698209939575910680292879653919133300809625573451781473356141072600877560209295733754181348069645134843046066382562671111523557162106195982506414581400489053750484099873587962559402141997555461215182006671190618584627532009703924425800665840661155098866388286726805647349560010362228207652618781756495183606526929371144925105549193073130496790040949855066137321424318131797645597911013675806018715293126369422991500598228604885178018438350429700361638514057243976420743250001706871395778924926698568148211355975075991801601655679411769282342387819360523566644128996006320504720097249224987915770720610045996412456926847032878014207721390226179945060683374034968538646681683682000291056391363994023023237264949618908779799297675081864547962167889767048282158846693114298376407873919586845585500256429408651361466421681261871189082145235566140280974736207781504848540059407341211290436935908839058686010536133165958938382157962437878384261671720858428910658697396340781250971986592796295857251821158215754158404658929304016548756948855538641423338327759528240988130580764897262824949533797020053853133841403594631862195527717572621885602420103323208243928042075747628319531815678996241148468282428349991451656465159686868782974509172403986150853006956277173621328222484704506098955919804492518241175912138508812437104690820969703607482755754459381228118957012486531308537492167727784640672017905985102614425762425284125647575832299250989789154605185183166085542706705883738505702509445681127110823092028781772190740256579629774717722188219369888700273831453421179018602990508121808383172187657719492730219462290114845450192459745894649761621504044864187134375366302553422278242212708101464915103832686628672037811234886942463608343813333176799312505191561359634853119752319307226324067324679392537617420216525491048358383049515491690713505827251321564204335972386818079509025952069542540687154793310462149080444800195396148592977705925558316254752027744420769861224422348297837158056636232553650931854269040179218512281401491244104325132658895929140182241565598747422622888380732246635073616334720202805907791906269886261712210693012704631282308941818312183578436026910797277286194887907153180406738216129319434584685615368512682937852189815518216296466394449682380654120115331499058749897989849061495599176756968898536906866880466092402983687566861781427214883577376407283274475562188029774894215631732555045761087685039378418855730219572074539451243295477302402210050942888590676321798086743204666255784600836665210335633544237121309243029582542164726406461736908584721442205521711240287763227525807083800590384707959318532308737554397133663587774983491293682069932142585649374433479865983600286116215175535147900812956627235900603793655857681535176197617445988186660193805281582629300318017178939057285081048077538921128291057297342501201771799217992217034412441306682182356039239608028088444201336233394229350167904174555365659605900174798416608296922110064065307628001811258526553895128151376025580001395245761897579111651810073696181306513145752492424844966676560408078038120126598283208390633162179937492680381346043553441347046131385684796125692867244489254831020749522800413433892150839833704241646322233509912496487139780050865649190526950564750052910802427320289041676259515132086013092616101032328003742598105317873240998785893004877317574777775780354718086610680972662672427292972391957212605938989942061648706499276232170136520329145102420236571291678925332291089313078575136097565935030040185389659499983620619545187018493918667281520640180137622336809544739587711427806950343015436078812108135623855110086250267503521405187679156994451346232417309243431181704821959406589919064592745952637420933796110356970043739711240510146930174647042621861191556641353776790461159582554818776807293913000988252184076322814053754452810556700593363829884980949926167538655942007552941125187038413288530629691352805506451293716695338756460147334673322620249738306456059376696731476459568564492223179499342708334946442230941155019155471396745345027243243431298503387575177393818800499032974962173343307599479278588607061003331268735512012988443306333327163971894511971770966259778608943667464365289639038651951176667055572171112131891823295538192616755914372719605623032424820395154363339620262135188579386655354434305961224567197055382254993874011811554976667277769742107387102286614153215808213944489207243430067468088966807750236883219263591067322530860494393739269818761677665983336545729675661566953673722123930286464338914525619296221107935741516830985369018577284271145913309767504358885783535424115285340327692440254393525556987222966505452733737807142376980406918362832459033691997046454813791634646773803709608904816663095954870074994139013567763880529133292250796240364112512084978497996656202859241131291214318642790347795111170462902354458448597757865653711394688208696048211543167254799847361456182313604066912044856356230385991474786267256221069167814186969128700679375943685712635708526800082957232568817329353596685721634318390538129685805794351729528740527946584826986571925619365148767592729526170720546628683927673372379822250663548016911552545609235856143690909625638483471054035276447399338662693106026796358574121438986049813083207896753972744413514080678971298047332175008179575632804400007310894542641920044194385402614636251936702886791331264322330971808346417557974951791637227440329470926231297379589875745260700388047369881340787567267950780736719580970392685957163572458578404681474579777288515735932708083416581399127595970558613616846086906591022773140603569079970253729342677664861189930002325403050432665031839916210016457954526482785450442332559748368058398344691071489863635391992465104204901056758834619021898712448990677433713559457920709733281537650829016275933282717090725059124981496366201888635907093297839728732357171946541862265249596622629886321580627511808551387135750528396397302075622658027189342129122444989322490630292295208656871960475603438145476038050981072514561031239676542538365507400654241096275737344055968508937580345183833867635786371775030421509974198543370927318444300453194195017834402961971386245642485988083524077039052880476117585930256728198939846380853897725324244363169139658539912794058800858159986164226406925405706200851244911825299853472570792142314396842558435189920639541688680101785684846071055157123062209110833477747430271361365694102145234813202962345505623292015195246920621781596720181194428530782103019722989016221629706778449626617990086818993665902662123939928103133485593969502061805227378600044726851411206962198450830910270618992640, - 46539827616709120275285315920386571270882710372646515048294027620768643753905442878123676232542839552081950059540952333290452092365425101730361231746427193935970795913924196091513804598950109040558537978141794648657258645562567165051754645396188119736316708052766970156921412838316054148461271908549879897639194079477643508837379963069901218264689858969470719587690056274157020902448533573874988518177826164766267934217252161090866240297619195326822817847797088599296011307438135706154766985292559803114289598098680960005278899782868803471805001925143038250451052189452132268834060523810314853731130538346059490716413363754044616395803191545386547941821862016694351765680401213576203907469061691506386232212091699988816772522467634187882176615035079267227452256404214377076313082364301455811525052051950422769540350293368515555299095321147989333771992472303347038898389613594035780197135476251317096230100120639930309567996924996044964182390875039046629328597360816274978303451808999940283068571970042462959395961441067918852202070918982627380823429984275098183236553641511328179986593937404952377517457474882827099165770917747819927764413445272453198174479516245275476501213184568314891609397722128953913910218232369188008396044952699880015849021057606084355664254469193697104507910397702179826550338404606097103181382767729677549960527417861938272303713122738092178573827098625307067968083589142432166520035203282800156355279362724970527425069060763689515301972876645706986091001471572959834108577849991638691355075557607880860550209020772690349150681785570157042685871538117327946894082434056995840010307013564206265171697445616124474789209753884025746661218570015089935704636011038599168454250101764280870157985963818042760345294680880444175739724392661608870324309782186391915678584160975110989297935722643101725079339840354583777578025803820200704225604930812274943006424171561021868224828084375073998229449378374082883300414328293655402751946712567950190725256094851470492716860932512601128762613670848657383825178527619820706943090321636806971116308104743372795754172428238061414948630174319203964833813280214688442994498449495183348499526202728906675405276359628666311616095474392366084160772620591897247241414197007573127151745943149984507720273950055652706130341429811401461747998801141792111515159674653550522698948161058302383814912643800034416579602895350731745401198522789986267524267960355558193544240080021043203651158935255662952957071222728203951255544272287247529464896631655741438989030601569676697019469226103119447999020871408939636730305194984981910703869729043506222636119133116571217713808332919374730131054579231309216512253944342516491468301417182956673934816422786430788743756501209405354789781778740579844682234336429299586627186331428962270390476913220202954694210070796652909008972835452103496071636306500818678299928333215307053853890779707154135003068256421119676540795013956621291789620223427637966410467931942354861380982805814140706865363820952266220101474956449552262982415083843254133688499072636367486667082036249731977560819709757067273878990391232184434334703993834416424361925377639257133706442012000447311305573329907704986752976980608014486494118231560346093012553760203469523110084592429729898384455616585898247109493347713815420092406279540072472798406346449122015056852185357749844417702762304530462667259283726560692606263203959457819882923473001034514398274254234485807941396941905507428663270615648415563802791122295728375777499404232143511441887219842066014292659094687790606088720204818740716151589925953991109081803563575688352880116913494941943915651250697100308886136612630252878332867638946022378048277781631331088179856459827362934728615641589009820219720976434911833002349781438482090914054134801789741547463754988467655254164142345190641657841580901366911809843230629252697418491992236315865588651893861429875083774023719712260826288734290623437598095620259232410854270713460206164830716660539462102133715018314236366326636240414592538907881378865285468230034633373090279851063051647079313905012458592165263706685058279304747519324639587912936065401628512878487930472209094735103839953739168688462600466938539443673947438943568469447940028682872727761494358917717861378222971886580641191848627110233117761215034363911540599394429443925119943781591623460468732610981020365381338091613162441509495393514532571782410389573952088878542135789411836528692010769354983212061509510424666987213397363086978429988740151723094829945073945202823810834475445558721755428524273150252451009071643356703773109419595156978177720047410452141869505421935385018364152937508917549710980362884107672039465431539197990752156601628100762224236749090800986026702414866186388461797541360093141543248279519281122077993655211604376601400282280719713094386690812218789492489392373059008729722755752644714703432839489021828770009805631672670995812968785385551791276064184023459608844874650802490190116806288251742786649526524655408844312884299771797100081129508474336577560950376083555368894285068584995245190626755711371905152485218795246637509980433845039816917241354347612980200665202303039503999435206261348805297461422363492502198139970937084859205492189564376049096973492480420881570712794485039088957266406230278308090386471768496526269756436393033788592753307978293396537348517284808175975758823070887982636275206294267822138015517814242307377236037722601097120608896973660653559020105709911872698092434970144277299678010486112776316961144467466087620484533734694887851121965727834714547380832106395644607964328418707058692376111722243173544513474739680729223727658591554911942566301855681143532389947560244986532274555122417522369772179858764266207477107748679150474574900788666523741689122134155981967684883654156774417801444137710113508272752595705805332961306164423902902263482705348302838117239052105780693869129674229309120588476474395827266855869674888092431743742060039231383694001140328244141437326680596586250069228991204954686662550040363757660941183425122973720872659304417506068624199263213445460443472311348741934311633975523635361306800452223277641972839145265235720007271885591507054503504931663984547770679373803541951283619093648924413654734984405809941379633257743889230146568300895276081371335584562894977974519682575154768141970974188720779596158430166073453401945476687433179531335733583188498250143009283815371825645752839556850557054366242869218380486911922319180842574520239563252601462427640961288083914066449584126972526074774311328023462929644624679982945650610471884101079858841536846468569061669931459440348481849950183894757461395865463897806109730638742114974012640529934651228017609990358138010276055580489146283192282324673782888913268481066668163306724035664256995897815632354123610147666203239694711296247955571628821360780925501562750498776322854525648248966891404847485051643059915813423993160129310172064580521013317863513881102278412001995417812878224215357227153158175017383653670190583996351522742546722488346937650985459360126297567542685140138402039201991392061482411627774024410696359050114517445797654418750962617947541786396523886504787440594995755651348455067923895875911861446362428494871735127305885248134868101710522726378097446418441308117470190445718360386232973191210311856618589745332175174642723896321610251893130209087013653570911159949326201829770932035286111156332794618994630262169720942895151839030528186891614630788442556773854078896850856762742454834916055315065302867125853376845126429029856442089298962825411389718827155313312754701448137231231605113158552506252185192250174723588104535438791460569984420767617759894778804653331665587051276716777805516572126636828509423494289606741267611627655034930644629344150377014307652143714847416888704825710520680728007035006464212173729014813706466788672685402429442508101773769703629838858278219491249323639801244449713091288559323786624296540721300700915914824248263543600887256415205512111584770494814381685905609172267120104978560355183158757099765770448753277621468619915790035700651416633073708043046997713844413309211751511982090742388557247258005859013880041066989974533972334248365680498851603772658071280105090998279734111631120323567772857060504850766080657275819525501548079801700832594018454192713536167440713937015906491644582486556872623584044525095890977407309864411661826837959675671602835051975550226315398391413148748427335028531508001988313395305120892039732800557306756572955070165194243047747612432397248055088454499762470239977675905352795496346844836989695178995400704, - 4533183480044659517284562515228273779942424360580896761781936799280933307215724657089794379581558080307825538989919754932363057527194103686501158260845830297334271973771626786322958715426195259318030965375342208730452496642813471587591197122998064638051213959071006737315520992168127600802200060492579713419144644764282658825457780267517307570621326377944470804324198106010065672969953400062823807412667711172876922452583948517545058232799103004353021172716255783781357689479594209915508651422687411359649090137414633125390427325763367844017936322472185727695412795949953731978552767446342130313943265410588659719864966753337314430448736922939314294405345241969396230164924711479344366197726264686258872734343775530267795199085192308581692657804348223137784393702843674143517023495271968283949525288227489774069221257263926677581576027988519514541129712782955685546358648909917591045332290972597913839366052475631746209383420593903350981270667832555228212860212518029371009599700381797179025648121529810387305224355178191632576539935813204664390238177046226203996596964408603733762766484298792388096228922732436746742621119215225320133675385657889165993697152321292277805727015698333447783099381957714499417671291022704296261372644482657312517128087477836192468017367948238347854997673403526009259523456969200708372063273435484702327831957824422295980242555256882025438731025009413902976359238442250848901501937122642639069347820720078377928651148697644876315570770798013112840342796385316923584577206842186262546108831017842347059055112181379759361054062982730749039859744526285812482770869950096450648586610911849989907480713287964188235630991366035382826561500814958180521659834495924727250154560270976641000596318663949080308687194461560837228036650533049475792793811313541183846901321925553787354219688946046374254506447288593866816332386759267290151596263848646759342913509890865043446900301479810103588501955810999075762939589766421297235051464373213754580067894870448077625073218225615343973292006472398419588201197210465968760030913087203879636308129881030436522788829660107943769625589912116577133804940921308529487935365503458758972571690710512938322388862961317284433084408755547405525711584804950604532444561750520516798322189451834487836699589933224959979874875262349669221074845741260545829691555136125380371747421682352007611287066854656569121916086512333277431995550018170177140251934016374374549287965323640618773943430158474236417812611493216313075099582830972875193216428221758424741800462321397403455463268769578685984230569859638427319045960552727196289894923617603690523517562863577834188692116615448545718296772322644660876007459690170855134463648500904220466390045028541511790027076970709572621534914600979859798812354323375426812299369835478856288977064310091524450472665960804505448517827427222523281371980290535893914726427422794809607594353594171167156940072480755893486200022929307823645967511549358112257726209412132640217657109048159411510678569670190043471063839282739014996248562942640528908352086976847581671186708752655863759983179166001726457244956335915179997103851597062127769841359714069306319205653406987082560601447856585638729528297294808601724325757076522650378228633744468330800725291560833347838856043691589816709876357179644559336387043956208754721792599652038499010675135822138255588485557209337393811181827017516539518808094802008367554855557396998987487241624133816944592474150390122452070438518320632696110980716926246505007616924347300455927011235498974470848056485253954011215634883630108569066785777408690058193337651069911743753034310537538699602025237003034855139105348681069150916956021917069258083250138562094615950118773386779213070941289162340437632764396376558801778856925986454289031229079534909482238395975733512853766113415739066025414231086572750964585772412200119017306705172886992337781083182166872093330784834289233374371442502072411173705885505285793927049507595931386455113469314133631990142154065668287942646850299384378170365276152640316255193530752124668070998691037506028670670013902701592470571226763465087877068796182726552383720063606210749333646088636341484869147922402939574185794118318845247768792174076021308895529774080855374724200514849213944728884901381739308038710607214675514971156467127295253568937161337281669302664918712958986200575253033120770904656423215443509811840975970664014225861666966375632919494374078270921508158774424244838848679258807863390856924355430369069702824227329844195793537737756250655088937618688536171241975253111925814542927539694590461290023184018230013279444513755078649472645569519720672611977402816459863192828921778424131878235395416494884435774357804118268569576654094874464735601191995313545624489297656191452681315384446887463546565478518646933370668682882419967682494878600365154741364919549406809483203412484319480516677580010112240700478308642396978245324911761428782330159841839565538473031218360388580099312754559651410181048773603077185199854954556864294427039287492942084551394189734017969431640866167591072381628548480851730564952763718497479560636418627170260885637055557216752809575915867755563962728591111725300916253088161224722103006919754021130774352194979255768904168634636243838785375459564872726517038862865043896072482702626575231992639324701496545322446041345530292507887332230898181844511671025159514365590900407546920013586032485526878997713736894970520670409911842341219934006473542639133321504496987418614835568143492760070880234207757343980077832430918385524808792858050921206104462940527519536862765088445538217364366152586444005085220733808723492040362675507217541317954649535315139395146471167924847327121946204593778354589060961882845426391715989891515672128042309330181708830716876702127573490714005838530887839969233398154104862325825339396633959521091493886480236420457757554372627874719174980928358245942127979865126724494501634321187639533992351688294557532981095793696038791991537763919300659074055316178086044771287359420576349765708437999134794615962986531461804341063652545977455025832911046568751537703684394788221360977931610993848055197315802061592793746812571506916996344205929006071781687148179097504088051613802166048988822939577893468444852777841295531519381895970035145184332797849056275368731859978903034970940274566087536393529913036412815663985040425875785507197995278227912604727825913745140716694206247990913891828987900226955540516768571525220465776997335376013489936142130895396203384672934528720849335643683925529978501830754306757370538034542365980012011010017538036979573736876313958042923374733857222816047846445485279473259304935926694584617818047299298773036626559141206006606770742315436245016665380260056931766629328995197506350725428174543729528891529958657711922679836694903240223751073279198567687810378096074425366936686049443345961489637311231725765070881696474426376536352273073603698475639838948944532439822805764908497721718545298243282907204627277212862385746257276810183123718374925665327088974226755994489928513979661448474499111441158381594961091494924859516965633926414140882242962078056028790951506342230209613022718345313589644337275048983001523415010076119793140363818619360214847733509999772978334439503961572831851610111050719655751473510521620477928407105508897331456973502993384381813402658931521117414745663328455351827418229467593427558762114588095374700370209512381465757863390235847369264744325623210735576249507834491096428166356055435974465591062030392077251871631669901141903232249662024033861093345044632405416655142302119325957574739150690871041828386834900465032530271312777754577020098875992457036685387318123992366458471226952565061074013427044404782595354802390761634694430127735074030048033668010931666301710210005872217817354912482711876277832137880213064281549231581837598837668727211584000422779427847436326184776704609090157685187540357350061960557283539036808454589544725414474264128469436144938695491885119108981796451674599843479443211690165622685437866780777690774878334210050933043831305447075687791288313810931046351254128849843141626728066450329990015886264018005283139697170795617117605567365369154276486044875954687820253185145096139701988199835177207363460510883832282789483579152387934006098963229418301358456983351192963866385001616862752017383851538680918297817651424154669221011325739096170718804640635341779423801457675377210107626229384763121219578822119342122176470475496111917543299243675286605642918138843129306206947813125274307809347094722796031735349296505636748525568, - 416866868724948436049260311493103940845289001211345105921948254465165519076660376693916627377157001027315460090816976347402175304787959066838422469564880217456308814344345336104354959781401866118707221444837474395252368179734490184497161113867119014196659300254384750054107681673417329447666785942267968963305166208168224182036527284881355799859999803998781249941495896172475432836516240683053233507163251444683642176525549108833295256434892925532384803531955662843681316900799101057968033275172757366916831201550031009155179995441488757522484544363819298969412238353538585360691723068968357918666593777148568972572643653798916597363418823345587059586736195180164655875309303680990917257484362016216653054109120228158079377909161596840479376023415680865406072078753668218328988192117084809127596306302283611123082925091895419248741279804780807107506174840586995927100489273893322748259089861082136907695773630421957417309845503958885963323327837336864997072616945932744704058760774374754952306418012346136389139753015344305061372591747456359721852023550009618929517606509445426826571569781545801254746475208373222476490806344802531488895880375898759951678059052792316724113114869178163925724957494480936131401753264219934446745702696640633020895703259209686656175473847864283377745597642005945720875621688962315286716019112246113368223152350928011816072560206202618757310800249278127386095921610731993426628350972465595895261758595248383074060022559378460331438765529494246733812748414085664292116615342782157889796566675041083693051338205282184476174854547370408082171091173816986563044132033355598106470537804283596173628286427246304269624062089743310542901253655616091827502039426829791714520990063988951028998327455231976365371133934299862106047507705738992456683491836378356677290573138762953875102421296155084038933110399590331508695813714331150493905043855841342081946131831066958891205640928734766594578065269655582947908646132271029847562049974135368551548500982363731001810057316638323615178777377018986135109069133058701025142912809249100868708314681265985121218085664243616446185149217200329470370343756091395105954396142456056028386994866161191626928380332181898498422476244943623507601871635548987293529535342482374336182230729240462940057810849269522704236426907402604632134346091782066819963090327255504629623530569259752348722249180447143797588155706594913971916211478433729095745650979982553490982776575914981470830483994727440720862539218124746023063056362099066464148448747691948944011661717739745760464415333018379653495385791676816965408270037301069539225143038133930862967716028781321056775584952593446855839873845795808667954949875476387851554283875207998476910777048376301756943569988091561828868498188510536919594317937560827697663865091435616980384102341177214646565986475298106996958832933256053161784255067020484889975316000062171859568179553431402782720208277862327207904730433412884490580241934706050570145743230592059719642659489657167882639569646911029645693902080175821455501233736988166902678771167268683763891985532267693778250640213897979972468874501184979100899904466291812956467337317385670520315264641279919929953414973957918094959694190542448932266094315827378831827942040770728918888458548093765711276672321265264766819046132674735062814033254252153582348178377648030239273566231628415113046280548043784091931590702545240439173743914130457794159053903144182069762282140788661663484415394300575376501216394302930786306108496215576956998079609835955454717647938312061247951968014361667522814967156013191850706903751160844026997591480638289133885152676352131042937370523735135290504076989810163713071418474284408184310036165030816668090647072597276659597509023457450807209580200442605270747021687258355379386665798505293290703223168481937336167867705949022751434495273496549613706778472124177477563298815016392912608826815314291271209084136703188855768744901006426853349037412959326440968514305361528712162770574574240255227688858745795468768766731145606658768099880096118721860609552083537801258438904818243606466968599278982187572238216224504071574544435060128988174305291051820523312225752707385807028573810006064224016362805682170365800130399009926021253905898681392790073937258842515379934610654510486467997238751127083121557418533429243040909448163347124886813821736444573644845286014413982621608425708712326356509649176609045617221887675797277451320285179146527106372001439014308835878920318593005047747740961842277023125570694284075859961641651308602518261624764022881103840831281443013079313779449387487179052974803148358189506824973817227276743996063971470792246535047132738052434480814061191519438939861654434877983131984057050195099906741599940366242683489821877436428518723754788149975304946813838706320589611574515521987480676785591886472394681698789281715944985573954049756183003622880340507028257255325823004364776376542339629303471152756514600827568891205837053463172832343739470844617733062869907092116570216532584141855569804708575072708290572037536304381001004908142047886780611294045750229294761090394211055414666528701154418879838641029195029602031681928788537672322185191738970082881654817063112572710819976150581643934373868523152065123483184797244747232082694511761383252895280713176050051958096790496042636920918684634141340893236706108397169474723661577517436768654504948536801790332373336636415107381056078598714233721315427301618345896015321002521666088304289511196659297365838441695098905125473953801617880885907181238732760501859711596388866953833067544229479660653560500743595763343964771216021922970202528025014177264985215757878212992085690800677476697620530201506516560203234020215102737801306389942751632872036655211790956537740482846212564328929476367285964150132385330248192854407933099704463583287525603692522006615772898896222233576723881040733155760965260188249248957836411334225598370565300441904545156881650811155357928951874584022853194759195076914939570654213475187453023893247879347497095789445749795573913657553993240899908831111325340314487181119510262580902737092668387454555899132773278999216982545237502401394866827018329057337335595480845627567889377059662199188038813357184616144179380541938208817818513630816460262639006379792608051636386890971665429763761271547885230482370850755006941028035906801886671067887697176014471777214105936517554042748216699391248721139431857295120870896161315748700887107695198277429818537592565317678787653081268973093778056091714642505495605083001793885945329831776857341804286209491101266557231498489181832900689412653172054200928620808641924740342768141594102423482715576682390408706459773449975585934814343084806489340934733486642685499727416544430044889358172564483930288685385125551685344189646922737554404055096696474461833183368040240758087393294048357967059001273394619189478401801597757080059525326793317667654397074630680463220499493500339757060964653305683420772702671994342941463400264049465480049750391167482282877635330845910511968554952134881142745369323767272220935074256961074034192948833918555465084266018673906586385162677431600516422398587676634707905746566718757732760257713920179018366792386102929308939416639188649556398991429854984315260559735468154580867295203746283038524489447128398521162912157806261880008059278430084095905316523209521729582429033922371011710920410573591800719226253566435779583488781484312486516677136696551420185445779073008558914334073052182680265099609532999688227292001516603506148593077499663312336783258375146019078359357407185424639925028008700960568850346855468121943063624772118177474372202051992107767459127673507481420477590156573042421527299365652926898504917679813399295739056865698167991641858588615005153784110097705560030803438659421583755865257832345645918901358316436950899656104294515523083164770565796431460324458317490961370614676694965058782570007384117526726100351923525497595252921855415792485170758321867157435468107635348830016633295010408644726746319580540598120464545372880286521901604905261058840562271714067590880449659832059748529873593715957423187975102726343916936224310670187813084069270944383083371577318502439158485604259196356346344727301507661158556198705543167934534253385261506586781529222641898923360082375049059837361368055613056051462078775884112705933826378315622663707276923384787266798925716428842888665106639967430229696843072327246515473935583672625933938000888265746059075241630353858249306830364013004681179758331990302132611460780449277088400935537545201057792, - 36160234177986184322286784338053041020939569327201156318625039772113095401702428284989988933570466788008521353680634095909163322003338103590791917904523711314467913137305802801736006056237462424102497147509758516530497037227684258093005318625878643690083877217669441873178050908004635031713728617884799969790343135882365396522965827954066930833087491733824590321253268452124079528918048340667988349128742204185389798752023735277304354509210047749593841412645654354764050531032028270546752014262674667279754428483277013905907120044775058212707468924144017484750259415222462462660557087753927508562228257516779390080165784190971385064726920853850685389364861339407708176535498690173963252376017811556421143309527829075770349492557385554424660908183152141131484270764725447490118681709786218064396271790998410895063285729486868483904118787587096074809961446552625516716123849513556759033102985850800215995178848159270380885997426484616806168694268488676352641036313503557808448766257637245855736766574101545077790323409884326269584458098430528981262671161661140980678818880359695912188876261554321652724823160368929362653517213418253504949226967610610131294686472174833109572861556830849540385871794132989401072590800768157997147632519850708794785096899097324854742340544355399021056413418480914257680659726223153702394745505399414984284915640199001039594040145542062445175729837006733892789876537364359848766061097783202288680962639751923761621373045129667103537588122828984394073019047210130109429106754402807305750434695072886501192113858326962889225076812154792940942327316011419310477619153592854250238158666459061873557314009921935244260959772242958910382850851040183725230932612654453875808220738252626463661314408930790688168715094661873437255367252645192504765401228916776255133651541813547083305610184477239901210927965246542069868119509158353755249866601660053999510952043294110803083512116315899793222376748269833817398443360109284306280884614871489570658209050763978346936440260577872893093649474632546410205331370207482154439190902597752236409073345668344917938061123429075527953600859840480019874341028656578530535340009268476230767732816369968927907215855670699682664205031818553429188177310733194034872518209721442640959459337620102900734497703863019153241667192443414979988271329198320628899162265922956803302355047445788727520099613459698269254103891257594831976346528161923908203152722211843370346084697271330650857318158958570733884843005118226300909654394906769893925455962036945150782171306614840366182230827678169056277569532587255570850993891271724341477539551086113219748789186435382977948444956155563468545968397901991117752932824649019477853214883109512241176759814210229105432900467920538859286324588297349558285112534333522499688921379382764171620859878992879741909931462585024687075017174468943666665849513450147999599855143417053530648175532196035259060121573745893059077116327543323190829766620781346845232446627671618017515130733571352199708420292175319757352578076354036972823108514926106917472615118739822244877276454089215236088275629518122674707817659219374702698552554081382095772213068293656871529210409331757615173452848552335009713064559155639078309230284009031292920599344181855563748735456300498605615933349235850622270607263282243010687464426617095473449326081975534711913503501625665483326454421821278353855451918111390321034788344020421789866600181400269050287062783971293890672612976065130640890141165346741781397297362737598513214650567979963212064511034984136145938587274259340599827793376033261657965364591203092932503865861126372158407254624071085884620003027780708511118124017571537527648980091444251398858789591934903178122425947799040021164378532910862721872907605318041906696423967334272614412410733147976237730083004137085501875316808379874948369178277109412385659000490254799892081065211740489683090727066548567648631411047365860503106413222401325558709664923388898491430981127756136695667482207869372745508044174313385067982683765144348865933930123623432968783933904001725548747576745125946140422891071742221299350494509689346878982054319771050899032167289726880615951283002348191716818955630801334116428712230104521551352304201174130984739127779826229254901993855497330119584115237649092695166278523882079796509348527316047027669480084106176870157181822340352261271074576183703376460593386289285080445854707161465348769812552153543522274602321897973715109378846953304700391367783239521855876403981605650060093449843540869366887688074787609332096179599116022341280837466425588499706265528669626273126858286491443899760607564414323580727821620347350997674814431735558549031399171423409412840860324533088751745725231085978903465199494590808338059388519907695002127096773581101089740850474871265111072911872884582535339368053268235310918921988037495854288043242959481572137288817424002156466577391737909253332919116009588974834954832107100829488598596821968495406784020896477388203210089291074781036008363281221312988457146092694496434260464192109137943705782099181197685913324126038983437157209701803156461321542702486686717067275694271555827512282677194694371288993606898330171999228784914138784611501135448941061696426846447323298122419111910066226562342694855440730753735959076563983751814688196513471436245609643132849184957866460399247447641282241819929492695584088039302959277282586209516031452963290320889271868993109657663394121352952806111821678535572288329556728627611383608288890126572238701125101458775869076018644118306238230492081796292493746307869944520355974165841728583659641882127586186205715917765127298073753876401213672139080470163420024497539207280129820374347550282458780651837553793920583121315403173580249915151357765995675649972620294266097513922555688890221069895142669903804110177011187689253000585704180794445367449763019549369789173103651244472020662586255799677700835418399965037283906890646646519178226979773680698106019695962313841379612472131289737671537776570435232831178913353000347188220874596886162410574397703232056835711187419074902080475569138225621710281494279017390016655703440531711094008587030986951160858528627225253713049358590602376618492973412171082078855057882492216372981372711484610744935747750275763488774180395896588599554589926968969057821904932094692045327410944869760222195736724965720871226165604260334017383038841195915593782148955006215110441736831187285789411063582004566761947186477213055991070017424622976949726352673319757507453830450961715919181662837855648221798049848255130436115616900677946382261043046188297918945300157735447724451442825807145490996096242436880556161427190110588489008965091573326884807151790925076575526592939635612616923854113201711821602666436159075802679364236456048636259923677012638864655157287587704349539706437274670004645360478412234923449379504507317849627567205864511089747795707382875624135952845205560969086407763881961147027922716078440065093264632311059483311510347474459308299599809393453760389067535292418796361312760337317947982136980057764742895672160162758652697539555445680717686839103082811448000808888470178636106548328928514559160555851883561549989072810684303859490374416419517035278184263982930425002165236717461053613990320521136369224905277443985600492499880660946503571314539383110206169097090268502003293425758421833207334042852296922553792475833781255125959042912809630506625440700337703534040000873042477500227543695058864099116175239767830048615215172302862892899260892161183088254684835369789573611642171999785325122904352662665276629302872149162026207989109962679790725403321393811230228544916109130119746936366843939477876895179209743996930854528270924726767472465543918472204129958470347970865325909737958489405447550013837971698150793268681379886718030886760986762604924815625129914694424963328230972651076584546747026177398496383066832573162931259640649853335187270958444542383068326583386023107310923385107024947656606569551804027445707545155683299035458164211589996440563403538400985414339657591153780176721455268849595287149304126233922925150280792274511438825335753092294574373041078535016928726699172975534124693584154303847085442387353235325160996080307214812102289920421558625782330374718822866197701765281736735192128725069670431724014790971835311761937235651857668704109046156264457445843500398839032899138463018903552586311410905270582893898456867834078294168359048275213248628802860117877520900230109599241993175935495176037812700771748108122921981254832092086272, - 2955424196512578051806207642804486156565800864190182235260302132843444048589828676827405328201443137994095288943920615659742238477768220944398263322169594556178739435676551770660885942018741420605365850435665282218830495679727989988761215024772780370458164006067930244233897719189398060889729098864870609235997443265330752879556046217057793672129249876160865284159479560362951188405539572146636983078308364073949805688787530410180067950295659288057186729186585700457535233073001890437860111833347472754670373491777472079461156671893285292239505103929669038945997043754344606898680706020792737143871685255349175943775671004518514193174988888535487236140097387829619565083275787559878579982279735198307701338236057959200388502514652231041598511876774534751646991273412517878220154025887855121883666914744253237028145597914108944638926096859810390883103989672275128020123078819480393750622569631802031981284249539818113938221129950677392205273202095971687501280991733343836142553207653061285771769217694147287251088183216512604238375394035862544573226713049896040250953035214086346645418514218804276551130520628906352087085214957945571257043631121289311261096858496621970911351427548520491413519750572984936250435312239517534892706156011072296496982944337579171942271311687961396826060130595388057668693835407659228975201840798810545420620498348132560041498026322080809168203273244882345977607398770326526195321629119171041485763657402113509131034402524056332373638755289750131116439508416552192368312511771572969955376953609942790552351925580565193882774661308865551557995768937302102536634383407693486515842136355337956450598908353150056654645900149052056882238197845269068041559385230530934259995446429190483612046728148322291063724157942371352199129341369900831069494433374922849774969168695264246756732978047649142102197077758041518074636351273194442991491193094000221463710480833107749977893998108727644881774897897914775439492874069769986464059152043403521423541280490142265277342243231951565155420208357495181952511030563026796698171021427352022657925359350382080789865904078978056868266952556888029862168677370002330573832598311592358142729467570836680975360162054229204160327536641883227920046995637189908089267616330864379000685736554556580922304352334542710229925509462183102172540089891427954607222124708055094799272770200637618061212498190870236064546218837321559744657801786840192641946577098168164535934430395449773134646153289378493271283603720658018254008031552261656160235083837170357775072988709439459974939700580571501182612148741087186685944695702591084673558554171331110795655556427162961209544067393894120911089824786909074540886871561671514268913213505757303124059840632321882304179310051248576946249479292508914733339582016336228537061330641910857045786371430800685939901908183328836895837626053470697494519944323731631454088357541965450285190649765779187096335350591511273001145762621230572154537068187575557565267211954343043335960202699205853026020760583734649899028136829005888447281638192285510100433211170556431489776505105493381659690993767813047327118712957222207064001881218596931896873325241895109976243309742178220155239744199799887512584579615609367141184415070669332584947492517922737361474965192764781921350720929512867870717651876688870118893219510681285726248755371778202366786676087061007035706621913106510607431393893386057847416319415221976750455092683514757147432726483799514311612691749444214323665222967007791446025951448340672067351338007474188061834950519590340774913143470780545469443940561835760082264872314167228281451163537681489391279731419612461663829858743211466298179388337705834337457836741735525207465715818272305307601413886230942622015545878489826637935696253767800380141881185661684407417345692277469413696346630978841925596563468811906374818673265809814832335146666907784701879852680073717700447879226551411563764114364368549107286454464464295615232104712961105346384399191654951430325992578054019581473035202197390955925590819146736078550604213398220754619611009161031454492623005034919170286753424223686100013332152095119403181705827105549140312657788766860006179399416440284597692250781758413615665854993642002413348408095406130452070862812657212899575776533437676561560516875385835769591302771876828155351090056272079189402856826803139888611736548382829529085596620340198870530593329838214002308672495716751278856421929459055821548814304154253752672174460571233237372573497453556826511977777540867636399398015863385654472469266585433497881630264733166011689656981940946764992966724964558400064969026060197468527104532886697384951704822348445029507983664769359844081199359890726560458910479566057280383124552854045149198584136648005878668191561050651914656016726887531442473794054180036459753728976864226153198784433983802268220655379279925297749451447502852683457168594818169289622659534502955428887122106073386520029860533114369516347846567351370154917852124153479462479961603339445293786873335939682262505684066747433958383064600475974370627552147889906125677929828046596314610375406954356702845019156116297623502797106023082312964196905540798344181207855024479325614548425930870701369862539077161733456845513287629540459787535141312468704958226584691608110185133532178630552677988318230845792146591284189693143945447383207260205258140173473396892759697481781546409855448927065944034108917587283473948182399066374948676640808599192588249399833889591420747142337176376395186360140204356827181365966974783708553947283590093749573095519073549337902073162206823635066615241827310627681785306826187571999597996941042625240663466005652793570143219110283287870182718471241477336799707207428828252104653437021422102839772944522478718669971870073748518544769461813827649132763677482539703914564351631594094139480405512129569835572206797460262646803290715413938365352955184084242481932708065716790609468104833476129499519693046350929315319041567295906553874211416690753812973713135257066701846943918897867360782286848552659405237348611577944732371554468490473125638318867121240086987860901151734318606372281189900118264625184799656255301575396244796810955426065380040620811512628750685324480011205592312594818479918447327064363251667279963383074222486928704491250342840146143138028976413036706312919499660955027520977419125082003513092065285509345158181609757859412775528391555098399670067861065810266737433496048336302570518911883569901150956029269190937748443931695827928674408591631588680876320382258028475319725106180804690133964227792924906827283370843187025628669112696569057268337610291823715642194994081573185313714702667974579802565382989274485248942209383542804712373702828516965671896377519565759771342614637950011413137173717487148028850471724885696937727615804343071253075717992114675847988830281852003639938190415799553372817745205030220426076321452849170608472673404327136085368132615528051587034579098581806182775819097091586819559285131635742837300032054264675587706560675484181392556577893247329704556688690085564600970256960742119576275124934607357499506259906198935506337280153286748035828557799549013080058214209975978901678150104648144429419768320646798183293502993683000180163437280743627014898710555025006246496256849806707803473118303462752430935961079244376436057606186567591903124405269136447792513724700200044354814055994626844223355311353465567410917213467079532422339746692035495709743162329490479040690638886801388944438307241937184694465050068981182956609676193071172593896536879844370848341828960517437091723420585607663386072774270211254139265750308258390766741454475496815320639059215699222928662711113451957888256143018924884874334168546783795433846645143687099569177428857536086094537974891382562066077522818309647949192957332642922835777118167808745151469965826816931690562604629447226860032010108474269192711220301433241458491632877862294756831617708938286363145053324685508370868520225760691046294922431595222035855529820460764274114325336408758913038105343054316918958410689736254937829780928903080014847698341961871635897965428367552239674746994241087020844329920680646154474221626221318582596824791582908593248651181555363359282063130329608151246102937563601147832931772346882968763202081737535822171418709634413455575307440806085542830690171526626332399498080238486647113858431857459744918520121369756190635664335873879100779736588942278734187576686941189469180978919207229868777961921680283357502888263396075126754899918848, - 227268193403895808678904822258070222446789583129210212498264019864210352663320391830239678463892043864784039955558598549957965861697364763704554483203918168532340179826898416159543550186431266622058956010853696076055760111120272531999556516148585858332045461682769554214619168213173475914469680327443458666562254376753706655423969760777749918508913513672539554886651063665541869416823823666138452799550319330243450454129534086772238080618487578997799448548162368565751803191971619531140502704115320364635829282479098449180882299253410380753698915951985981610612722693505018370769973077732739600847622863070492594922125689529775223791617280226086059179282597090632236101653358124639433156061437736831939792489816339802383990410838809144565492406729888344572044402396707709069662394134047460660426762230636261553947498142913632691705986485988409961427874393348645487976488262571279276563263942282091353561080600909784060792728983995958735414482333284314463479279733213210937037739279945322409268797841274186829952542903559462253833433074621282888924225189766820043535407094883732592487915914544667206838078479880221614875871728226820210682928431906423316951083597375687025473254581839156203904023015612697668407363449598318048328924682784254379258357277268249481567877158839659598286571483495245010700871336607588329179943251529513937099069223496910222398541556468161792813927485491927491678736242682805088590701616661357903984027836673901341085319186722748758493995909709989585782075393704552100283418322944310037937533981348785830687324110175838064884949670428666562402182570850356985740579118647984806935880927077350309016374142628600564775865175626719180246120981994998813199741496964462211758497473924740257121412599185040623145582303311576424625239623290779083239751711107534025409278382421119280720885616438058671241636138902651310887004771512786124155514159164712019098679958190228313477978277550395068864999253366790815130227247168801291432874359523062961733268971823462166813218944924097020983538675515676696417902370444751890818161024557233939506700579134874461516440347647226804664103687609254636120982799947062214594858868561558718206659276249169337445792836158340198489895974130723926417663914223935991570336306467497571548867763451168205024947312839910653280150530447274092467184065892113682902243558271865260367106942154159916886785402986930506723098557979387703158994411318964206121409554210417088883748806561254945588715980046512459525313542144493689537737163232698242815068478918049911989617196462057169877250247343567003640523764412482837077572113852409211050866417361418486145713009630802500736961616585417816780620601277720159716544997313100725818146815003583992758666820819668918374007899424634667505381767922945485396066169772537341404785290504071580711228409022262347944598012429841097697241946609016368649979416621901873153065781138615035200443646349264840330770941254744209827578404911980800234064862701360658693178002166511627392804956098756511631867140382165718462023747465478797039987982342248900476362619240593021926177997200648806696844535113309547639006301782803229100442084142107542699515788413007247285651634447629220579253406257767842642418174634799278513982075402637587299829953177344921321334817068983985828473000706969126456291564503285199973254571745199381116076548281921018686198812415376090263130069861443218099058260186787229815265599107092616640939948440484292838089065749115582817886768385819111695046980646361259294922064133409007702179383039913323050738319119411428327561924669867422648214940419714750501396723485753950090720773233959336407197453185012699477923304585728187804973307809766762455550594577315795149710672576487255570841351073376007208847707725962418835085197689968662373123500085507759559696763183442128123357511851361128468616509705268598281421540740075084606890737813131764228352832443604187007538990183516431680348949857137575017681550251252924924076955269472333649036321605487330004368364523811462600941605157855088328433250444257517946812959401002774153596821469452993197287868296027449909507754144093070458587107434536478764126073603767199383417128657529595519121250457634949015503657480009292736588973007507534279141621697198778693598569565960408567817788012951860871828171875753802985053174249731522608968073325625942274193579588181346788085403226919819689927685530647610655321907728679724471220988542388125352696741049002675874248915074410547452632386023897242765583073635359155433856974869735254928899265695647955560636246412175343293646451917462904084516923770450829616848141561673157913174322546647059260842799353442370932543777224743359234032355397456245952396563092489992432300986107000328386523313941823732676492675772110402889109102383888400837805791814243208193357730459587456313173447887714828018983449950628833836004117462893838750330669894712223312897081343434942986612522415998226370330825193395169552406380804664331321618265812423090492301258038044269595847935545891371550439609259986091821806953443892680888697450956106996607285254130463398950693903149009240924110520965988302609887326200398775111225691325886025583485385663862077628939004982266131396194708012479113801830659814502060573681551222432578079584523264795513306049587236448881785392209123896840433632467993683452903565100068461478932923058039169741361068162136831988712252481189882104730367621008349718214243079857175846947990063898375987207899326485403422668601549621106168304661005552844446625334392273238750571360445122381851338093755210824486680933996561828265033754480759883287528795885780214766415198088645251094568399337168788682040533272676687867795995909754380182265465467451362080522109174024975599676270952829628573934592812580985601445781024761082843826707391204254392386059680397996496928587778274059112066170068935985899781507961575571636589936124576420811553576848896386632012192968387687923921610780526418853148100500090497055169709893054555611723221039020930350963535374896482374207641738893203214705814794501491924627708674113882355460255992335871916814004129411304787062181476523917444297465042709736548404463109396767788161107850951273537932450774071156829281712278799132350992380870359421662040868547094027720761300267030381654334457943138722991648234929516772477587675426349684260795889137888978019023437163712480016269694409867670597271908681176130948616251109723656705954722493146278418372959581112243345717148229754712311915174673623167718542312513867490928621106196930297868577931700608812206567893842657242587868528658224315593060705141085031115560433721956521364000125743636956909882508933134814938390780804143778876475886785587772420238179004828289139001566132929909605790307145036478866384514943825277535471580675377136392159458056832784410034308204269426220191841268936504167485173241625221532837399153725524260109341463771637018481500970855431277644503832932386635523884557228070425744005588072701876922918621412335336972573969863496098088990568674054182711980200841734942194576545907089840342099056275999611457747844409661207249134375164933249107432526009769773289142099306331586176301494024181057999311757523170264176467943710844378109314851691943019410167537059114794945787806071827438459298663821438254846386470703017826550286602026114093729626269827838719058687725471324011061008746314000651650117979989558501506197029289422526849153082878485187302913241003918094040444323007599216082077531490422882526339452167216306559275336274911363774025869049661394836880502599581331280075233587660123763069732409788037536547183248374331982826931624693728158414510349253455772089137645525153551532226385010847671395595962558098715946865414935213283896717390254725577912064383082167488351060069948667710755077706694645114190196006222166649377358610157412653374731168281122956143495695845566082981214119950868078414843152089521604600522593858205853137831065925320043428285769920985355441549539020763338523460062090583107940084347784239047569783064097941441367962523174892633001826871300799419700534390583887105360301547925031334656089224174080164793801520201028373541316387173426474094256482707545315561430979777789990148176028403332365660455411998553584404877114530492952148718051343879859201693910863613324673959553469489333033250619356214534288727277642206154858134726987081036982879944907499309854187559237422239179062192254591528192829534764276511979488672201710043603297738722576665746127581585444230703036649377403529854976, - 16412708880258817400421375467716730431379196534538409855174572158953158290675165358441077722463979135054343254583053871180148272023045347641773114328173391412843526860120164565111544831108121688348163660683627550594022574556132854069376377857115577192872732783981016800731636849084658658250210345924912108531246614549510151986952931268972401366261802916434307005363417272563478751897056481264912944789505625175494478501525997737021568858243356252512475327799877092303538542329510686378609163685970592172253665056582931151095407186345000428176543231344837512157683168221869869800407144463456995124333947841457495483413866857437506231027684045043845436742223741876282248789467804972194818317574704749932737213566746920241629587770173905094688021149099262589414511873403166535924508837998900736517504843586804207432401576377837155523300440670401109852274673160670329160460784749582660057202735476197510686680632349905710510079329043078157303773979517063346981366549741234195767410141529288147135121296819375738905255487020239177466710468395993402602745292748195195526101827607597045138606378127682096513903820302182329893404092093621434943648141821090392685659036295072527493680021241848020898501708925846483789509029031500784425819873845932504071861091100634181993511847767237050634413067300022741177752444067712416598619877722172824486807505715971599921981285201177018467201946488877209269376303780219875110245367249915188801172293594554292262983912943216067338016987302225755055849541493081399432419516487373702675646365957012973256371002314149155784128709532464636076398219867450611947221931382784040177937378993639906174864410684375095104807456904957392156190775667335457406625870849473830798530610437618998644186713778081221921769126003672468120256138740850428703221418111966574419532902218333239587390103569612895412427558949626122207354194702751462383029495581919007250722124770937146317014360174111522019783834589716437812559248323730640703650814669073160147088952940437675656702035345412804275002655989880000380795636079689553732569340523073948179834212959260200428570036822204852532007545111889560753945690579560085928350694369651970113360501640515525273626142037965334593126946840933650940516271620844649435405493068160893422466652508565874774937210948048117849128014079932089846304609586091359960279949388181134571465231184311682426091865279206786679812068286062512133584443670331461313668282956451084452662017104763588979948050102092558272658510983387523954290004308951835666791752327941838335498345687868326837528115780598469479212416465229153681824169848912447071538475721646670668225911925703121507016794956588143750348110004296424912433685244728043973055216599777748108798610807618176384259742162954259328282066611521314869629420659519640919013702014894141444812186656844092815924730162096238306383044166252947373347830245060535384234134536388128081448755950257355051760678170359204504799623181556507716944961242694639033773584904138784627954697346172764524142782031903029792084665164435943819891405515690288363952059857927180268457187763189276987707775212958601157018670520680832589797424382726479564453211253155160421548558044134078964196446156449810210701373280366752931354851458757314048909102959431308202735933721025338726448201172423166436453556745685028876747259121342135681576949173460163590245344099631079687573958480904018639596272105306291603552495621762919796777096059623197924823260415906250834897988283657006025174603315362487806288234322097408841185067226308306801974892248959430390722670115218252737230905894143464220906477985599303962304655058889304429383829560919503755958986184098222305801742310972206519642137107493149132652740950738508162532236344891222643913005762956973060769518257655654054445048240222901747488065765923690970969265855978977995437016016550881389329577670909705785122627261565816332894147402070799105167237340162671001470627433122775143540930182050438882958379315406345432859988806434625002405298947688448087405959703297143243607135783352345795770940596894987839685248483207791374157621838990745547342754133816975069337405886064940737284627818284839838797010575232638147053595507925163639442614714443812541490108108770648051007618628803685044466511085990327469726049936337240776861250795913070842783582818046257790029077457516605489817155742919673715364547259380719518373539935622243706227977066338160769523073946504261814052970684119594110454322000916137485048054824404122387315525136190727871616870099152455035419490236309736634186518744697793526277062756605844550754721834967950343040385140849831696483378710879598756837288621084749363098973846045209014237892264320410099530089176389455852297044287799340733201793492587099436383848887450130682907957987024225186669970797205324481730897133306950715941050534781995917612917146762085456209812636132920637236039029841158204876713959956843675881250528514298731059966172195766589418333432249596464294604920564238459874115860765380626622876801413086657428094823640209041807088823701790101653452535002368643762866365020392221931752995599922789544731279246997825026348783927729330385075430414850409743917735199976424903949972212077906900197718618532118988287885902998403751934372744961202257251344396923929881392810311175286199951905308058522810278362669835859784106653343894883172116668645423152659455129324299781954795827976208250515341194185914405703347755282550095068041650221749373179483711969712839566199214549355990892245063143096736900036729744867444343913935558905638038096833207652024405742742310008782171115304142098800878528056907231057815345139265809693198128186917840259948412853921273975316604283266160572141502731646767291824958436209224550536953940664005842236120715477127466510866318775927823935408717517016453125693815386277903746575824317079246617888694499855070270148756941405121877880463974436736734840835265447967487926818239429976924012780867643050224995883337388314702551209463900988207578411048455030131965492533788718891804367813502426802028349461643521561414067718743952158607627840980750590099757177453128286049953763412639485636674465386445960621451867941680877913967826251247658866963028454155566831102093936183858992455661429733209358185235993172051812325413854361129290823410950981752837677643802742369067042489819251297385146814710647005955482097609977194971103066439769626027934432648233843218662800405358685249955722179392893456327527640386924617522987191872673894574782668004588628695569256585021708015424609318806656798793765656574246529125093755195584072140793725399879022366812565902695733829087565659541191585287051870238373539825763001574404431432637109564617170025033728389029153287582154385468649791447876555449826510918248260234759826845326214845384356727812052142242502127460827035893655622426727381319669633882435357270283595975684376041375878575574307191733804912101201470805469095644132729888243144507981749630365248162474680025083837235197620198843077310544285029888187309172792299274045746371768050558368263054779493618206941437172504069079741265378421490312235917611433913321001152771831271112291940521819563756347945306985533925334658674796853074672116323603899111455954556236135949565362599202481862325714469758409307148631517599527295454307126192937198729423207083409716905753413179856458249232798259052968841488649172865344871213825844479773573268372084536317528762749319762046231346960404080653691478806990825017958529201690374223853969199910308541434844972337060859010956802412274432572136482008160723929917724209924977948514358326255275715208042877471329938647962456302598712690824592565959708793639132954316451588833432343762337321176895914135721625183416407343170169146203969037650746752433567984194676053990440015200905106831763176163772818234235537511235686015883664652565210628942208996579922044975489317189914959102487120267830469883952273614748739180876973974409135198134415411195680004724777977767720970621951261246517889546828544389204808853423121312215018494296217928031690986611767501766489790202113154887226192038427535599502444323781301971579759841000118388380440716625856877568121301902433531989108510575015889959363617030716624217303278452432505515686638495850140325257797471583020271620590151313356341241951467353639673540463253779359662008685784517812508921500079612186065809261919694459023140598692529103608099625465056700232018154082552251794745554343688139986809216585116115734264593933926400, - 1110425229005078871628895912682136202693194292927589507672856576198155700236480219045349312792378153782604326779320079081257721185348026870786183934205200356686537069742970404626619265209896975709966118810774418987519954277894851028940104454253906000377603246897960644065018940495331851858206196938236691027259346479372850887174724294203791614804590491126260092748451841175513171035952763260616457293887879179244479750518129810453133186277052104568148007959646710293916519863875639497135560574588552274755364001176091028126432592519145974532132929101992741906585560725986147689936547390688177083083401961738845179687719993102665518187236558397247805361047980690396075624311670170100015245862669623607133998415600874964406110540059180507430213207715059469240845347214470624069851870003977027145752514551011336645714509235295601971154107354928138185683929281439987113556191987099785877718760223298307472539368907746265224286626546638443534327575819303987318286426762206457425273932514095266845109609231384453188994366394085107228285893598967412090009597877656234874979500869150298606621638088881764407699006301711211640916792922233498813659170640572430961928775065352883589387002096701182915709265057239337516431981312408490661156251844287464881559867420533536417489670116950613204249619815145298124045220271507565823580111515920545150973066904276216072417703294146396087429325310094004172321007003343525174368794304872684962780807344856832766769507847021304704620713067719136079287350917466037661211079019258576890215836438591229207956269910176303259006303628935860257482567477143694258148103098334295766342210078434082043315977913484623971893201786929478468558192538686852672198355210639931710556721693048963669431488616310941367756225176170521940817092152244601222069388279081250271322703428224477129091612598387268581189046767126505762255751173186495918079247673509576524152188879057056453795852287294624082137359153556490094209185274503385976825957075981572545598110415425475585978748039304431577396081943915703037060557150011527436289464162982374928757247481431572213593819856799904245876274842094847713172809928059969230219532417360663218858017854741426549238775588293264255149336050231685593284482261608013338565529882680673209771288368097576086171002365396432205542563174168656880499485337353083415265746678539577919311802326225547618950797861974399647912492520237999814372780489440271471833365665188353754185020324046159793534030960676594459410394106083122470627604168592769002120361687135019130430752272321310730039532123991667134499032251166659481699034391028078702618216553803575904005817986114596986988067916425583271207070266510801753661059936836649790920963851533606009978930799915174807999272615336505491633465363897144853123454796778950394812800685500928454816060037425195728765630336602347565590220945457454094914132503485396991485520845983020843137784452719045300369667889756360853952834922272406924330574039027059634705178757915694901586987793680300984907773290014867146389734950584452466355673905545377173292788915937769361967407505592454035778482852701346223297188005613109621590886689899799977372096001120521458300762484640481739909174547500794570151301787485775756064621504563799818879135964810692885757550596595163440598199753549046556002050959703413618572708112518472825015340276040304247971568134175407483316855377916017643094821938778112820955224779433888540788439471728466372279537878983319113016140289415757968377881353147367215228739485817275034610002680871245986463619335849178554609346724995783786348240587403887585392869220201655271381301595824573623148749070964767061107838870673683712159355992712095286890386085225888350586378966965461093065113798007754891022528473583893970201978345137541060352232226971170614231858353750761923530936404895237300817190819892162889882519027235873318908608771547604393339458841812433237168159014648875331233904428093119452056519812315467221548830065158713937753357984259642691620010072784752438330068264901837436709907677266922924868890843734891529905662148326794654186397209641303199902968435983407153628843151582996203283294497105280744206353915199466728300747989643890500772201504306151519676578827692143199783891935108222415209660176321444216162994457757471693863279781514123226394784307112849785424414213251927734381293435721920264888895388042897922690657368144138799459561758112397991909593770469722552671592515649179780685389480083614561053089070615650041445548989262640072734810217484140756134934152389509231343075893985712017817489564821023026983688959019854460548690424935172013067135786092514855825784034786775510117610718306410843524795053790630041348230385466514083411137543916228082900915246332193680845155745544771576100424452490842337000212143232051447520910810410270695959884029182948426105361092175690340571427119234370866875735319808053278631510021082006776612590622694801363146676042419211351705667006346830596145727255319945475043704770279437567212486703114503306610696658569821125256412878433839609147182041983171588165391035468563227525568929115097376800392254271632572221402823907635861181820818472979641632821365512985241684923749123900079003072483219882278231363238440716310711639113642103511823407003041004554327610653873615821122622927083821241761198963885935019808932094057162462193614703131663568293091225085422942323873060305589994578996334050195029837191136128691644676630137338506515911142392382405771482159607282623895556912230002593814425891776090381057894234724456571065884607652113509041710350186742572417748040847017050122093487349644645802251136181083579691565115899389432728115564655832717086661335867965393737233165521560454474458090144423101671984398018662121741219010185636120760478584826905792339210881174130644306259454541708992085121046514541855632559905440028887528519787257406490828944750214545269225417471147432512436452206363869982925016321415127369123534122508643192026115717680685565678166181249118634459070875628135856270149362544810171755980142185262246674253863537354815703127298113975283469128337641876646021635950464989964105628505977808736072479310720369983411611489073766844971136457432240425683964515050238768309732172976121442920878642468162211398017467793617796984451395314954359455381348806707221290795359341447715982907587241827526235582988079689267426795694183476908362732351361409356319885393218518192194924418975358268373021470059914584266982451840432458362347763767051610045087443686669909638227414823372000601371222372331146188587273639267836474692980622950811944513336113151231263821484339926774114254589640874574148245603883247783144885267217159414507948605165193498845217534642873772906255825496639658234049242557198225828276470667266664060654981315853928200118010615838523853574951834851730964227627605006224179410115228002632610337927032909521101157268716145231293774698808045782510018465772499641126060449033269400842702119680130159686519011443036664532956514026347630396105678550404844230526051372270779239021516732816649711871473349352872402119868787913011043675889336222498897826351597538840505729622610569962930440484104823863616429209968017246592024442240793792786326925845383345878179663881232077191144616677759572764834980427977927060766657494564423951176821119703004010573118808403915759077240875594870998541589564551443383799297908166749029834875747132084059398565821655291251975037003903947708204833935564619141217065931005200609602139318584631196703678940546572721334875175712586582751476152060253604915383768065267724237551580477894784319588650293362094118977102139721165535480675243347852916956369638975449307387067736137627002219170374737195509288536698785489103465952059817278134220770631262623890616974116912487970549285099984863492708662787466002287673730445339015030778026358753090311951383543608305260347963999498018625130618356811918474725592207306841851847483366878757811246714493796236062328587803748968299437336713352445326166259231431777785285759674786534213972529574570471737661091562526427322661835789345356222270162860692075646311433990443451866304429512016088666978263526022902141434915453002302986383960084059665443192319045242439749633933941335312413337806016299610443014944884069744298071032686079407514024426044618574148820671524469611504195367281217553474053062546485888497075963077836743621861046666735145027090229465814239050933296408791802678456256267680508542976, - 70155536191566165574633469143330760367175733276652838569679757003869258771479687273772895341691115963698877568658100274924593240003953441009302833764575700669618646324952351611094138420956939122700372035930372348504320361473325210202986117143197423680351044573082544120598351513526985380983271234177982176460459769100391638297835998231735250229580063663144979846408159006867342591670927625903600369091631268129305110037132722665423474741631252634888291191869125394501398047889631811659676085371222810758306909327982300212269466168994711379885372549245869819380610428656409547300326534745325974452269840028921693169886364809180169803217261344132347357201233343236456171450415456430391417046615559762212192618803184269125398544157177993531353113930609228428174225810583719327619750006639942008209764788199124299316606594521339639893915957288020574032863852510100069707495003027631881788816895450566789749569542318864173401641383601758086897772547661446939033757444110762832631391821540437675451716672267121491705150714295105024500728381093852127680317947710573362649722267025923493956096025242318942336735864215198819602310501554552744368161545934443087636050016865430076958309008109319279520848621064181079790756770245179323173348662055111322010337727472112903573222754110305790515894486638020432866436280466869215208702363672087777857155941722733478514928251945870014825679755769647418796980517009050517799088450798791270018946673906857836365855988060479224438324395806031985604135431022544351167662600315957114842601715057311105091119538483822380858998878851051133314422371239810115739656225617610497201776328982657403520834787124421612581248009607975486482207426958098912299865321779756894884041033654612227019660389194380466673307484899576543297394590210631059161428220100515583880772955931050961731082163378403662935355807494203843384001536863719373840702787906003350487530405167371768365776552420472372667336256466978015353844970419639402728410805001171116911614322526436055603106283171316441833040399773274444542155775732755902016676112440408327733559524128081266340736167117285914210195274086871593277068808366901407254252915889193777747513984034878394939653362376532718006723604228131404140461068165263040663177535659202759447363191527377699209784273790710202503882151827691899771554975334399841954727249261169465578901006890457766560344675099443473489945265294958290922488036577276316805391112788044822420477063751660042932557716711694271806158193023150348613080241150597892270359718818236398456754292404905273519954330756453883334856717868583266523952650912508505714652263402214286993444147002771549660818689569386463894477899698927725068596052383353919445569022667568780674780992729909437500401664105079221000193529404366972426989833977796393516501693601079880273305348012210105441564098094346059104942913338662136049117771625014408755317654565175892707684723795140935271330058673019667105461493510538787036331277151559043150465173181355215973221692756372822197909570433116500835996577000060741612424232854797189016718965257161128598470677184316143588434999573528244798858949734480685296767987576375254081662048644820608964127388355196298968877656713100357351113439697023531460982956313291832491688506987009708773011979535226517886514941047205168613530741715603809886575502016189847737596260934988126432094955562428659885309381260328990276139702379260969471844451267623048022202383428881702408930703076471161935447990106875094274891461005082685082779193288332652833663244262282906843864986414763451349472917027778073798421220746390058026453088857043349075453808501919909205848277407421317233883166683045822983054741987181739540718459450008120762900871154037121827251102740144145129532190565430835197478767973905978335099807436581357517616844152093613512320207639492794292483222316475246854353666040398918286961491414152923695999212644760637707458383479243048737579895191955053529381392936376429852211447223341018177364275543935001652996965797245432202835681163013492341156920606630178518707407873116836291984026169251855861052790018957963692564593202120356203071655366443594384802288569566982958595257981191356650824542329598176769418961286656802270857311803721008112284396950781144892574233787813486816231961671021714275825208017747333401231479207212425196419015690119663542647887842260089339191046356181809503947000283287396987095893503372126873936310028586698585542817175055231517505094159264708966622220226791327908435556466291734279809702139680527144704096186384938465609321837104772131024118133744671151713599797296776356273129956849573467195746899374160927958485687293698359164217173688672224233699086493419746344168992180249694561697990529864248072247115229358711315537463854266166703193989376326667150967588908219968634071767772663743569419019753390084129484692252571229607779362150940542051022465309307183618207558041387879794497523017157753795811034873249648395887625354989943882984710084459000110846271810037257330684328482406060357516156292511204183641087568817546617996053226355676093373105690104994785604727084146251983935545595047441256979347183685787181153982732579520511377398688807090996623366290455686068156161514822629193043656500442877633447139597890259561116543657860204416120875738209250181245291225879620181899673524223911088624282322750052690454300270256428726685498003213126964745477065993990709673074038952622110325466345445165951523744605644060448377884831250092401410021998415257374568113863557642341427194635160967821113961567920933953092309934611785762580368505432621188406326595524608586621791821597825350804245469766898412794309311967475060154959273444720167625971603137234071171036439881135676583903466594101254257020621806028205005090923179176811554479963637036483707353475577605052172123634112902796396594663819220761100899764158274882585959344660910302568020387381944039762545563706885594886167899956511947794371854337652665660696841891720894465389275895208330995815381847557461327321136396911572619635579808243117592045270274284080706036991370740305119899498993330671373501135569314437516724122621265293723835956161419603637072536161214719110339891974408798449737592611742440375458420828608782293142187669480838463641002964442782807004403754779841084906272505319015305412510635725441439623664409306192607375444004787145920912660123638184347418466253141472482422527959945088030282809189262158643055577392168886946168589459272256609386747286624005871539437957814219037599201793765248597667598414170659222127987054061033201891703631763718272727536272541133376468463944884759213588179619351979596024952122494917338160597149142400687341425187284363263278471862068077816205048950841219568499786876350836328513332901730794090394805291327877507088767800042366869414287371914788921604177342739100588036800923972519400370714789367083802929187134502938136514259959448990148664051395927575280202450561572730124525835344612185412799330061813928126379529139388161626923023424441672114488328570356065051605696246446181294367222339335461368563301216158549112237526620167123388280860610459032002149239892629046133741856925255364064926544759617814306724198219320985078762678703185415049380457817076547816040998430748032894346366921907250600038990979548322724505356669567409411345909908736170625301423973767752149222200488745389704647700147544050660028739662487094508141620577691226353938799492209193479710709873100193997638966243427810135652410746317915683878352296517430451553140142552809267061412352945719885062627559431060103668912775436294034707478111055912992154862336506584843223228704961826731320700987807311954298973840529157329357208009566037178665164880016305943566194176616269570229373384799524774609266457411966848532797680127289992688218783478583881916939479008718548024785093345784042452740284849838117661243167962218432460445517254784636683359221346941234630642074750206998482974192940550656047188266162952345461403361426840646941942913865050767752144310940016429223220618095688956658906977644121678952158777334672590583466537305063322405653758752719006777472784237010138226071223797522457495278019623185224715984916357105714075325120915052743949364849194051798965088386461857088986084740360558797869829078478237950602656370500165501962991992017201735676983505956069588658118639762488261960467346338239008328297284024990554301936316997964151220664855017434768211968, - 4120798502867341507117427681757766055895371430381686186281721171840047664148180450418863968012827063026478628540897656672549942433802540349821945216390487838382617018329137882711652908336067098178944106833514852378305951374050514188175818357840668657649672089182767100813791080895189855843644831600875985344533360368751183538946871881148558853113047609085466126228727807602229493985152820089176414318874885377319342459679446322957522630993138781928627608774101710573220959824436627854862911454353803607732179193740606001932360416354013537539197160438905678031495157369610033158644588095702770051877632831345468939108286982388163686130170272524402959456340749972696445061859898760916831572551324095821991033413824605618140732624999862767290951006194151510935009031193987110221739926557066558812806362740037478773843309955781278207304629867764029808170715981171073895525943690067902077806074764204704838424193137713508572819516735743371106199619245745458109328078752037023836484575967004339111795318353341783691138924828939663345463373357002110819258573227728914443994034293646064683164389052535841498889990876102157428305068360455688554483209104149584542887753853412540724533640724927154082089308007990856749424418184804983422136737177579954266987892101002943662329695085592227281095633749967880917469673294516474491625521886750821425202576628381005461761062978935232024123105236106111841805962899206419274413942399161954731995953865920961111182198890220926375085988811127769425109748864135086494648288346778188715069011444500209926394705521276142581201719990702414462551483114442923428105934629298504211341056481862923700756523199199178996742015180639999523453538752408881994642770898397568467554347417471633298867062274567409754262825802995187759066421697833323242353231329496952089852559455916562593945457273535364347009037415666927161360914205055671364985661334306842804908936762845707711262032470874281275620460612743079245734817723727919862237427400264793203805981278820612846658365569551290486316082785594040870941335336330144539526829889783887438974778722644821645601283559556254292380452562104223831198419270612046934880605519876978034490831665343729998841095491581199127683645371828111651776452811884701828469364512152030997093720323439471595104235916510829335993976612866938853527082921479573901416878879961726771490362129709062547713644650527695856208614641142228531256923137508446434413388003501092510502446844314513054197789295225827048216945830429643175437831795725498143623113584937131918763895741878879981875803388344941377071851342411553811917302858359613410778999558076132310802641559424014653024176475851800826215981295814333599046728323875592870695895193518583240060814855298605006111650349716441121764499632792259992381237614881889424982215181343565084370532140210752142671685622959726958129586731424982276948300225271621728601872570715477398489876760904968691996728032826153691693511055027578536130472049360529850468851026904271676279407831010866845198649123041919739664373785791559738217164194908939551139995145179763897260778997920973795173707648569871554792271347941574377516163659842762738950059326256665604531840809411896826203188299141263387489844525700452821442733927703172046611380632881527383282209497003836135616790818395976597482684901826490171917967257183363128451540628607424418727029905270107229148005836903927281978706639224604976739223183370316542991064008457951406581014082068604157720882656891631674671124427905553269093461196548347341280571393670584273421953201887080642412099062431816415423212608739496484141827878190460993791101897747974314186606498496068109196651034445304391448442542198569993244218697983596247818823168515660309954432102361745346666569102220121507680100075122777470590542996817034527479320417465791021073615603403656856622410942742026595193821848648018565167626556325266654228719042832942105693419733941385045703603981843330728390474225958879275811077716834285258706635439398480464952907960286826434408053544111822248018776788573226192777706184220418267342046809349416637175746254486806221732750557746442159857721705871043679174673510857516029922953674626333450339120428275659655048800417733792606851509344483888009584470597395970971037648662293865922105715756138883202136154731745578872622192117296006092278182499762329196010879361392788630966253173190880243054724388549652976695202504816978051266455052886234498568916305477127739946812516681448271615222678656733954292496468639117238008067628323914350955885325541111694645408467834078311771721489421207123780515896676427334294979064092573043978172467414476673957987402059404435809456580777297333654065337013029358140392793398075210411940365427510355503036257681699584144514835884808095468913470678580283605624729731977739312745346825832514337235420469227574843079569449907913018578644210355990559556329812017771481634916042721215145304926531793805684747211723030518145099024425558594552950736465296966147457291842470924366096683955334415126440323163781919998057518372088662478438611825477888665780644266957433966731223942192222217902976785389070195476979505115703833520777598109915523683980803431663337210958388389316971312243621812953558234433273128796439095163609625518288131689543326512856074793577938208432712496710686295945447019724941253760283055473272512677977041168436725133245275892109776539018110998245473260054135952169843353647608375783524265867958130007430627729959253880845787529190643145360993877527905263360632008940009990876698560036699278590347615164529843615856054143692356115990040948601011611417975775776505450701302147178844549438410439717815919253046656753192574372919676776217575658224930249150012231475620404799509311621762566378399588716102755381131082688875259264787132854397603526255041566956025645571828896393929472380011567397842810437828023551989796556845329432148034245191795690641567872225550634722878335693946014130434513415657117700587861447931793015464278248779031503817497351586473138304689014955076281324268456325266559345650765488415312695601723846167911379647102498772941462542330009963554477113162237724325371082232249253482404342773670166499278940403731067605069632999163768427399269679773357921096166436246294117805228525250061031666835635838150310083528902890613553868283351177635325591070753242238314595199060507924570546545657696775581230321095474728503364700574981188098980812206854093221928191405373973434024040810785813889373651220780078644753189167501430037035229799261176755209597057216557256794585536608485077458380379997196417991681657358832132667041419292156133317957449790352750814632033136161609160733829010272981229346712949496683756048064489333528633728527237986518742698181847562454835455281136453776743016373124085193811083680104983051240688899895233822075498577320442915573980665942098517293336018609052375556050327307500856154616194830373971202906293499982494783407388261195854604079107452247252829310304431602586088414148705363926465783723416800900129280207979108831556140814080312415164087962987335091274214681482191551725232274770069765758477227962479494308169662994144187464761894990069430613150130543709414861317915301792844985271044824767628900548223632341586052240099332747610796300529298882090832068042180178449774211214258722689726410063518570634004547358789552165087373628835215702545547395249554201825862582204829849484394609687076255547665609781346523655963813397888452851682236851673833912929678216720138487868531476688491123271496410973719678644871626648259989162684392351278555904699414144153305653867282229530893979930958375742104418829491132746034385261166736542717676200732598237244645298790656806310981039454089796306983230106254457677332420734674979356043557558353699817571874220293740728929008597545545657424188902786584919533395631043238564713926364479620233808287930437494037480914147229785170423717484529878056570384814738459748208874703465284451874442518429569348040926406134862810769481978722103707794570944408182725165434204925393773330862848851093317893332012472101013306340411390371712783334853324219012095124799104670589888243601684108813503141465034846017081959626731155605791136834090604663706533841770276694221111374805086984234515671814197548334027059493325942992995596327729629745724698275850877138170466192195132628826384579268485890099064767193169942609635489364026851328, - 223631183803369680192417710215496964350276241688465205741851238075536091199077476109083709829922257647536155922561083708545129785428586748824085355211043515933780416721346740781645015067838120194027363239961639202832698696613538807825788763738668241823411477060194934814964697297560997125943806827428440285254496518480130431041426298022615930147414703052729399750635587415606564188966234030486035266188099197873149367546838932271543268056525510377167839241526661484571726641176886957916388509185901125455613284373749526778622322004527336316246196981848408154641943107788268494732587688282994939479206391928909698616171438008029672582892989962556121152097470416948955545729585936063573690434966710127748688675674821220228534958041684734981924495904016223701761423663925631980743858218464586904050395412384560235901057389471990679838730819811328024111160287901740140510721864301753658627925281457909488925758890929332312067451624018576669746438020853205266809071115419851890153664389105686544168805511366472817594264140201570849308878047623996720680808000711147390170347382282962299539055931166525315173708986271426028738041613003150756526818891722165476132662044771239655685219710786857428344723193466684204591473000116171922797282177564099712901751708166346417918682231252482572552761192382873209799472183945063227668467591023330144410623592756939058012145110455107527641164172374133307649045120505134717557853273880293662431261357141989293414708216622077141798254512691189594548317472355101850985854569323833326662301723274684727752649794442938419800367103614712500720614060366823743418686632370953024646889000466222810955604233189000034737261113645264910334483208260748175409243072350613406485687686535787397951102701672255447871911062785609802393790048335111040106331289437956349692103883709340583794065048081148610470336141511905805923764852244976240713096451561901585197757940524667974749738909244570991611700344158446183927332936138479071448804714914765293204312900299499423287160253821070002973921630896033465315838228896260487798675733168885314494785527325687325971183789608800200719727426971809514101295316884556697206784211524637198961300602664276848257668271317781466655320596146502459143528604586756298161484223657902210703013169376399401344003002416968918343547428320715708576339102793890542764322982946943816079515321084047690678762589608835522597145492135076674732483860300868263288413048106460926773601477317215213907801889673339798591072293643138510760183888386655252231525552677848642505108143662504504534382603151135095700779032791309811472767017383194892570258191730082292453873123095541747143656961803647412672766245219990468278790391662530049618691591158706944242994653821307288490824208396831773029796240991338483750403234099579746790657781201929727050029334223286801148966948871892457253957787063948041127849271963976709619640890736261545605622602345022363611070381005352052963153853817952058287587214270191102708100601386397051947009266170788524171986763094515107182979588342366527535023320717875423927993192056588310374201334418501495579950568024908643340741141111235032723075269439557170024188145929989552849444135903839969061443638489459807222149846863380785334425914861610956094173853309756923606449710220822004075628642198136775257002530055405743402357438205216157708492327069837188036704575451678753485394442230168198561391115569652094786689944875980778858224208644304900073126044457171251233631478358700088175899676974535661956185271121008453538706239774856468615651513316064946851651174681038394118708066156582399301731755423946711918989727365471473749298632350256460705111638557933324621498864019695125688847407271350083035468506740892319909303035379686865967422705800409489156032144482888249599850262985600282646641817889715375262944272676142477863643488878621165287469272970769335036265526051544772041420783632067624393592343095281062334084756121949535346095013914362389694213529143060748033697449765239673916079127134409460861960404410387897624300230539847148142469231477101438912710912603722857102087883150326102636716004854631761785804854843849756509375506067157309150871462944725922239346465788779520172721111317914199031778413955516634555161250562685709103543560271739539218842563165940622928961923627063447333590279326154063751162040862884863209972696208003306699850015570392218097239093051385782239879301894922507193436086999660357535672034072806848431609858201944846356882526511786035777026675551395520843145101392080541340403689026355622896073423334447602063388551747668756659979735334413709091163483548519848557874836180362052782533933107166378365822169710844099996831526589550188072211528684765997301703788017055140556490175303706944854126814255030514695506691597273579255329898609885182946044373514570440597338161028354636153277859121422369969080327911222653109759307835281306701149419795733786732296248386922745504129784105791637277229040649291078874977513900695628490460971675441505280361122205921282800206727783374572789856779660503847292693615946993492751600859633413900048786831480850117169345643577444649886915734726165410304269909419015878287794668943002323863195959073689038609314227936241388423979792692492749985395021841954443680971632003853495769452425756132094567415621513813580664346808894563863442375562138413820600387132163516650594705454138950634854141230382860094942141719789167777348235162728378399902144542999330193761084877183768687448268725963010775347667732039074324540722019720086640463527129602785362951233403201060058458734577844084550646217679036398528608747956624719744787696233434083414668723580699746104289716464340853867301003730076189340098196250399531591978623611796390135888919862979036219502278249015602979959585664633754958691166911794570822340860899401505936084549648960736030306765065348789382808877310481611905789779388652438874967340264082587906896149498541547570387545419830495320623373436092109421040648118830855776428649885961991187766935332731012437473328522972955669720916935728370368911586830587414465413785290394694318598083406616376578131073223149582516370941756201909725467550978986181309578063203021175621006782639553402427028522020022024216822308425105986764264058312045467692502480436806039420894436647183902804645057488266245174514322914116648007049131566972057836058780067968864119606164148848371092284102770395484241944686257083769149518316661719529016402886155678815537616760056539005713414206862491406852030897631508214777728679164549688926138852691609827170991493797095841982842066345678643284483378375129185133351296730547359253792183338877246080790039281199685260989994381485738284901201927451444743162158222852413180606103173659970451003346431019484494973979769123253974181213805073736420389383921424943145522906503859768518977801850683338910985849357113430276823160312128611176665169012757066647512326246981090211242446307298250388198608200334276714521584334594848063658759401152196214401308344848352897128223697561044622152897371362268426491990562516791133030050833668982495114286744626597767878871395099549165595223377456834359719288999022250666715802253231328939340657997806972460079423945154756078296116608605194552865277255479950762652763502541959774638948510418330364265887533211466011883823401619348523742162947939817710755004463230488101924496034354866646510397748731538118494833913750689098400401322110337829508863930794364351831494606991880248591139054035948269865137601311239728933303342976069204061306879801963102147197964565058678354512905714749592941912846311075859013788760460774551786451736687155885694388632541661964443295174591705915966252219477313029525746234143336438776830664873051450114041122524742037158366386515325393615314497337760986539762224616802513077859203560655054519263668270139804871178250328052999189878824373165518236864871184325557065889092908745799685054820549396430368806318985972972994580649891376231778919201668805778272730639221999983572505887894940891853741049637069031915772659862754690473082227478895954779775731993515028603792730241233197167814429875351373784870067205789467038267575048523330901405231906978152572408947107461648264570108368504972333556700442208315701921163500010077270586290531512967846671578587001483964947854095483854075998783537613727068127044971643532207342233408928112358952271872, - 11108699848739806330260037554090071408039896311797636670520303078814204751236410618056651545291676249914066544498205409874749070968713170055462208043908854322475964337349821451643916085227334112154269792408711665075824752108289428186589767539396369232285575286227753910224664788006602983996728889578644912118372304249879424120175367913258092592758793076013531268016378522805980397642531092790922897386583559500978234981754618214801613118226967168596138265381916872256146901054584675071036503978726661420752157193593731925837525100485813260653632631550731250319317646927512626909859474820488036147536719897991452243205081688594687088605897058144654399838558368962111274278333546808382711931585308932155019160187388165562729471181510376506995584135897099184677653797801349464815733842571365258911232393103233145883093438033370359641599206840963937641191219437949807152503722219266409478760029915653201248459679037745355357998947628387793646071584824761336541202136013712808820734310015176456683014487433210702659365990640173487112327260763498630303704155810466251308447933242783097935279254856467325234815050294812284447452805838913541681356886960366338594316048984333876317005079267034228568228358449953845065101547120798171471597416588311089221322033866364352476050838746145741463002524974763677363641461364450463405972384484091737760051042845828685283318905374550275434727379210039167423970338651481034234513595961481131750221783533101128375006236095087082004011452581157095658318117811697796776961700464455828335821915892485908794745022645034554772752317331797111096623623328361533385822573575405631798158819964814678606433389168087895739928494579039948357043603252307146927234058185668408945023574884996933044432352496558655482396319233799943662868251990816639570500759931593868135524065254888641330622352600639419147473285145617905554936010092696586810988023224458073254326375627453699757230895876276865788827533139807078376893724260790416742917124943260065706951277851047360534894843264767075340788196366966116738229896346101265448518399638767239253114359297845201556367941982500579950959366942006436103415085232225496836843572567190063496439497488848945474193841355913527814860508968412946187503918714953717188597553169524709685835597462373548495921053248545951512885105286509237149144063177480723753620825028717014737824074234047008970057685533309631833309432167829562417000082031990099466010430433175229392575609494562694198953752281508127294063401805255529266294269522785745121845752026998136911411177207925861304460376906847070918548263027397608899458382941742806669652151514963889375501550325806388642309087758385650373823809732817476361452190782369426243851978065749934371989258359688400064845934135052165369977247188886981837077481398818816626571406196545022140461090293862534682459987583446210289283586531425131760308766230822401622575598193373849901656607218429475980559371171405486472735425019254737354288070236673751964358568720006649205766362932895534329065817528376926888312229190929063881576757939807108361237609385744132512680711657766008827550807697009427842771113796228926257201465441093502698251461515323958449158354185428015541604300621333495001662736442742625249522807669781943104780603234893865340832707702173747595202756748287923326743135154514221034265936513934105738172543316531911811822374566265639719068089477081086353732960724150960408975661619445208921010516678126588513865288754206999383187239036594619750118906425072743421963270825883201617455174589537298178721651173517986644609254254245333835994734349458458373616961920351955500488121984929777006337180570173699759089516744208645020880897522978832932129044838127934506407794396031404077186350646195628139112061051080267515187784006230597830499003512939950583113622963689280389194249134617398722736389642993522070863545126988553272826200395396337768447426990624649221591773661896789510587242278293589913023728051287478872220424580173450998697219997561928125618136787771160991064013832011066932591040674448391515804900161893852713342474117922875296325148038017061249073528069444128747152048601010011523960451153277044196186090222494303977791378107689503803311536067003877201483604087763662544520446442062285914059956067018468117519169546879898906937905194542405466300627319200015742224252075096218493967274281915146602671357421640317555237860414431310653655903427770885043321353732048349211051566451513230819398013755162932682269727706097862312577954662661483346482984386782302208623798279728650715750704631312182444164571975288151387536016241574945252447971978750475629348948166455519589839772768990286187101075974991912371816747576455494052221984155340077939197558855233110383397904872919948855892304657801914008485192523688517464020668768006055043376018041768944804852741853225007419322141953045805157641837178298570238565373052340859713889626159549440891793241539703008456981748672261861146971184023779766319776975878006839318347836941428141789710393934480460370266277134133869978947854560169138030593443295148158047651717669953151692953398540586557673944228404137080655726499580518862758822002894414836810961404771715753409501581422545809059140038669550901894443441430958995896191837283951123024790519812103011710332233417071746573116284061403613746366799119098801846577072119271949470957732217475059304209528101898970158096078024381982425062697557374369287428307736491401954094677133007007241558200714582179236704875640638669347591224455746914311589463612419831764418083555481807673803396412540722874291836839465173578883081245580297623059715134666074616530707218962836123804874620931781677217738568957564438522043325775793215155926103956799462335167503482080266318164496569312127815666473362906087601791790868814951025508057656228393823960086585037262708504713715175192819470700164734035797118655875283445920225520954871497584524789345747266984157358207627230509061089037129164278788145966761793820511141872458630809766347466851700215197536059788803556447255993574179588798821103514615837568037582968327637885820414095206061528397639258619239475157489474075425161091850428444643125541249338161308880835300033450925505722568449568235714926692322330997756059120431946530500356953418928094981498256719384573838619322286316733892595519144763466810052516849667518862254337850498311880959293779056866768737933994916201557039672271807876171793719191573694897354916220149315778066378772916460274230484466294044981311854893047401683941482573554367951164914514820684390397181384353957488298556418888076769890857285907857788071002760820584140244329037011301905863684634908048173150731669357062257945812075660151566850949946253991143199488463699905667648185245447310417339980447127413346795117050115405683750716965088556020295982910522272260799718974759029488018471123540918605038360549685849420332914426169611381781809704171580690687351855906277288651932981813831734523720371836749166840199778654341619590051938318821674679227121817191148009788423879737472262829520649087101965853353253768850240882481872514955079984157893799902728009446393611301630669524770839458311761643851932265421581519330681822697553413737064040753611353014640298367921630741764861445510215486601216785982519514742891012088805399715929270317261193680920055959201091853341616800431966791375281402820874345679207328189346013362892696340129022998732210603411191494381980105071095594319203304356402613507597198438614082769024979131238939367566870211396571036144341886867481364965631200050516697080483170147944636482042624042222491947778506033654039957682441155024406052664027022802270420665026827771935945203510967063351124994082552418746676679923170698174088678995389406919301697864007062002713448356675687001611312010186021479678271051837964237760505661852452113668765900381619467486247588968256907424260999227229211782746634545996270175678117680706963954567885120038973775864213001707567964795529187643469895037969888153937201214434009472741807919193920853480421637777529189493772990377916854722421933293352152855913149050119181285563413157319126955502076428823065135082112439212206846812443114081620946049407120133674758026894767311144028685396142058934926516012707230531853113796274972392968605050756117691596205643099308927607397004396624396075873795189180080445605281792, - 497573705312510887153816580594422047950264856040679525580246422332182802726416315770935431618154301405597087344581440729767914468052158798359450929880708663218241508851315829820404584128403050921812408694755389788566074809483676936934909043068754996466639660722177576740132816026029418307880789749567610338504723917004658801504174852790309938463697913699076009038774567518331188677806680979338600996494984408315349238501363512128057317500136295141312412623070855565316102542186899176526913758579492256581103939905781932474597461907217912967769838102105548662483302177093820809906825534493017105350024921052757924531425764053589114566742175150999160865530427890252555722484747143536087561823115790191390934799512779580901105213081381457787207466401658412005534256283247255852235729580285675185062973795856324809075150119843008626636078222347082704186728384395474920393608127818454873447507471661895112935422388453350041648764268845720313695417581278827376377126471183608990044881899327505648424996619095004927939723380338591359451160112305428018580307825240732833232758823668648512994529212249226198462126400318051959863688336611343022667379613064574174972187307253000422243362426356952375033030603555066644140249018184062609518926536742107798908005303954981278604199166461826458699098660270729872086813724884782549019988115151963557782266682737163176598481154229541012001488557692814624502983672389360122453755338582805251466276834230510970031882708447809541988296342919139175905735667771183538614883352903963519417364002172204361961672649335623200752301232089020374212678172129801681913802165755412448302839961436981177772081496777137299124712340050987274236543602303611433752898266582905362955215959816586608949964024201141326718166738627175032337457460661321146805745185642332581892089050305147577395946399188130742897610808190495468402795300203616245211294411677296954071371493051426017764866815695102062075227417209166685368475954444662040920366994140148913356829550282912093479397379634075360655181582648942720154222141797773231708716766368002460292699948745258387145101415245274623660551537196839971069949865477680390000890200574422287789136727860931940655974289739341613071682703281432996335191332701056094433798048341722609275129128111013822927667100195602708464668193494768154067543417289249320200848688267938089000497711125592011540076802291329922657091765114082409750273357835734660620015255892441705857084189128429308334711935303117305657607896971984196998259175251217077535212908407458373555043517657141397732907125403500891552531103724251609856917575735727774519436676540471143195980397012666307188450549056430384242428201266404298854377957017700598025549004815635619790414971869034303530617791361403617196912448268920306560189442208512965570153635878886697748667143934312142745682441074597009062059629864843691125488366569466099737406211515997600588941900217777233991601562486584385363006904052928673524793106458120902671240973815780462243096429287612220806442764507807439331431253160901398604620305970024566391554072312182214463245403983847726498169868125731905900345663858510691873693287618361422977404425459147834651010568150628682584335860403491047646145068314582476776030384443725312269647773582900934539716964747527764157717676305424756330957810539135305234901033216215984796803788803141879092089540024745100987604570322578929648313372234115515082427417866439489757812417374088122300805545058019742180160806940391795479285569610688918384763119956069571052213211418482375470585632045444594237972793308372054980980801510178737832538300930371282327609124378110187030158364313471688218916595389149464319445378868870337836131172812077154516781233385907518497986333995674386525124709162295954876848656325559010176961482828897115129978397602954481163507527555996470231879618762801835528680666142659710077635170772149553132097714330678442038484289886619420747757830997213432889962264424562510754609030481988234044426519864100542700491826299326854004438409035948134392164067716264701873599719136776650561749783188926294179833741025367447772694784761882572530978802808793542171703436835751696367178252681610074674461696155188449992931636094124113602461608202208573030927255866616852428214675895896095803307384652827853663271041957698906161268937892356440401110223159775668798410277731597634641834970939380540104019303576863432536856354070854103686452781135957106737704472617678767478408632057172820195771262618330636940011757616284073843035281483298673229086752404743274321969037924876848196992261926125814769032254023568320875214728891751064299009620209804179031332888955429630912233054991284093618378362752192582864685340632515580592820685061515156167190179276263032598493460788554896261948292488835487357795108605978552202654746798769011711692066234333607328200362427618947490201855036256479983637935028816312696179349270857449647095338656774207087208902862457705840627047915780954988322283214385006670143535423572704318147593216279574914434868097189388766117699723216034225092333953403123939465147024836665058038237167812083879467872445853533673936324383429139766074315965552059771833390958927838052678879222838279980737980860493892366496019514199011441296433624497328392389338162329503031186435169165652490025693481294798368766836130768268962429099782741798887534000321335448370084289699975259541267614130663423406285629247125058718490381050029429705960178886662725008803176120600991453915265800638397280001206795040044649798428018050951617520856616169112132710793138194159472727204550996573033895275462388252821219238938978499105250496223369193747269554246772790792716978448419442803995842860553711548035460772998468845846878730186621084556082940266219929415320066277488737319236155990093327001501248774188218231160473583509191097096966303367765565333143659033829762066142127045624538170807228472489264731361900459911500618000419494297196080950467166967444507958984004983416495801316372524972998063658757499036473943162418459489338391821539984404242678567915775308234157279642166799325118439162726536158280779589897773488713487057074570943999616516524893644384005471441098405162842559028852679508071719563901502311804314927578202404440693157656779411108188960089836130238236153340784219429845021291723937846218099113741702788751948323166542660257195809761808890798004428064184523354719779207695030039177161754152662700987396045452413716387797158067607568670521220756027698243679248463712734568460115767791560852341096083375706043975408624660095282130705336851222431620107929887208446493576443444537500876980523691527926463598482230036317904438480187395637459303046204924545736719745318412631987378599083974616870073235633450827777489884593036808654902897570267437934446126700899707352380649166389766994349174933352241620368795228343485945582416302862087429826798852343399742483807441591702853037008822462089948792645548493845323295373027457803983931948193880044371520154860342970378092634163078445381711030422065213726445325598245024190131227240982188238919930134325364053683101393139311995391070606069482521161832912923080791769386750311747519700164084612155748273784462268041230069305819670187313729085429349189775759727163029719426191862499501524918118549906221317101208494464983601805883746096592401705291892890459113127732190459710004415973681188735988654225661686972970422947113432588224391603818702689279388115125049478683063863772790904759696150698504917174670542808597799714822569036332190898601798376587066128542180802238922043381987790819463416384596288905325705946915104630629505678301364125334321706183613382240304336070172951034294428132714459272678159094403032441827227515761557678650654559797207496537821327946781823916216863294176179339634670266858593717059509293408493033079323585328002630562823696121281171283054623533724510473129453400095204319811818017679062734694769985254027125378676603769332993613315552096649209080663619523797567428037292676895368637922652462489548596191686900117311182722311848000198875485718276998598668026490652409977600313905785855624649672456793871140317543350393719452479130700545684141340529586041933442005189676337276312224608288926629801221140596300034226995593718350433568881029690339189326446357047318495884614389586525650157568, - 19560392134709005301589569496737092879009063971091652048879644686698468848197660011555690668438954988800877594846288354145503562890046594302132048582625834958446837381122267067294026024724824644453030227328067818712452479247633872102723691597196272595751715575961057983756349661551024522210902641334880514607194269015335983449144281533329833353918079585553292462571353671769948243984472299131973295527235866674876258990355540632082186913870397214668179179434193953979742083689440676984602934991073860482049871370199048486147667802670338566679223466805279813023898401250378858913461760343887111039106617243232475666394980916843210174893025865439976318772942026069933729374258849252876892472680486867225906273068711462878194089323843812044417202655375317275703726984552370970128151022154373503534302688779770643051475248962142710803668989744284442512465974031465631845082863115012503859898639264680109101556546239282483151220916500281414268253209961504786873554620962465467476610027524492831161553287563700370173442918271010253946007609206407810925072659725070041144413167254226082028002737810063128305565762581035303414093106716152915069434289203607955377351272685329334484904812701018608315190308261817623209155821167886044406116958538016978336768379954922603405092510289132589462256056584526067113940195631162837229041343258982241719498324559589668801994124838830928844847689244883802655744705790816519281813926857833797653173648965892373653823235817863144646981714355779620485890728997434757777082510200466454632372939816259700123503832432302011531388951257616167017220584777558866146314491546576685931141011878909610123960743132655254021716076146252080998963989548303649017595981333984069243146343652405185829805238649652450638573698753664078521987421129267311621721218730443045270742425883105286370319608605720713987892354877040284558290970623478614167732142747168061469614634369699023510659109302643743444028182033360526639318532240346555432403810059103618900593075862900767045803248613084518266331358027750672073909084083073265827100498507381615514873322830914056561308783361282206209060790402224403249546651231312664171453523526232437391984522753673903295554940509831607878188407974935689594690714313565171408831644522975735225732205683378532162401170059145720513359469032310946313688238890746610369876986103590170294271626816340920666265345774032984344043582692474862141120611665557959503983662827440988458554215423933417622180398053922631792232367589193298160736337179600502173935122056789724827413517053428948715201011790957361817363080368418823469846985248835669279895182108470144723311904818447941955237348300045426113810385482275900340430751372213199772575264817971514364885644155197263520445054279521845049206723093587078082452799154333120579720235096597533732480928622773614272145298556477912142384855371166702035409974509337055969869379721629816380990893706032524254276409286212461188234313890009113781543245436868013686696901347354162166844273974893263427889218045013558084939982497919912326844971079616206173084188684946767660798534080461477496674748291470197626317360262324999502959942831511604773951172422800927203462304581978829321499791748670344722857270141181837644563244608584614343506359843118168039705803622165844297089384554349154339760055398057072628078765906840780903133564245001162550195955386930099672251752852324449661374074321752204596815739276668159691098880215135595142687240706275568552024095519061239712180293739036147962111320995075182321195568784314256928844681712220489570161586921673062415023524084093889745334704845876118629638550952103730884281704727227003296767770123327396955746409141275451187168251755628533651021729368979794149445028093172139848260775459118985897042268719364382640201370699364635067784007714744411635869654532826593704058944324031257034417211557762771626815397165091091180814540851725464478279700953556171427673271440229401419243132802783161858944147764830605232393400347176201397481618905527207442015683067856307109097843475445967940540443011820304164693774479540448551500620859028603642058537912506770471066177528202057175206912179718006369589048479894119384618482746176035891545121680413899970221356336519316060586420656558626245873529128131562371169709438543289232096178917083924980897104171139255679025716991327449655373141856487716496622248040926595191426146089920416166982633151777555377141644846527744763551561085041925547575983118193945652657995051707393289872483886744360255757659133861748502842940434182967979439400462160574791009490979674347102638238524182843809632504428538149640739218466262299264487082013618919125913272310551067772366931375412318021307647837330556679014742759014523004516483164468042351370643371386417768578563254710913673959826278313786810218880767764393863128573714170440707887160220075928348516562362893849717436837093188433787836346158079444072806031670314410779502574656004765235912536435601353062456606860829860834645895555879909692809066613565761513790761242248743259957679912073743809966168135233489731818023825340754458042121121600382667095201713522204911819355431953084371254469949084624013746757534662222596558387895863700176795886616968709930495148469325287776113625202263810643850874221310700274283287142991950478032887261351321615953691392396504184705261246442493074019973771183335618118374201881447683189034208239948737523449258765316735800124949891607261065671324258422440725374544994186695605326270068482260546910564358085637227410428776130530810420542112082421981545255602876092144968489609994009652066020333822458570122860004902656104223677542028822075746519912100985035496351395978894395424436789225201396873915167967355896135717667991862184730707963623460831495990875623822220328700602536013524283676946187025101477822126490887192502809832433545110087212950783391880210891556731813453790158109212182240269845514951225892398511382043822692616824769512320165275269835639508161823683499014465889076744415083000795036054551236622347283625735324447146887660977212994220884500358532096342353274279072928711009166471291591968194157620191231305810074607881986311881408055501646409839665247979436222447715196745378133352703843300119155575845075981610507868185868003410900973035737613033357780940106535206285106406815985359748478263946759424948129597570201986216983438703136424237649585906643843126342090918884607826578134609062024252570564826716121727319782871283055518637980503433575063595675406118178683636001237557050334397304760626572257838433765142583354991723667841713118949519976614823106718846848769643603435850549538678383285369035699413441644156703267403165388330577983881388128438870100211334406325690895037212714373365747729833835676971259289220030211661963035301156347919125630254128893490580272222340656872322876711477796163286016311616202662774217055522264470898196160939207136313195553325049824817971529372222134128367444220048423236451514161379853762429442913586507881922727447337636948067461112322555820480098166543825227962923501961848943381688728372462232106501833324703489417004156250802077131275099382901581298438407089643157694722042591795812898760755142806837045587095632183390693527156783346491769777871942216207970423511231610562759733384608673355032566603286532578683390816196102825391615376046277918954287892957685475713566580382298702480535171415520268434030401235826121283708973042078817492305792988285971070920538718766142753058503702050745006765690195319306919521263028905708629335791127784725040722654842526882859691163706318672525731396695532168853774242724714830568071517786214681612314301694638447225989931346761813656540368508439827797744935610274793832920553880780571719031313059609860993373012886361903006017876453567448334828603906690222746260977796393907546296472565919253838825496182745866899757199707461181160945764946846106960434767466240570436804679414035126847559641856037755940993272401470070794091098581075926503987703461718994350374151398641496517592427375941773696523994607249171637215403148759781064213398868815255179035921292260990625814725826655947917155111275213724047114837252345839802419380871436033155067251897714711823123743673307716408063100808503528047268734258329415417047518782812638209836071977484288, - 636430695240301612207244505101204289218405118617861379532547793669854795739401620661224314962826954368321962821682756880582985731309771436200380415628368530176767654226784520869967458531421646115075735287417773842350954195038608057765532751990605216230127144160297666701473883077479725329779140719922233757904954056145590904156541179879309018451789662064723374665540991183941069441484198999586286165045362733148838902133842537217713741226507088467916397079112833158563883719788684357294179693669140888680430694612338944985123412598905326464657734366251710262058386310975524022562861443806879634726483624646713250281479742038398589688671300511833051673532129041530831149686080685250258579132271952815685909379381869557680444776307926625306604370543553453421410715329568650430791124069376341231904387462081292874896718740289947214114125802905974385261880851161652229586944883117302351573450739898387444077262427906378273954627436131088325304533825942136786718443622827666701085254047311274210489364519211707340781016701535789546839992592169727041049403744167338366674949515568601538278364507342895089964302872182594068866281250807862904252690958335734937948164780156604302880584595732891260054347277496438100927989524327804346335744799653846111572808262782869206256998420818960752459115067516011115737550136935979988556827440782982271615458085287688795300636773095758834419567131876322673235825476989427801042274669358522202710273204944272215440867697736203562750723293365292295155223652936195654140644224159540556579084037794260843791774543492322000527626395519059591579683459311771750871160120508167582350177041446080133563100156054223671060940493305077713695808887482778736147603237448591418489910068779516198152672255911299935890878633177378078991359140165189418007518523461222355605817198059265219532992705226200002741336733571290694255944400691751027789606079058128990570452872234213825372559501794655716898749665826487203183375444136776397780348161534127782824402484802247594202874402666638753269923743738310174664756963400655657474766161663442477874597735124359682912635373789026994486872824652618067651872975169532131193792701078319365305331506272098172071616517118832338698971408619238337263266855953203305917256925443856879787974974120210520424581612287973808606823094692488008073323003122664042701363270493620860073123578226030466504265739216075187232666692565768227242007854640779928292439037524179857690199211944442284661155260726572064902399501717937857449735027032043654313039842328244682094025732873256935111005500001496161533669710830518754080259405969292976179018305146850020371392546552342484554375443046752278214008152802815146155535075460029519852479863889051092449952666681189387099931048239348622643979686414713478001273443166700050381030266214841187777272816214299063929207369673080305205990589173641777321599606176350927702309101583878597482453589118104635991255861022984451977233619021076794810791701315275313320372320629772605251753096575608168515939875321031161814992591447875118452428722449015121497691294525740732139586317710454889323647048475823481958819341248075751534279570154829264418591346027547217411182420651621728876830529709026831325282852160618546409572121887957296401434293380840653657139783801308296983668107419028544106756879139323623641078723200323132080197907799804188737673152688382585771034428662514144137797627198436057501872022583796417314873104456303511183914821072218438650607994123604942006500810734759716432739214618070530743230733378161797651376321471810347525090248547348961636200004785351469477702604590827297694915019137154136571325466437010929141815654625076306007366840737752324264139939391830412359680011741437125119899741244661141223549810731119792151045880619812472746941938037162151810283717674423839555268591424828300506847485459695008590432707006795436672958319661477608236729805399125485292503071989364622731376948234968489128767966095125130274817801212166049778628136659796804702152157241991326137655881194357145296258968054639744694646619693855373187449683459354369709755243775104707272253382437587841392157001181997708638940542648490870969845874371348444930814351195467488424769552511211760457411698538106405512369543150235557924693065781033936116014683893965036725545099971296199081592954980946785521094536639670508776278089040747930213445339817313594783933589484362644717819846497011106969008808351054512314849967822477223196402195600505529983979101106897960055746562790523854859697475963019036126243982030136794001809284431199786515002744979050802548134633652293048226628732697242654770746256320676303446115592355466363068077595895059701932300865045801038182922426604714192110766220166598259860597454130232911757721718855572589148749229928147196121846468353947113002655772708034804025153426920749034379663520399788312305462133255392405741480847847367584777904469164960109851328279102602655769990406382522537908763261040328048955811972309321047948603368158277105406416137000971305425322472065253358855039154155184036312640146251160767167708476489620899093055367631300229386153564667438201048876941530085433861921021445997249621052807235560579617945660851807803043444973989478874066444704603925480263091524798158175111651911517319109691825837406021359582751759378316595145747081989305236466108434686657723768717893082339631675596456670466494031052411858493677593154383547393561550386730664657819932431467629830249332193580862925332536330898643616549051582520267414218658231020229320729096613740335463729054277111834775243098822857237480202875883437765276976552363208896663245453731018878333234817143563774970416651314316818438795506012297980845997823408292611059910665382775287828207597176820467522840185200700692635299963178292382912749461175422578822988027502341328509866301216024567599952765011237936989029827953717047018563920195033875007476408981743653761258856996496336411841080883706547480102276022121028595722040601520707326981499823349711480685787196209342861355621598712634176209067104134646626219558566678749494890743393626736671928146833818361415831175152561889978380697528552346803710007935255985261473870717035195675368059904259896926756104741470455912762863800544181058735036546092127309914270049668452572554858575134042700558265026621286283271761361649346455087126617499094941160407739010749564123875887371606128350633004205447565707927836424049066559923167816369154231360726157285302748486423635870812037631910919554301371885354160001463172033422724420352081861742281624829974014322991724076092192302179375354974888560317779630178003552573362248067359157599765915387687106638158092746670276434006928726015847871096737171181166444421166777372806214433075055571838502354597158577141200494144757098884826325136784141580672889105161579437045144602198465900965663941047324019811030091272576765397380715508448330465641676997014559574135740351630039538414027906033484113342375124825934667932534616650322632824780801587507470890391368761939039679559444880988528768538643025177016556523685772278714269822588032701931576612990421602685129057835761621021074556741013725273284568290357360777396916395520299660452564210416460502103655778040161532934763256207843227503301051287700985221967221875136491257987790853345958007412426170905207043195993274198055308019362632593890398322733649952670082103838829989553941276545908114156639491595318661505436067924537075376962212402399337523360433939082341227632085182333745362357044917549325197559422452960594900102342551410175897378017110483498312556038822733674987761768413452523152864264242704451165618629184458206041599358423400404165777446297713455158324063311867316740955367641412881121142700808445673791542679408664915379474554543875844077483357635403029765384853128419195791420719593391539987775843566511779886941722408321851769551134045234286059157817385434340670923672238901371803533609277816998094581380305722148475465157366974060613069829566091831224859710532535734139491280127304488933321982797125105201197665958059695542404448704893149256106770284962215335330346186362760137761559588749729197848752290744444858442402212462073202791584411806250208568163508981938352686302713542013801083647167388233019304778961780736, - 14255294064752911770911102670956860387641781383274182909246132174339836914633857568581332529491419406054350636498733679623661917231392360025592242708375732613428203219886366795169384880773833347696910589876197507037875031754511848402935678517510784699071605045341529659561821766716879030057385785708771021092469199049701776427965308295817062489647841977648623785519103306445523237053266381809671373425458487307175036130340084184741226681975546467855583332929693671085903663215328267414574656519836645056437260446973781265706671026348834477251991149929485284936838726844538917161959372433311381360616759185816181072909387863226677326377692279030490823305939502027809277371435879796103768184753813756255793493523815404707841766007544315780442221548020316644053583922342370261789224449741830296512085649949513934837720323528794308427838108092278871899215972566157322767640937060443062404527072429017228635535963231920006958462713141584576771980664468178791015943090542200143877225324026411983599393348937184009071474029138336612779530808156125114909837209948413691132951074744394978643192189649441925272513978019002386388860096360346088789241881897284889578641806494311639594534496332528528672593406977067103285045928414194703904804394442229235401371577761149268936277104998511939680943597765547353476430444766139573949969122447759025568683396147506688554755908181962965994950178173786696223300547189164626075676057743994064273203926880516196137140604600065277107521593793217966010466940115189785241404196875814080215865064284067089140476414345060020543113739514393648413635500336341514542903620473739422023645981427289245208157502663702992266022715410655893480428349154722758159123085700633764626758531400389303653582078538306163859742603375473727471896131713799587453624010058089689238632398611253071008206472235985216389617865608969710683260287134172733124586255319915101866902934316914999118699052685213847559940472338154308159915357430679937321610852759573473647496786214855793923864994663604952419015633894543569190998514710063147432420710279100267961123030059299093442011105968067186618318824783511502983081236824191087382900314368012957070491386484535561803953782174803870723068493277996772921849982355762640655507367399482705993117758606208925856102001859624159823031066033325742266026269370466517397646914749681434200508215601181269335945868791112008957381174316865563328385184640631165958724002133383612151888318347137436462914775759205081660834740379580540948718411479548990374882318774722061918622210321587764501115494541664160251636655284232588075111380822126382068519208804147381142851995828624355301837878419072593178523633979241058659416490723203072697802989746896347909614221698623415822886054507207171789141757984129918399478866417723495407266895503740893218609538026693527530936271892688916901278075122455493333473793240913455983253883437195785512869738578200659878563549718734323762201973230269028091478708552268455654540656077401351648961370109201817811314381655247320501254276641525638733455771748918571901249928486024420223994528014776702417623673636943474686842273669409261553486620405434900257713526362183369141653130180910916318031784131296883396879387043372725103193358105154825054464947939686259209067921792479112277186490299953088015255713683988868097028094593311331352543248963321426796755931864450939358694316740408647815312352396683600971197081616781838562356786804865342307637726097676256844414625031639807254318004799127806684668988055018337485916439818505191919897070120396700550571852290403852982204779618430378582584338796984820388068252875953577822343430557731102511626989253742609758705236984582333841789625062554831095710839984654032374581925126728649480309042018448736605119569089132663172891861073893764360720565175582345836883802086758484639238644675677779765297372314640176178299626794332622811202924153685945784813562545884142930934021298611863334026893405224616692153094030378680627630563748078901337524254391428588700411731118592197509167761096978992851020950465986412375254601090270903802542765202354845029140583362270468469524523065345107767761468005133643547514907530927951040032689549832512611460264251013514570058522868248561593305859846073570709155741587794073533866929962821615591911463302801130555096560819398272007037024839863679445461894075883939393603577289155645303526490659768473473145547150742540443593162156758964182537245773656208701069437615556255896521427457434455286283214104608303481304885701960527064529294857647314506072947598954375456530269393987112256669277620503914262454013043038928312988819352329337889586289198739443139663001326197432017023558526829617164466953413997601847089188547818905233376061901040525526644391164313362456043982150349487752003877390684533074803610492846797770510066236044291052155609830898311169685919937276571244461719948921899381819552538494097742799548563076445999970080360491280271380613099367914487215153438223726406291734370859593463015872730852453777310349423644375884693621415973672738264071911897931097493959065395239667841325186848461984267290539448110701074568221376474008803716366696668570503625240445516203278734933935176360277867491694689473815541267403981972368646889290699359912435631489192631177836291043697331565598269633711929600573051587516768497131898954627302095165644785767289905466069421864101938501290292471302669156451324035317359222850916386398484292989515752709088369399800035962701175611602405350211846959037181792192249297356943773265197048840261854485154417266057169102527431266354017988864236262034609815357498230968234973561815394090107220304208339789362301672012897740321676606440829637949271096011061336540195325066742436295913413579986919065728259279891771302238509876524882176913212462848124795375413685203394679813910094628443013927287441293406040992134238003609391456103514419047812504924017581356431260540495661829482018354302568674847169111459695820170190749331679546014366562347142754671793181898918388485986958453880924485915636886027246010290518674377149642264010567850266543213047334934135997149167000371132264856995579194506689776295105335043742845402558480294222289322943305100086282989470375185852536717852159788609734746865865882808832695132481125245774915189221097075281623244189392288446715622075411614334031468191703609412372090937730607521235645969221766267989635452574399129084653818865457181109762729826614830887148620286533027331460068506994086452404385868329285066214346702679650344774240759538854786657496921571246369832921240048878046348220776099128893503218517664979616717857057064736625540179395568920013283870174096081496683198449861953401350474841868443359005905640870841057922715019619122877787498711364957979214962533665318066165756195027095623208855776149755237712781918992940144704408337560163023947851680590294231609927955147565478346314014599141331529095988098358564108647053951879265245563220480089075187589087991678750937054439831532149871112059099169841180678238112340423689502506902717990738319315564050589756548280670162877834674125478160586277645810821960701696692407455541559841976442863739114810837255971058155057391454520884305250538528926734602232670290639248141809094351458554097646883611262463199864863590674340644668679359572287011629530792999195063782634488576307489565725620964223592167800795099983804976003908412787358577966287162337955653351043432920285211129549377928605297735344561229958582114883933047001701465741691315810945470776635412836661226959463908589810434691632396401694223389137444224006679218289596578606558640308903288113690697833602024546207479648803920220246347806151416256985137239827887488133698959090610537193353648394381106752552241273731138997285158663396650182717839541761361161735073877762754205810305131810877998869344096824249783974261433065201839505678836978417016161669625248532859703686468810001485087043397873772693309964594456439209055305889753023480249540414809101691905720139392673090358257089966055851697697817387247560867670197250040334434734016392459865158493161150760805283908794959043625160383366065981668259529916701875899721370658119810577772547200388874372046989220760271522633434573312098304, - -22942799660018296909141597893988192808950949278768378709602046377680964714621358033808614245764342087054501512207258598357605513400829415748559416114862340679248058334205525669632327311801569123552906031477363193024854304237994406503510556373884194968718704033104491958409223941056809214982387164136711227124042361163884621324742741860438343663366671218245474944828748858698494499430770407509239833652768929291580685280854785245496659714401183593273615866187261697227325060145963820892685138984037117709925194498662764289778262203632627938856633667695508851127076789647639646643839997333643736780489901321321232592848041952124295767588826951658521227232638915238791029586975409699811115531771123790714616237063298524638788665444867421860384796353544200866679004116548537015046581882796275351425455504495067598068232987255227496797040696301754669537252484492165038188411359562668471936426314185674774348240194821944195272344303546585600073829945139010514385996734079261084268646347341317658944860610993187339285145468911916051180561797292905848700293390472833629850028752126758898602810887570337835558682166690352283046267776972740335872733375233476975210869699567256078836991696273819805276982113011461525378206992106554840988890799542960103845990238937758326790532879430300970423851054578088565612137361540244921097915736460133484831325601957747112168358076660095649609846109983634663102065497781666876571975928182548151708375477516766486025342615029535130659018887321014271263065394316634547711646321997869121208950543103863693655428241556597398520099908807004266653985510580489248307277259767122272883450562872824190568828043366416602527038524941230805578401420199891918639467757033065610681655098269065528766014666752092814316027271929850376052893476677319794696984625913957271070544839079743734715064169380166838709554786344944367020745436798090061818099278252731840555491938083921277445451171176921483686308969804116590865008142876868569747701202343068001695199789002954171534682484653943256999954375131327131727490890142228035931718456442993689826484121561464219543316952994603395652265653371782526422227543993395024270798172763672284118406359536339337929044673593345987688803606864513535134924540854289730650055264258828951908706508725447971428550547249852405318812318643888427214037954564546420776702616094617301254268419250498965182097828751280342886257394997695036258754554718368247693766490330982207814642077282859049954663246266363787388061335181365634874050009726088992051711240134925366843527738908536084434303799094995127424734726281013638869378741219600400180527441500681100210595432031098173637188381823209453248450355789195723266385327543327137704828256983470955997564898708636734364485416076004653493932817410985073539346795496651848735892370410818569060190626518005796788548900626283888846148693051140294838693710161929433649256770423697551180012822122045427928252737363394368667225867714158690669591561723976651789514849807387527490423334001536488837392625862881709475728284374631795336614893923939008816465007195522775800517721505679368559776884465523086449667043781091692884950765922377853346549435966160309281168451382742168647787190778575896660507302922065383062887148871584621912596664090489367914173553436520615370059509465619778536341229332744015883836747617826521582005283565686870674992008271487950139172327707877663112617084296840785355167071567536039822825382739707938226879263586939525627042920636013940549594015451639265237967652990130795287172960231245336289826775545238386700574391135422656682967952754375339369154586712681099154245393012696698316488933177103202334151280601697287116021622601177810259839224805522542326468668550401962244455401477365384763520829113545536068545435401657165347250694775429266809750479463318495572451149598544075016275161532805755646108621675744020009215695237949479992587012042256630238203299027715539188997755383356176249413153535145165288978737058756305397049931993462721323159961048129759159246050703284171179650805385447649738860361830303024804348457553447029931734317687969573710348750753667443251164379046025539360257178463021120957563321784536273513936828536204835328949590502999605838990228808120338117012695150426456135612413962249258876911284142917797928830260690066304243799684339904304231950248920702468830790533869528743177185454329622339486186305836813269537438941391474457139889470755703592883985876519336147247440219779670631160186670602511472278391787006033430831464433529371590670532165325795986942016374507763346372833517128470979484617932512033934293858901821890743111132003957201115594147821440965379352373679210454791415194309135445417199760497908937610257683652574826831058272210045759637945910496823571812343149499708486619805875441742731033949969634647265519329215355112872098918914830171544094308305479635046795331917489071843459381619391863663603906225387360996836758624408312000916152631461090671960666183364218346006940374737905054833314092159606735444543069140156992015448715485466790415024754131464080205318114712448094785079058702766387799231931465286864373022853674142951723957846762951818052575981332668982550062363144701530930279199967678692244226282084959556384949590660984214144694841818978361816606690823794402637641319644880705167127117171389932810115095094187471229342958852701671796886446897302072726177613540829497014583943951203389228035969327948151231685232568789527789831773769657930955183647778729248565161293040355213652336753839781242517137564493466270327049617775463995598360204155255235446498614376110827287860145888644075966019486050149310659558810461242602459364971566429091247607994624805004326259283127131593047286742602229273285640740293180320970206707524850823937958330098556890533679673421971928596101573333298689072140433577603532577857028763967517647202450428998911367038441718316870269967386157965803633251577710180287616516121655762308801524782227318025416715357404082623250907832244986196424941846362606400628614540281622200883598095647542310690582176580384302566865302715593404064331124621451010939915886536893396034680411917844989331771660085893509065673095050005239846416091905673758254492051296634612373139678022372911673727026517690651165323054224133126462252824202256961976425765002909259584761152683092866517191782750784316607989537038423849042449344498037002911186163643384241680351299870807501300165788397739405582461472121646839514004902191761587970196610057817426182239944532138483021920231081023493531761566370852473765493310532248307496600670828839978106573122585169050419290903046242155875874715836722866121132381195818412029648951313990149425682646638625266283481428717805397648458720893898094525744468010404756062153635188754900309454050860966330648916665163310865110181094923209519098022494868230876771381121291888340924280769374568543895492067851585899802295876774486188749020662890484630427503697139038393504746883530653878410557374766878890793237875660901249298787033064568148818646920423858211820718532110504303447803560756898363424987017658847769790005341178591172416640296094851496353538390518431379694913532894344219501315416907232058316880733680892467017697962511907198909468098789656917487763562348511341258767234535639628654060034248693358061462413816325823265352085122452910475871140270576215250564394505098135562879169262219441702595812150378440187277621747689064543481926561177860464785779595281679667259699156557476133478017881908074142306633930860514040004499241046680741469540325535413586692646981627879099001896899717082497161426812834600059481926934069168584138627708839022858507445490076796276524742493448292170375273825749909049152124870965103253269728782563855311710710407885721290264923486713578963037839028487594005656361050383878461133548704560177697767672315929664263074985420635624127438368632151838041645010220303279898066750035953885500294201961669793301567934458956232416229322226681034157647089717155570656826428078243277784011333009065551043524415249803316104066513167880961249649573377079831494086580259217258371348266047779468117721376415778066663041192948793411247263217539156154607889894091269953552384, - -24935845235067625478838551519430704403823525504791949822933663598944888717985671695919389793459435806737818959647565134388809572814299738394279505397221377687885658782508058372642631903851586467798580751327174985321367805860953825615455144318577712856946911713386538783962316649637100229189846432753800510421225953464030704528852061282679463516516086083230197879984370132478812371725170802033907116077782070374920393091796218947368502433809482934384273799589047521541300834403468895118875175958343182272913965495757831056980147591061659307156449126462620043711996414447953859863599491133925561298006454535575288641534125310501164906578258314811480725890030317687237023298672081335603727618517413198001767870507516542303731302282178992398469630913526933947255917259301744940788380216633570882340699655322643583954725024673559604776174760270113361655916023664841787820967172773843716679071866590757927828362652824848582506059035333058744691855557260127662914006121085907304877887757916590072826170840356262309131694766097872319902596416125272743392534013185486429294802920331553362240724871993861150816429319487743620775733157046256797988087182377235252384302692370167389171587704287988219256695603207963889470055611549074032551578409092835835473193825336380602699750025028168644908248083563501994071872250447279949256308782419461842675779275531239814772529032020213965044447938967395046287218330414099464751946526489811482728748376547635447151664612717835338407215426613286244714970388480137261182628093012207965247243512112933843325702764416342197294025174600492318392253451840588721463252247186811851361803621921416032434538587384336298466949174680828829807631464271549256223704863494993908447788314843222951442325826811653514852944367265172013846502986986513491526980576674470794281610956146989720357578656444284023266246203461732293353941033852882438428650500478166181647201827962978906810655099878684797600010086798213562610072975951016813407120148743046904490694486797337310355678814171469456209264743524047768804544603158625234651500428479987730278098781953900504658539739109337936230149433005634397253763049291226430593186790972138945012371605160684262348066386122287066046605701745782068972430967805123311024569636106412257631083484965845527662546559332209733448306594522134691488063396254433448815606724583934949377157257075618328497253236794050966627189564556741266705391751131983253263432660328713516078646604920129026963348889781217137174836072081060041797261554731258751370003941695212549402922319185313530618433437179542168750747976963532359556492292380690533449029023270268078444085682033190583370361117595302379326001077883551004616564504066935976722037505620621674121062368969166569411105135045845868131164657947107261978322803466703785364489576818277420254494434067429696956436603143383188534453541906645181142344917400315619749516197894060626431863911048405773430903409497057375388370499924971245162122583472302419680965230770308174773870972082055389610745144298632042034889845278119764460685546009246043279088583308177485947333212544218349854513358526601054606470561673190871568157047283991239725956325229352109342760004328892116411224854727157639616106595616071357249567290737551029335208095872917920362481671022636211340546012409748162877470499540370976812213925888933220700486864558935383996528522308767583093578487721805557711182239493668008599650356658573036487722918493024736976848298159065852803918741881916477247946915809334399324084547522577092170674276339157577104082850983082851625561588769409124673746865919278703549422483019877480911596971169471314969265726458883726868952560114798357273983036350963598566296568299383273575734411194921861504529105888944119032939185965155400882442445032983803643793987543624384561992364584848810052456815983377653206754498202101633779946673865319663002427476414560439087967236784688830945102253889445117627378084633349840576841128434932118169535869928259166536283103922506345398930826666316324149468388369864866467312230678863988316097009594556169948956652564193476431595630117062284075114498984473371195362445852524502617919813584759712579616725793843725497538832352204724659715268738871905681895080489391854709371333691603985501604503680574040305351492608925224745963197803308243660901783601614724835740135478761842027479920337141086243563737738519901436781444278234980742591686364546122747887817860094442924933062809415198046499691471066096001392346257896545972935577766927404741064611250344117892854213408611576769923791969411971039911845357674603619311666842556547442554595351101065936737048673219756907806990322302652955456778690163860667549592762920365766545875974807934841580698617157415986421335429364640948634259374706474354845315254055171244395342974306843669917239230187072964286541882819492093081864911013183124698706362289469513668423566792025726043937391007794453341499210522955952784061559509123631752939903251654104765841539190574681660379732329925968147150392763446588873299673419995461361398171118255701952872449994415300911268043885260690541418432136599832291034576364496947225473529659323317234245901998292635319824565827397978785280722231804855144479260292244863825084003177819773935131634947411053267329064101474366465521853290224343774627140482901114031385848644573329224605874560229952215777394688313743213577702843244930305019490756412594192908495907811333471410581668367533708946903367383501222875470876871403629867152290383241680558346398748720350206576417939158281766304988781693630794975518023748410809115285071441221907904419541279906902674828621903179629950430137442502095236760385837256985775177643430817978511204934777297667705346379528496190658311817964812434530214374825416711723403788334875020636233537348358107616377121714610538136888341683585398850155385600333651727324748936782785975467615306415670963724870875245785627922247838727826440828385727590957362946379808881238470354057922615907847356832600313866375808514416889107911012484550879402500080860437647584830983107677343121086016511332132033305105747678679803216058225072313461282921007893710352568218474994838905015660368106870243729173755609886105538329856218540273426400019004856146839709791861626010788753733245504161492867659422735925937245681004571265380808518403822045434357915792076683519204250783218625678035216197605851862616068645167927181989926356064527588023788807931576065982141226477691537972762836278301383726090436928947711418099513239517835440158432737321648997900332275271181116470575584435366543470147088094311435377304445902783387207413025758044486915142210128650528761332926380571794285203198818438955100122076789768556128973356651491444413801003432215229200247555318134297473278260139085419593330290760120694897942992597246116335593837640661597771909374640062162229304620102819694711725048601400962062211917443597793420171371564522304688933881603002641683742643761603158720855066235559955987809201253782879756556896984993666036946636664394384932419202470768556694965915090493514158850638089353027286153448876065438490701127457195918552550024287531117643852001430236067163179606875628522332591170447078997182244017496640458520256408984964694587909811922213038149707698080214123346800319988313257770358681822167494404063432128744930351340277809677891505681144315082662113952317028409303623277628765117321143835378010278242864838884476978080709198087560281175781212642945279895274763456689318133329910890460813027123491792729665633751078284953255831448845244393051887796273127438176297709765993402858976223976686418866665591247961774793681692799002728132181644731346550809258115505460391529874097689994789171107983235408975198688458231097182369093728273416914424066292624841712373827761366070726150460371210222314853487597327393543378326159522124644537108744364853313061757373160654820198910300323007192707491601152804569076574184933443876344338246444410873276111728500722269376656308537415936969878096424625673615826821920967929271309888575581394842821120596342563790280821852566917813877712158949376177441896024988070208140942779226323703303632484611295960672124203249434624, - -1700091014420795190226632482911273352611937031827336831602661753461712112221983325809898746050859400433601468441185296279437398956172450995665561694028884679888954074401260345931347506580419965543589541790592248992003739099178694639573521798955305729031697388738432712303143445083505488642512774499583403497022336854400995795867095165539800113271556402292011428401642922617138441932806782124828445428880735844593107306941752766178791005291582603199736232947274566769164389529029278386812109775136349598281514580689328682034370580143761928176138681986199763835502600206489289434520861770308883245166905405816480270914180523833752536982780409835279725823985510762974449198557643632773401004669698852504238132015061528340685219133932071306133490723013280566156171487427102235849204080471425106546874203242312263638952383824129605361488777084682433139693828521058041010425632089441492967569290491811884745823330730873006060980457172527973224807065933011548519885942427895448541401804229923070751820889785964515447664500657950870149065439269944072777120838410830294638107584635658840168308396258895964154342365645874583790329103357386500296432275584633057152808133163024795712437756323547660672586865765068051762459119060252292565094030037416545585801902813337071356990175101655926703079355441509332975597775571768850366270275729811186117583948354589710342346502323844864916685125932468496234681056167871448632258231713541763624121577801091057703776618239974151865820729532019317043313451480464054871415728964971035855763466604572881921047422940954603158438641966167616969955473837921170444395573032629755542530155895070696388914795140732247917291309297900532851100785065599160306004600484414946625084431022316783874517789425292813524832839595889493262270031419175477372449327626127548671589454750152139274629395535129745169523094155076801543998815671261420937607688269290743256857774891025400792998938494082544143067739008618806383075413082282776145210115305957669158378179549705822581283915396633535755404547811549073459570384506786950519985313400026857016308931462522264686080722761600398379124460670232646877033953194687415983494597424892766638270906096180881670800056516035589037970430002964509749925170615481166815489299397714653445167810101489585133915510603700849563565203994827701746332918822844601950720699334700633651203606868999552484060214349842459703852347888697249219604206684248413884166994462808035452186030498366928756058899150433405335407565524372688082620551918073451301649891788863028409515577279098524544712824070600296980827801842356965618223513619318706910640316981990013171363689269228871487317900869539708955886490200892278883237884306169030479921899004195635935177423473316153783811459221136567853724919448825900707760392769733164638629147364853601370371570907255242723530701774867742753375361013873238117899407204895024814417052032819644449474760928485753329058187348199853513599134110613227985827004869126930986719511357135291031055818728110951507410426866810728595976230095142242010070820596612342342800702414496145093662350819415637088906052176567386236008180481714876347679402841861196690413596007064708325663018105101564851890405716118817728002963974772792033518772444781643176579212052122099253700218701856761009463737723928746954576938886325006011013985384550724477884585355371932723266662400484213746974296574260267830678677440685300116494600967547711108576330405205267393216495326764305233255110437315661206831448145810487239222188456565391014481211318345163676845001145412850458124312730411250438650877002661123170683402138697243032267257100857176491252653565774766803125508899706845797294723321678768452467736175099750343751391226484730203940765655993322566508557066301552128804713964152892970317720933567354957485637047333760757972830164152954413493392942828393047608139059410174396978228732213570494244994639455122703499126583832162689662699065524499768697320116524240927325152342331043225356503406849671429771634979318865908902122936123069960306882623346349638631821116374294734872688846411020725362301022836225561447093845570882987947961848637551314890235607471317026724446999674450658360559050130716375725569835096933210508737023119796843318754849613792635682668748039081627899039775082554350444800563767385225000735434443623011367240319988868358448500573130415118563887256359088346666401297330351891290289852917030920762768183991703703287829882356182813413329300408720560185770175281423780170717763719725260479516137566447577289599131118803599157177503379982515049139310611475534475760621136454041359371724750617234999789411950037436608847117665956671936317997326343179902017427231477885909398642420964499754269136455445936814278780714921993214803655482081790897927270078184465513372207894347066437119529002573295074862229004648588014764199103562245448324707490366912129901628435553292872165965655106524821525295890346587833234107510867562766758418865038645453562796666779236753320896575676518673502109584318518639478375259446798446202272596094562137580065466989227335692978271130792233882905926219181151181933854960037177280363409119916390613394891060540615164060864724426858720644141493425300842710312369835796155997397143517540476901616088187326907730180999083388474490163208260823273597195998271727264495306566528302575618284262659418709699415178757488690919285216931914119638157409546058045958760072239113421152206775755575514948135888155599301256798108577663759824772873544129630859402191403173441926837876818197242793764843775284927013707792112053864974343127096834767352375227750001588095472232218654319183666043606525263931736891648589750760490946040861449821030763029190697682779091394616231934840155086192050017418742910476043393382645425880659051542156237693826281480931487824351272837633169171000236353424267607880869083699563411171220667718016178059184276687034170066080315117491843942180662102427595912666965987481137350021534189153976487817735323346267630406036202031213788422029882698573964412784980185132500052917175625458398135205749013960323381915404924511764281335351845025813644012557293521840446957023100173834425427883084677380585638493541651663156362065001646935244945359358033594679923405453155511821412736506592998060010113772760439113279941839786896066810535231997317138281816282897495044568732600226574593387150559393131946507287174077375876842132388699782802293533250605682317574568992245444831945812598091564329006542696977014081024037021239513051474640778928585015165701649217332596960047411277489935498409814880178967219941508174212035131195709020302429095187646606814173070104224091755728006183468945695510259415960856670514026873112952640515754646721304977959250194786966668718992245957820358365981455062408779727739203199665390738465498141681791942210716420188867796601979647746612336828787043171537485757427928645006050235301408367783232029951482624717828149721391010814006405109765623602354262074276786025003385586101233986723105629242383332022466565512353736102926677680954258099605397502783610266315785444701903172400436659004460334692082659812791359621059961277324422538921181876334708071178326895985614316082062792815177536246518657914256961049438830906301627402922028737061349464712024791801915052979449379943812874748429502885378019935649139076175815651628878973430373985110265830104796239185139084859256258892961541164781130264406653256095076228662399428481498954261484467186299424655955645145396741184278165581155856482240539422399831004265101666377683724710877397142736451403943718053988950170608006004831852234687676084887601647324689071509089670853684709088543300921924030821381611906814905668912007584968403032092997002651359343940737206081858858015560572930465638099702513156321922157792533719240047822825750407337093557486201279293914272690661395300105479241408209162909883230663412486866293841928533858350532697075294292277942987789469338529285070796418809370968696008130728367864530259825899577203749605122899003822101035304599429348883259024120036563717547775694253389465890721293086455915486089597450293059521279773672236721494818816, - -77031120743435343412493189332295434623102291204178069595861747132657494768746651303741121931970525245303440163873934272364307930145800787804401181522973494492661544177162200393202383355915141575033662313523344169485107052106274071198273293837469277950117128111409597755960640906487941997565323216078554624229062847330569453901215507902852400031738466627558038245116830283561999365159503528449910750878295963301866643479534911775206814231855380496557447690232620998045107095491856708315338919428187198723798391664311177735540798077037741823848943055727556383834108309430178779505846449128908951780132271172694836827762895255478551440125171990899975498202455392995083477536444931915230384169630272932830076873631907504611893028939636860377172061619679527803078823049354484600682474715528835727031347407804551584323542979239213290563071573192057634357466698868515709413915963980861492265200021219945566404398390113499749594572081060329638755395485859745059756900070233100310169119341125655437984339908650662860663295577167782646121218753462598337059399394053963823123020377050087189162586629310875225771966828504895158741681611906356543268585894017984403963048299636541166204763728205551307969620005968548727269827766103462987170247108366597615802840994270696476166573754867079826590749177512499511330126249648160537535046968126736523635922687710875453341007717156309968298816991473533949903450634380562711346722936674169347060085043082280058205581412944267161187290357011523937776661264342322011473494931644671586610342482760929210578740660965888994735353500428051422415458425204162671170833906544639004188129726132505186848302631729482892316728758587345950944298319559430001457408963303890287110808212850042550856412350167398838760025506118844596845472814232666407796529286050488819731184274782046869846715879623928575890922651839603684282531916832303051577626303712341985620888775737384202532789768022437015422073183070992788908315571765291321016531700932191734589172269026630788359373975968392458155462735858009216791123327934497386355614624971193905109127230050662734480558764506817750084893302014691282044106260909792409123273361956135499874865286792208666767228096077066961213926615269032800717664924198490823906104422453225214625009984844820209801157630233119706457016107572401011040114107938294864185418140735791211436743447977973426322638003280788319647159160166760460697018509014141189534870441371836820152176812741293270745887471538066074606856249263162733970286083938705396598661846188067027473778282903605957518134433637431155762758680213170967373633043394336342778538711912558422767819649827203965310457402763716344285429240915832742038886267239075924521897326477402318009211520446735754211698328802210029456956884039686996323930474206324822040815014369655910294532716011686221621782031855151816575090035641024495306158400386642555495204019748568864596777485392159889558446157138012748575360455682373810788309409722053945843343980335547208474464645168711402143996253699479194737656229948793414224346072818371056092592113358493215154360051225651703495999759957287756100231082782190444368849939664307631624116552243786418821000059461080557041247392998268001026838467984859249375107111156906687640918646508070959428863146173849118626069893042048458930744548217636534096614181680352885867065242562262916522510880038783263427900962320800570068089731911457826095200951489386976463659382412374158851959381386501244158738895052789686761821397885137669314254003462809150106068648240681176598492511683669903414396139841291721328731079866357214879971734164645323492071228763485660986381310523758440345682899792328727437275768564524349864456881819456195867838674631226135022963795841152404028433546954892999690182817864382973638663798075018515450572716937161522323239025079304315171877554403575120603829295497244263640512751558803664045001573940688911206666933860449880824891740356844919166179379351508383909932610483902001483836053457759414640558443715425236398222848708920346286497099698743597427902125830175981674356490829316384401745130669424016352327427417061275274068322167414828568679202445815445596865926859322974788331571657191308445367501845078550684251262225304994794935039712638960176373824117214270215963333108431105272353092016532233853297331527972014765811598907817617063035312211640643539814505590357713380079335961740709054507409539976524793858334506695138437996457465785416600233967171036752613660517486258285433876823279739288520570848274795760031081555065344328478945925685179750879981226961562792526561147175329351390208403919890337773053431047765078478097964383094841448377833297727127444468532122823657477281514490432739723798522732506949554808836817552175494818266608516541431508581167996453997317527238698141940908317828756390971027026741341124670707065025405577471198555237907714280308116890077372517793554561822598805193117836008290703865052306604062179395670135504112352464119229528178379543528425368782271131752362428995357827589135093398045679933489074785408019330829169224751635464761086408057314577504595117992594564261774939422196952661057500142238620579090510333606401227256794809595159156324984088716850627699544279346415491871071057561767648989301947278652352527613654143660012578282642850067387367762146327775674623775328559523637146207925339308606900204636654253825145316886126594788638627906950309222557583467864844579069649217099177950971894993738899653036388754183710886043902548738421957916748895179004145209795380463242673498058404384612302038721195297097447694305589665930339918988211484809457525949118288109034144033085508107080147224321494894930446870565160101043971044635544888884540598839418878043602188238892999688473187887451945564854042771652727150591286005411316638571615966976471540521261790515396316859727223339072214134974963073395793467214850504053560246424548192462386975467488351844932654838234349298271875477234388026226967067694272392614411632630560131670238532091047328537036888606904807784109365311147923144893040561639548494899580060107871966266446777707543840488522468173211039315324489957835629625830785374669534277960212275831975129940282650257301061121410885418976474834321727875028269487786915115744037478461549281674178022149560335103772736766202478029038774022677035187599176857956967650359975843482168206803828589258464693797086621971239398346064235639647735503365550071379169247983306848111931478532143753152796063500796299878467117171727557880444925498142046266314777332905611969893407478473452612510273171563745024910887894858241103175293839038939396850265227578424814417845027500878285245067947197395575009209904190482000054157785258549173372814244427240386596958773483043443678508097748667799490463597228050166215399146972292738353391677832387260243022441705900824812277640672708156241841202334700282179594425659339786382573809065143844894660561806763453803607564979660703850096105216156093734508604973549062334385550463766563022132500606657449537338361751424081912163189947370781572357180967689881608584954953892162481239866827420602305784241946484250375274642358214900296344722636350915426359527276450980980389336431524025524777315549322563428087026385146636482610805933943610966513395057489210661082454308429303712828097241261952206935268430485363278895665340779610472830663309061701127695286452388883969366664113224994470354756075989585279588090421160354623667191122913772163592376028227694260848408206014050196304828534521479061998965020142496593594945801495282136595945897102175517298978122671060582452188327005092164858674560135605127450553787497276778411664770055232707054253181737776968906993278506572755805795265599735836975383590850370334313539355972436999060067838809566752762236112049593500198967878707689771249959841360601084545238789359396470152619621539903988775192601981343904680526721352428373377196308123227097892041758168245383207517265395564313394337072330634432437379356761311900546208188484750504803057030192324825637690564217105162864406765478351451111350455499741463472324890856332245431195243905024, - -2568226375840324116298990770879194475020967044568090116236651097691979971202819762394174981414517871871592350870629976074503603047925223243241847941258193293301726575144243150581363887831633870534000349653222960695491743784441256617937111963696392737284747163888729002822844136167538540916746275848436675525519070827831649453311405615233613806809941276180490678083547699021555783378638902987794928739217509931109198351270714281345413411435263143769356680949342154087151889641022344473451908614489900288054522577932910155281759007048130185727096936782500174379705645326217580305536674849322573565181826072727973700984790917658381521295075169484012294017790827749208161706617751690035624982763812501095986420309982432711738685842149244089554070788237881908855278573208688958674619434829899298005917766083839449347526449985538708533003862088883705291053858953271021829903387174573406918581102481075604337451671471986014521878187760369285516011981675791129884162805159398056528077815700630436761250436059711532735182799536815937136374309810871236328120579228503565433107922011605373051493572527786071733121204330763698082850648377984606653901380372179423090400048998335968470697962840521598481098823444676592830376250936834833647150774505411250558302132630801176072785434009204920631405401496660140589887086185519717668806804716229534148389390419147886839707087205518043407568812889653551001527720219077948348401330499269257528134809802886499257883892480667066499478829578397170204477127092909085559022033417325467622981508157087819729947902888382487206179857715244075907985687607054095908796052442900107259519046266628913258170552189020800642873043759013730316386130144055490734946550939371580196682081644591926593527097436054562585924106898753283859037265136988906887752530054796554909110504922460411568011485618184087268110350016980317693306988141909920361872900004133491772196621995343569096645250305062606867259095819763570596074537502926075697884386094913759859391790839090952694582861972932378152389298145237566260580822347973398060319064000400923313790388285397856276218610439489235790089016421893891850337952616057789768513254088782524548253768129645938203636098445951444421287327824026076523619454080833611816924007545850221057815976176034244654402881870499938492963296046313351087592711550170931890228832031958676332855769565982485191710183608849847037022711815780430735752942006692865454270976189224759590292319925640076134616305258865173376893386057464327195520853682774061829846112535632316114631962326238206698114917707023600722028566365945246484319680593111686635426197181283336103854948649689069560320302926923206084726790418775091628476906717380893967721529696867300932541850757964842028861138098434778783073542226769005156546097596584607590483555940835079688653104342226618306347502658425252152831891378418219943627573570050046997763517710917190626685931042399038933907320709086155197776854211058751128755556906033440630229568327142681876934343190591582990125354067111687063142817234064750464022495916543455314484638178958375829244618363075792730425401630619482851072639336531747469109940149751991225067405576996003343106699327091450988158637454553904857866033263660781796742838254600997179059482808000308405012239936096463658355012294393953895889845087986137601598963700145074438640002879429149049305835823100956776106253646127095589469677144422466285934479764781805342987138140426585014833115884551606543869127020233595740368927924311689117794443557015517105897592633201071241175530499652289646438776414033565094802693416388500384898768296308971285033259691454324012942384358639494085483637726899705072715681514815912306020058582086582567164136715496517154675218562786121141223536835478740948229953302881318421282362703653769620944790159705625958000656297597808784748400975313557669194050621773334525044361432494963946252967585900078689103004505159069468988014134507613046446943919444312748474358055168555276139952526160652038431064211110412596522813853956681055255338854313595938179355376286522352749714582193497534854688674938179153148964444308091056423136494836334444489972052142935338386900930219870045689496610579744335472509112733294104699199094654441960030105845197879453449132517005350222077801965543919355423126554423483261402235989115008160070040879664632780807152157830489029841773127765821004718740011079357184979032704185536887978058260246411050369625226812992535861295744686961534455646423784334031794606564973665022688708267372637194562828648634148604598441706181066755400116161037089024663718496686307523794516566455048753029280512069725499301108419569007850834367106202717726021584321441431315540077120165401903320735001990164394001541859949357146886317153678904144406895899986244240659051687017443541322801546055239089970868613256611970661066226583110817001578641774111668007195841391906096598335401844075990594942571094695690171310037002410900618460144111790065878846108737433944688422093271048159211419356129226860780609300933446309883411047377612628975114731835810169771444976864132005468737359375798032707887839935373260316507242556628534819517439767798958875817295202597511372264846338087479914947968764106419097753105438674038504115994523726883168106262123543188535967351528807407642073100812831471163769454084486844259177519289749526828012796027200852357478959077398612115272403790060248391613141809011212514094428675256055984268754139070822578454202894239840938248996423466497348925755695772813361087864345934356303814217334344412998499275842699570070588316142667378108255193397215879665033518964748420034321947696882867833716654393310735483493481025751660974382048182257172618819291315054613547208935549291424492946447612969267061859498295854542596347643356120445624440069901623666703486702262573939769891997475952512621856497809920280515647822202253144460365841482895840838944041198607614051402753803175798396114828384051525974910101632072473982594927925657492522588866646921794205135185262549881470896684296568457875498180167139218866510752976423166029216303176658378608336523558863723250740889246341481556042177189336977668062955908239003584450267784606812379706917702256634601491018963204097243272627611970045268856211551165084076104574705120584919187545840865979322388054598884542380551254182678248222237557987860672734300429078199897283729650266350982420704195122777298656195054001217510910359790585051117920730061163914722042769731127213533584139333283420081540294470637133601071670280956058446384507500349829165266413179177770328505770928201160463706871924287606843676520224401483541155776054171269777713900876840459819810184677424518293015901915772066624580239835661703471096630540837638935101669661743925456928903781211840002487657595961100118481126527073966346779508691641062563120949071189778511015596019125629927151134400427830087582592444609171584972578469962162563448979588793746213544703814289348028326113994443866537236849001690954601533395488423740887020120502959195432899306838337561049016793087363409101559395406506820921418951867354196119377620582927415211203414825705336321113783589365188731614626278554940480343229071435955874169189713013005608914178276421378119643077378278705246232923619184092271718706207258769951134979100500868705793658828862476426006200321121605026108356406377975136725375893205746346598015309303603038152443538421524218123267246500420333918620540519067069098819569110687663262470995127646691031648221465050551381940638088924345464231762555559674604595728551900231611132557662329136599848824782283847305221449634950916731808381637753892406459096856000686399148693668032388112965008878927971854942807715986891771606734908177864691336144624976382339230904980325830490159408191866208237782111181623189869353646606670199986432829760799622152119113607416376716574867349887468140106259916823501891951127073475020112190373808419587675971334300964556011657007442860289230807952642084169968139476045180763086166520338868026581229008304819399914375343977638537031463333863311504283021103595520, - -55277225958948436696245622418688859511899562547192431021369206176777062733569266933089329006928982401594238612298980005890858415117879973257603135566541626719547898214418970642174708432255486868774186488714668956021187403237337095461048974835174800808928273133499735131266034958026007782565458522778269424956326337943504386352189330285642761291830923559305029449467782767834628324329407514070970025147420048554608083043274588233248379701431350522001736084174878107017060105016668577033421920570863196022975104348164165764010244724468469630436558311079596697652927963803122019759606057241238884403906356920508070907190845111799832548025099029588609663081415214927664599236440167915425992553610608370030757992910715051294420891439692458586251032055912894568318469743731329851964992612831927396300116673271062239516949600554617590691249051419177819547897133636013621928412163988952939457375500555913886969523008741881096193806688597712344771385120705188935115929714201186955803531015227490638688050100519207275036915141173910037587655275262885266982014262491527508529546661135808521259901901100019828113310004562545653066339320982671901028093712588502569287628125697014117457660582930627077033170883459933941364069973181811431870204047391964782209614395256476010885506324826730949343951359910352223531880683626282729476817763376787494397885358849161454647352490180155168362558293935993876480475588796548597807449708687383863289680500964752499701842629152602289687350081991960467375878868942160195289191989043709849536299410382714082801004990668355724185344564122176203183106302174767198306797283310229950706201938356691907154382221653700829433566444550860750451167181008815645628279227431206904737398562446659440082762066654839205403326074060476570199831952043338131066071117645713819082301552977238857829591012899882525127990857719436673037834131203257678257934691486663846537345371423346152420264603793591980796521776000615878690023249137672549561122305209443635689180547891845992911930322742991379193104839432630257012176479882335108682914352739283063619010821398077814972800518077475500413617523469522888464968517483083469787838607036107050214836921039049578643588727694787342479341506804942712047854704821512487925069794198714664049535001895047948216533367322558077641402789434879139771864348738747878376063575559325298249551891100579579754240515498272173270657284050515172832187906395714719871746208503177851606338641239048890409258657188683276453400974957866615568457214067128686104720527674026131913959957031840585377837392728524365285091977828050147071925328744391444352916639891166106331500852543416149101251650006858607336261163012443022726117457566641383848601458980350433261436011085323980931229325397555715213424706445570710238528977923282614426683665519513026337115850966877128072133790319238405923783710635864888632660597436746047268119838126243647444090670439655616195759264710035445244740488283277385184121225063689806490100303633852461667313468618202253041589640574786359934869264566974808829466368170748136102770950989141521673559509128483279322296761281443647426800080319161017056866442032027308509485567218082713547604027943053135292224867923027202763053861170401750117188514066274325149168479833696585712307451932220575671032085974370998930477198573600183205100509709634853215237131317046439121246810220344153177174866249627170293419470766580075730488857601138992019694509522740039195053135130451141471137697144267400410341253798444808960850396440312250309180248894790676428402464525736023231214426207059633717595370924005430986397261506010973309137609895629554551189774353650351649404124953855823328764013932885872031359439890722736487036694053336726102597650340264390730539877084438249483965349450189157215740408983181046019260296497151101201795879100437212873216370519414735960752624843323919189624406453186179882456181851763096546061338504407319489788861975473800312649967049152008912915091962839505380567311697892827504796439623990002611501582122261986675971670990079204486208938313640354176493854928292968214202822834475609100216707348893581445254259651908716153286429497061971398922336706136854834928294164624891714854125171899559047844873281745306278247403581027507199334685081286431614250568125547984278809795933314070098372520024761008915665789374723318077606242490924567749777968274987063202151890287694212263871218401766533633871750251495566506755285064512363668218746450762567023316700848436150612614490908730678577624153801614267869583891087849631841800515249922004005017645160471538510902835230194397538633481712083929147512961932646910527119678423444115739668071148901533619766104117429268449478297799039927484976380833767997160901625119790097738033557600636924497680903137534254416215981050986619580790234821850729164637806026789817264631579135482568144641096099858053734499410886760419620083662441140614564679562380819032192068643597330496140972015615955310592184290171113810501988857280912388765234945685873856078509804156386351391880729796397787118091534938953077742958123526667794814241582732385616119768608689993990934270793712722567380849774952054391732606807907200820122227598075288530088743653031425773766526272053552638050214263377458870982851917575207356947048352649636087096141935712094267216383838948311842742100838755775574246279456913543386973776789002082848014392634601408978606807544976992662182619838439423141427000327471806740180520739214732893972504142627886068588378763944400869807113536224711699205255609294390234458163237977515242599829406497648819673945917735325679215399907344192870315990081413768606344772413394340291780003527952946818839192570252386751642123243789228526179448357681871710327857955423829579825774742781485930774446387538558775506389155034544029817989794678041628319186070529190180119183205042079731094703414334795611834851218273201745228525561629957879116053294291424699034169933134098962955722174647265611875156127354098872179649364751067201398304592287565111559807431620449970047489081546687835250679402188498370564110974481249216169691093825782394319245206850843600621952085182338605510195132131370671458527837290871115527606667544744252377963563130801850625423636720474938858555349414782005905898479665775117868124721048835932575546267862091139272692812118934171734371870380758105347145047542160189698669924936189746292515854448029365099274343625625656040812608451666414956101805689259052012494746026481272875655559492629502109444830536047041809765190557303592192187985106106694793700805174068444202993997244412388468272941503073644583816148504465262446555285366042958610800317455411705371962972171218815206580723394268507412750298321425227444626674970882813042720751953373181656056340376237635135117568752820591153783439784927360593309696040148285907127416800419596436956219495353657004158462706185852821987305593810630198669825127286087004246096030152397493605112137683149784771325837053779332876616449787250014946948547909868388414371920042949563558418679257009303918124404350988993737437203921690597420402174717929503720620977307117161629195182654047618027199538443628853592143774159876055381385935123381615533571375725424328976943979725584272795730773500367443809704007094888842617952701307771674160234733509071782284892231040638324619865497605419433059924008628349228262916698875739494004005044925443500491258975281062164925863558679003840490548848849426508092378112967075965615166107794763776117056027581846743411304526242781740918045881360142854469090796351777851475901612547995481095510043350762666024116246033175057590355017289106009757592182286084223016413136044415953182277098165890056806757576783245043250975885265646622665793170069043936911253443744135804655862955877033995376481041453705937465977802912975651423703434383040867057995686818081742211815770700492072070219482249350241234810718973226363347929531435126426657286774325306658652937503156317911858688071659827324576864562533370212126907904444511310086375457571152723003927042156465750016, - 48174813357234532659749850781741903007090510716645100840335512992213203604565617626043515089742953321429393122695029499520090787575518488519023861005052644114711078773023249462822092986664008364231619865227835999099997041039719869985889281751772772701498306640260601949421605558391057887586181840137383572199928989116870476212536839642469750002260902751860751114364901285468093031350712262677224679980114915758804524038547396084456128406455550720033194005452840873237040611030870769731880026028599420057097637444615343537108933664835856878628306026356531610094233726383633978327219275872514258388556108884822618329583046000921845148020524751699743622366277571737369481191074212243994012359985532096953154490577391875580807920502460731947152262965280129537697950454888139571246769778170366956134927300966440350204661472732547408856004587692818637406136344224073970275875224315336928391011488896088836698400214206750620307224332566903312643964632299316548996422907895114983225543569472025940434733940416593939558890870338851339365369009300294511845522150154768229462014947206851657249589579430212190211110361476899112798977475589880816066354870135543635570294399733011198422782546144698589691647490633837368704319944773673834142649294626968564839006321018491437725527703249372261184046880773765467986673472386908603742880536356287034578514696630795464105458170957410439148949699665744263532193984745780090539158353069871711040056285627106768116437438122971526639746257836852985762195302460574530691053976652889246168073993572366575208217341750488272852285895553380395742832659676269661775536621622261699715998299706978258058866020092793263049016179409497097181669485254484039548377195286705037379112560620816442122381384653083507454977162381691364868914929342734459213016861763957683413202681394871542782720361360485870498763056978906762129308763648298206046605525009643788808369047354916689203554478886134684276274966487749409678811570105245748646515928461165520882067896860102755181741599493184019828261684158133553125086599197618562902794554629166451245429129045824346062063182750640407752478717223084139388185624844123921748124863976914182010966963455801428650011717188601649255477177014042816559441162793710490814462039727368351957985354104898683961658933153669323040981063885582821280088846803413892133933382066595151229202469563371848244821918779773012249372230346252849260529037990862524692887487489676806174976392533076866561911622479363184813216245551114004140277356727552901622470238009216980560987453731791137081482463893190628607006669078597250631209650720535046006462674538045053390630654342379796300274722542395558341172502783308485659516528896172698291311509685087744936492297970611233080567478720839467813397259475735725359178999944767481766805827893222231040900723501526970145996857948707334916969022630026566678317045985307906806977392556012316120475794746650945743971654731938370686531412996173902334776281321017184754473074620060556841512099017496613127811628589249232793280132599749029521310959186124000394801658380842448150027181870407245194960346835833681300956457932164456367609923726788951800502856838918187042766078658668800175949392491273707117531033020733138540287157575348030202705548501823039116181434687245088585590873330847537571585943429663890166756055351318755635834120887301801502806610149437754823335359105980855815790652944608215750911183730298569240237151446335932836193060851916181455355645540451665511922269678220540335387052660133198732110017298557622384793762777019017588483240302244524664862624984362240043339962707769181172054373808183897759504853923217334396636839691791637123058284219928890982490012524588579323839977008130719659235003398466269091926947289287302824176949588282507014396824928177667062970509889094543562814302814155798708280273716113843151721240852203292199583369128198207968316644876182198084484804350268262163473514560111897433293412826979699546623159683443267458409856248194509615277748069733356703536223879110227367104850169309002969643573815479067743998695349858876023987725680315421716731176493345294084758668057265006099241096085973555678366976940947694038169107011638263920237429972482088980645478882904845165694414616608444363509354608969806270741594774077423836672506379644184529648613409009979285210173236991104624328398321324766420107291103064418835263464302242162678243787613883472330848467162660130862009335239337463003508256014818780913688096057073329690632349661885086618469440464270391368093393547411559603398025928856279311772976523788261954568463114199114685229642958039445994296725697338855698653426183546373451748321393348055657412408759543270632483109469242443645401741702241057502062339074510215209673464282185272436414502003241871534882205711858175135541602724339864537368521427970542629012902909270589963380579877101267878022621802635363733213479343246425337919299865748076232089188586638243468095170832434699500347597855239606919797847156658544060122475593086068660175211649343928001284601753457964951176218203773693303870490168775077715533102907452517135523416174372863804242822976701164295656137360620088947338541304137362191646324030671664815838504920926819733388437918415907463022701906707770893337564860976644859121083950532607592466478705578480193575436197488696902813140645440405978126443339782912113997131194201814401891769826866674805711284967502057940929434631807131915509288774180998207057209192881592898392798351197954786169607845155094982829045627163690162580756456271359714679702962673632377068900668664470212844306208451243316151894524889653621566462620015802347023886747765013495132997675227892981655257967321596008371270007787682655512234140117107481058168747437920781087357155876039705392868723720695948730852062203057654980124342683945023507975833472022703036915064038909015446365259888209213397036333568587534844549373727110720806918487787942517813413384041046725139410291332561991357774413793274428867823101681281392723358848860582294166015398912511208923244610247237262115720933535878410483354770382432267718810908226445176723185845034213734825437412513375944317167484599164156882511193839925480220049184441137272163382149664624805346270276130100293888534842844996054555231370482086752754403792595528011679422536251608352733992978154491866999027005518179688445911104479346104250199614233107077976147620751966511128848067302078384989647877462728809264418089139929074269625280909036196844998611912609593749938532689971394300720891142592344861646716836970687948354491570637202236122460351485325306716881066649743999455485654480192004060273760384979328567317450764521692424505349790111216803988748383390720066980260279218433231707778410068992186318093508243213907004862183658043772114278608909726155300791276184137898667399293096797022657249150774627641437029624495440005361879770144581859458829995626009504774263711985260170520096832660771322002887744612120982355517590081738688725847405421561129864587995446463737211480432720474325708325909774860464119972758697220843513324003456797845007012820346520947967490710772224288042947534231657543111432852650679164744038691172082355144583662453759354212496012851790370158421346183308835598469487507125756658501211844709485868069994878600414676986512367777557576570002210573444022006047516927140581977855222254592567937576946303818667481260507049656354700945787716339487520539833753986809622051646159656347808552469030082543723320401221905937646874531182803950667719959028919491033464912133040888136786762728225140585783817241303481961306520672712714154462712626105603404604359260355262195533706466240552498189592879052089773410564800304295430217408138199176217620028481529678587359005600983466729336894791808508179274700009964185593634663745836648648174077194621254681170604158173552120786400132321552599672572493921981053927673597654430701678378250239148149316388239638632927659219984986530169337322581800355430412070578106437678905109749489294136238975823642624, - 74178989800717818467783326527596436956923106638607370086062140048306141249901327486002565585920613390771900770413792548808239568558412751878597323180323462825874231416211271171352432665626060547046752893302173663594301353357735111236423753750497191890057153367141068076056536757609674935442157620435886527915308981807286901636064161538181921822912605382764226003725163739016564857015072431143813272322760431270854551750996788368551573420400100314521940949221764757031136954975390935154562975942230201549597257616011939800905743713068817901533583079343293207014710284288280120564983683270198834300134037113563256690820729245219289725931623735217732928510579176013414002360221551736191833572004848530227917259350563125241882692497517788276378086884616820826881342171638587309570650897729459654540064247292000564677229722138264018347835514280226223751156708536027691683946670950949380237277321211707040422855942582847571110334504818089232978614987618740540484454343810558334407949419068674889799900916022310392944938006365486024283115332666959372370182413800994167231655159979298906850845291344319257814130567255832754174321374160937993914084878439740466265812428943783776099559620447585236299965202222887864889498588179996938034173241158454907835079078392938379874427340995148587886653292317420590913266880777564753269745948241713427015769924556746421175717893879020202212855624932912820233549414004793210701158126325436416431834581384916662428666374307171653565964254411494847820159269966397139695744197700451923961463001217537395989698223202486366312966741946643225778509191098384439575783912624069988972396360668392196852723659588399791842847312423246145421028554773181249190618190541777365464687007277383469204784361003339768974693387405878603845525629661646995449568351746479160858097117151823113393124030316781743663997738752088049867825481401171661389953292723868164864445299557772496494925804143326785241277838194597136511505126938853006534478192641537931674477450293943983471976648587815596734482882983860965042680827670280743042827286517910686327534431743765585861937232168053796871561396136331802534497731378761335164963841991015211000566993466830067842453470792469773444428205885522998786145732039347317498393039397542415773882601493255734765067186963876883896043864142152997073017130208886295522496195321600153258805477111886635879099319628438579361050890365493973387739368591480442559609737778160517709177610873588485134777305189521860449599907054440757918698523803942591854669090039585112239448633301042267741224677330906675414256481293793655561177342634289979792838661698141058753735648283806838185306480956133255672409430323146126461183114659907035190754686160265393075895677767925806150109663511036831245339800978255742472386244382513144108134407337858817507244673551543462643905324220322172257838356001046296614338155922525457974303684575828126969038382990205676152649553626094422085973307287520686594224783509697428416639907205912736361146830459178655826909828507456278300721514972729692017461727567135692162261135870279128971836909040203101620494165512905840692197508396320416818960816775882908336797496003670552545926733231519197793852714936422042461597182484809900497967496475070610717174816947161278184171764731115182570881111326986993349580551286155290321358218497796474770929567641681206554522331694704306363161362688475168458889527926929249982640255854027926808907609384228448187368561993498669187984862543568438351806468463337675903610760303748537894959945009153552805724043115874915537324124944567184746496129964729628749261146504227017404105522495904915424343874654212496875229862791870257070048590081578743117114286794233812150244979197231450453498523156066573986127855240381718261443833815148910800972207235114363930694276754191827167320850411218441528614798386775326228311167029130882313826178680181608836699493515543948261939635302563365059574347790019102185719902121865874871132262312596398824719086775287059645111149099655658909673389804854383525561296410238842760044961524858087587142538938633405128970573758951401467463035375212766685397205292315372970798263083814086619753773218643685271497839977745726484051560313059571213062044171889702170659815587720576821595119283080256912462648500695648046615816117918483529562821917833849608870533824676856008207542455850601634007061618502104506396248679984599196325392660812814373019318847750363119012645329036539784458858591162547491715720873856997802310206908132652481563917514412498943102620670220983951992025745460318441288212993457405570634486323453235607289787198135226799460144640176414804114218861519670519428380030922318162965575920488646362160928506669540261305442589620604941396506095041457463641660613333247666573381400538948845878567156955188696070299644691802058903421302502568261314688091146742914979517002254987883184151638315058588588617285410358005191337889258475063551612253298818663475934167299424119194950317714428647312919143948830290771091482720628761383040656167681446513325485013099973412194952621930582174011948001676941220692378086906836916957228474539331327659998880437632664896922021648308963221240229146727776319933612001391055657303960462784524001523815090313290267882487020081546384178317028800327679208234989992891377269025192942539400971026688354032930947800293563715732972218151517283225228866538596542297870423191874488538920232440645779013884146903772148272697421209017046268820987200135731850521094183753428991938135918072381149582783984874564300626590569466924700889913312589537560232646090629985708097273420886656159081884729452576224370242276454944107161533586694089217190617211203429963721961452572249771713386751983180777880561386574256753559131904820303159698625901396079066405782353229449049412016429107345345950464565452631939717070218618299074567935297863921722649984711396784817592935457846428726056227415632355233490703048505063634185059528772401287686371680806862387246053225316354735128359264767266140901119973881618585752275801847456132478498493636695419315928861824499334909456601757904414814000353112403888385038123266038521226577860900292446962134009264713446661894648148782454578419161355297466235703194634011702139613982371455673725053994599750316875429736536895691175917635152555209344316994331511175505816037579539657314272408599149471229383263002098686554833455051599294733328369567245083187692194529799374346483261231951710605057406697641340919320485443070887060036008840448114991147347964891845321601584105918396127354065622706540209379413283462927919639494265857920521274541591602199289911352493904020187657388712843189665351512662547177648900904276448320951565474712742774050456842131802913994681413280952377694085218676177745264070225996800026470070772288015604878457999625579972059069595246543548166868737151393427376404589542830897510954937933908594608246108321919408067004869502983890972826659872869051479287625735972744908463228204062072256163194377169738322391036582505452973724493299113774366696549302935394892107912527832633462838515792556933252673860108512471694390775997191143836423319996231831365581406057509018164375604283700110290285687028143423987419465395414056305523450067306946001880315354536277703192731312542798992008070487487077290088167334736138365648147637201746628791267934615010196994023989013574240097551436685244341262808862652889963084260982791772568658062613994736909999442241382256933516991701791095437544046499026897311771933905662690862827101563370831464145054533684425956921010815201284787743571447870353272294016286285610869910115826214139817069773628849987854190896774740660447994522224940397920530957488651970804278447166469177057295410692050353958066014505658384847872360719674178230896182715969388250084861966987464027350080235342660078377773105231054614382451190158082113954590635136214390971703110370395042919534792711174930054446592412486850603484524571714525834255216608616101694539614618627971565486080, - 4231656117003694610588475438271163379661479033867838223688879948405130135079853332574380721414959138493094093278008482442010967403270039100641051952909468322172190521724809862936888395130031261166927894399173594176464096607237741528642470848907101981341910249854682383320892941981447866791673278246788448385501345923052311997058003133822777194577853670953270305918121212634862240291079886286166626989552799181673669860971980664323869263820140917386487536650483837971110957005809828055191805142115781019282663289839265920675987541979689689702293086026819972453968988351390975699896661516709673984646317291595072964234675973543347420021898106891529160079644584924771961526236357370757905676165091662486451268021821750366869854417925359690691482926103368170872880591161214631522409419330799152796447016351545324814191109926484117115995561206988553155153168647609391262870629402557389471880772068404156510541757883075283724863892174934030716261473742107728304040328494120524575033265615282994780541526541710594699652680015188259356146895002581582952743088324858842564717861579708716109105562084936452021299438216072262910156540485615105607231417746885418962861357387885048990557952006636292117143143466838360721323819498390044246511891461685089265046727677342757006037275985065714050726777700420272104015466623698330063700666866608980294459898485665206804166717057168459702672603222343787935984356905818215726299571848411476093982363761382811866416849225221485120478779448188435191583095259714505711541965144595486439150972679516497914671891866489939713146945713574490319616353204066308116534752036734773752262567305297471272835004021090271484718183735051470897733977152389722502322102780471889210492766445337962762966924363178431475298232841053278469702841583655145507908167732586094598315989065063901532218078725143890847243093206849484942292032161107071710194996118899298520954901866017169249290787273572718163641734491595175861931945331388992881627151131039991585072323908490379532260304239457022002384579587106045757609150471484967123665971953469124208668629553011062888433396795694526322731657918750709691265067080872713213970917691418006672392118159910547998444349044534653804842749233904774226933321415745386675697366815974022919248309130896543308990364391424198462002956689640827521460606840129438313073732891203107872465389296083211614523066127008236597451024666344782663552669715924158186569049729724681891644457145661453357592687016058640254241965454689946147779020316759994724594192212740036834109512752758044756772909749349797758910959148132196310937287104903305598552954234676994348286049239006149641252851043414831077472537512625149201629558537018603544711415750944449514222043303009016426697320035955170929954326490393306452234732026325418094336645454745320119797147803118361552341772079343029766768825352907299172611447773077068659604696580835699005794182858939797796871353112131265614045503562634948589460947583455037415987749493134359570435094753310867528500286919323852387723489090751633338736641920111383619279784061600726113907792433304819540802192302089314204808226171413267685315379438986464932856307265329556414773594919587679755703144112682844435318396381683824142888883935273042398588137933747608794736031058298036753170571723220062830905747710144231937082344941064826551761352740722307065119435036748628200234039736102692317151903517794139761609051711426044013907847345065558452859822962512223945391913476637848837755731060235519709244399968721698750583187523065331084404299886207169773737703848490676449566120279419744774231011093487612730831303258283039716270744974617468538526807046021899667070589990300095879894767829230306678125165026922218273840540770869823969866337076188875540004420493401128565484618248380322126468384341855215446760864136292430291635783913272754399952152085360371867754835485821845026640819924138862481995183323259376350792040553268674853075518115204861594344060059750082780351270178589690624177086823821174458248112400701657978130501154063146580056317528502594473685170263519171104739805685328704228260457875861851534459091593810881799107685300351626969443466534338344251448459549948800201151218117295333092493091724963391419421270548302255776835349275451494717581889833103568820103639131431534535019979754516336729946950322776281835653700705138931526301690106442011489354417731740788578149055431910381339374789213277530001876589688914179745806450454993833896882015513705421674747898858986120423005820583355597862207503870687166199933954511884105384392498291490743878641460393370112829615802626728116576271181131020837811371781778249816403704167536415832810925149317283069446639822345888489054255181968605805836966534677941893242053247555467202353703221895732371605032573136726491006569739830167965356574692559241187699350068182349794564228471465174378885270551397647233434279720466196718929560295734117061898874011093055803468145816047176607739316841524873327405359058467613619634217293527809818490607981481655007753071099767962837490112858118557645100406941058924752352838013694909201320978744722895059412247710151031507117145948721710147963824296086105696877054406160847378007476139865262378246737328443116555383295744350061963396843972847278002857582312817837744802019573542294931226026606900773562220611686372594080645343648826145893374513275271505819955381851274874613383004028203236816982985876232789214142862117807578259914999434857234442149678988935952086403570735934644110112649467082581373257794046555995159294517298123430099150279435970197231278047247689838148855689778353307062128109912947352808750806084198770226127945179088723286806675403837043208594358133687282319898165132202221814288084211825358401506997199926311389224209842309064793808460188205876467251896272280513382719465328993983120456062445716007033341254216258806653001683557699992365483624294038211093840795477864274077485376068049482728861783440850855225636795926577626481669328895647951253565014926752885170149641592784866672960735930246172078123601216298101330923839326859246985913123157055141704551689001348649376450769852945538684245639788315971424127176069742895745048424874557707999810412519611598676859134128967334129920862502505187795890871120313426904114501897049436450829514038714521071225502543286366325027245813783336130674957759804040117389167898154400389413935663484278024426142921145547589221814473375803526796440854344967572977660840968197363807820914774225053429138081115442657227051881555318856343913641479065673131035366591541319213702865164152301736112878840684667490775793438377761184591292547465042530002194686057420199691909772121317964594882054972047006997794808857631062386831919928670653524089857443897922461289960585690601748322069652693043524359543795666267967506215088469837628163780509397902296315932078736663681245775410822873671000399203133913605409217122558835443495258088871571427470403025295700619345351156707661473829011156812349276634987028700353802249789170755505790171223518190380927483300330961969063740953665641884437382866090277235843302357228100261690762223883455633962974436849625014792786925933318281114688218233578232766410673929985746706925948624769037676609193586547022619281424579767375905767058676929465517822107639195469814364326490669222344913098936667981570314854375838492516641106746779894387245329972332597618552962069803323810808806063713100884556237034843519495836299836145545676997703661729433400765184302292785617967777560125921087508512721572989411376670985127805433567268588772902758430847702734707588255339701154940749107954663637575776537361532183106517751698082610859878941553921474984921324384373265523961416341573015339522740640550681940291912519847935935681178100764646661872957669775649325375036571633145028345061073320731778992725588483874322593817696807432171343118750766272892873196445208500464423390778353328794934245311018956460839416845863997131263574016, - 149118370925249221190656039885009065685655747268917832685480760962162729087997487081474702701217023214441361836302329577997094841137994688072735426874908167180256287343144241907137806849794384525020116103253477254090250245114167700214149877160416151209785882561453545417388056444335437453362698737249006041977012255552295730723888372452720202520324418885217020769920054423161549196708170862446526564410103150601115582731080123976592054090131525306746043630437633822240314249060940781218419718059746035925943451121555880730369119758075924966155475471767422081670440872277561246696763105037956275555127649734120141057319145305198555513277782837679897046451459434131225344895191484913829059690404949764981886169025993087636725615112831645828668497555506818807539112222112823493620932132257834814343501574503295849002444565283389546701042424256723155351631989432007029196286543992361785476411136704460572817863935977646722518123658807623164965216887162865690205770185144958832540807410260727311322174904388148389723428075358789004880482523808749057997760775339691394000723299567134838524982050031347456690705648393275409365470367585326454472687567939696743734376419242387881134433146298986933135413402855495520451969185860826917069844418150794789439213886279425788400128558025254195524335547441987961542237416636424309220022351291834825550133791614249667733235407760932799571474751692382304649995269263668814213498431115340200888341901903294515107744334145194448867042964105492980164047405508451007524538646981599188625614404776523593023771028075539925967635207140760637010103833889362657437550905158909653344122076823280181624253707982968548735951093652367722301940847424036682557497420118288766040157011110627294675880409923780680496383594788518615931024723170030136471894427653898571729446169208000969920715853306422609975683381674855595691903153133949186592944373092472264118851440546606786198221790836516613874546756237911113008023378247168010651658695910704259454042702982351804434498554886400598248383883478409506750891563657515363775628430767260779339660851319372637598214862413551219168670793026551949595014855095279207899231105526438778397643110677839535643326426969602140675529889302286867697433768290804864227333944188060139255335317577716760555291206227486953367141787996140930123976809872591059603861479763016943839073064301644755776970394347147613829155236757946052873474752043673243195400349597870431932765865368655337353289084251019488950116512649783674092918717711157400723992925525839969351066155248244372607533039354566780550678960247235858539470872725260468723284253502812700508559720239290090412566290562849766619587004219185547241365663566807971519009510488728489136170474241034195067297291854461392403380564002341139201811866393354839386954321288091747608811124333223152736439618951021789332909428086768615159300393834117337072738901533860894345504201865685939675120673370827599584494051938767226647097271189947420302574651821512407302531323443609436952649743601157376241996915152030063471420254877977909190167292027953186572179288220871044183840628096258236408561969866459276989310230293337775263530200854912922213799572836038998995292414589210306074576691353708081243713547044595869962620287301752800302954655362989581902373172390541604817775824818798442136492206045043638458079943910824496363547022291266005654396513713898619672158764604181323077925574542223010189301384367414675130315425433995439435682270523244526368769944314658547350407348375683228178666844671623443008863637022682277946941473052517422766179778372994721276605845517227904468748947834263208212455032817690887719937396547250609708471910309550350778631508679726537538327034860159671145752974373594792053323531329900131178582868505709964146832732701074539488505920998991665326173242480410366960755028743721631339421219687420577312629370082024085990756338034354750296001331280029546165666142959300202346515409802920346142238530571730436285662765680794774723672870302590921967683758283759801808163617280001973643509770526930071174122137807104261601768401417628695245736509290320063179550668042968322391933776744436743305338192859499035134617942023558098102169929143262682060976189875921526507664803821434539163437813035514184588571349892984085874623443363598574911942617879261558571069713321814584149154406625507089995994339817130203752651412743542485469834111910427964370313727082185566446903910651710018980499494968239449064523239621418889001292546085969638246838493155810412151998316465193231509467137935676043624290535935772329686089772460681392067547035613866600714100896203139685093820851896159242296327035627735775041153121981101004497992240810078994719446122631487675655293830845239586337055869395395196936240950557144257244544543245866156188967117642624077942944405220986401148516802112827984490106430480400239978116930652422000211826286544086951082537513262294678015304161537156533392553229810171189342775876086299865076306629248584840527544455564623985782741521036683145530530339461075099631109055757892892628322707702945057741212352000260137428215848131615810646697329366945384843441732094313949142700590826458006242003722104776057407507208641478121964622898437803849086324340156548342834868383211658024637155615494652012539686129435301630573978528634951536927985178257086341765785680986722799561350170599144262472239342639105344195331660271394738925816203273775450516913101111239373909589739576829110535203675464253976421635756068985521849665681529049581927312409653742461564538010100442148098378961727862682470958256328167558966002732839782013355926196601357344945243737887186228658077067923267962188942392907175078407393728146874820312213973564860729081139159650326131208600229435473195974269198273196285962434231164921804700975133201116902556942044806418911679071171026654341746665729297625444789462383151511454992082042518876363583463431521034453632380088635813757091917730479063504511996173188720727609183977307282684463769241630464486686356114929258490310839720717894024552074148766822571378797588089345046009721242835208986415398940218970147759052852361546717590285622438571228795147449894359943545916656490151846013044409646335741031510585368168043001714747545595307087351550689922464871512792284308644170584426245753455139073934158911923243962976155300574658688125934238765393380124902917857425938268358664916532064660891275738888812312113385481628288521891551186812731421545025414927003732819966068897838490836250346053910165199697245383866939631086356092516100376202796275499252148671304440724859386880743276343534525069280765089124812641042837442835599326256856258909231269075364976225430216305886527294253586480925129418768747589425072965764283893217098835134523908464688508602017018381391690095692203628720144955404145211117930420631637604312106927852212040998042436069755704883593661105619785172147176153071023397661693609160149179529162497455192682298068784700053234933132285993062800445457122393859962151856555350780309169645800208543012323349870334433506076065991407024254184987105405467913075270205022752628520385429606014133792255389983358702647438387827305395144868303512546047064240761072822950784506110764578036690889105189919205041799278061518733167912335946541499131822719344519892767030379936099144482794722404187298957694890075056021353452595054607339949751395001438673475342951479149487925566231965448498878415716248536376906558256044404407342160267567403181401613986945648415327067276854158740828550558411728474681581421564124504788748173601135079133090401807111608551847334755402876230796495131327765475812327155725593719571225504499843326529894668814131865053626137653684886366574707446601113672265050441102610217571339254477149536126968744009372541811632083487425933686331084590851305762332287471742742723200346530275068535747576049454072133048151529976213582927155021861875760193247039230568300544, - 3272861857046956082868408478745829608110052060646668650842195067473515654124332282164503175159823087287064100952928764940533542125943008775724110695339228051642312666042457877349491174963429273662989610241809018318818005281215100072232629270551303433002278757897078308138318824769848458068538293613110594735833313410145183777660959201048174383390950657332825148538283434456041736980650374245418027341143276971143118308134597814287804626386929864277444373380860402766225769301450638799645064086760845004843082745255950737302927699196120548859672374278446969144378601460754430533348692405174684869447655823461164582354223096669441714282240343715431816479999965534374445183395266571667778094233448287364382836801497217094683174545336148545766520736847413138182494299240131674703506711280781448922197259982846730254298082289715757539130660223406538668767594026186463815049318329000390514008741104631689001258253235981592699745414702191592345308257655942055528833960217068285796594188287378945645403151556750459489558680749670936897279186462068927902617641510930171980022728941915701246396741862494837964384358003022702249811728819587705212371600660253485914195542164045077611929147065406977026486335855946445230210287279860007697597689846289814294206836762805891654354065757091609655924778714114668762159479776840581454959380169914818599022468648331777247235124564851571291647958086463629316479754396308561092522813809385905005081536598061528480397518706347102181471826638595629123203367844734582531066466623948328162108790834131974331506748620031231177298765414208216880268327571292310249724773237648164367203505253606279781549499954684376580659353377230190636959767366089381981579960971278380447179989257034341386421181766122934800113249254514168699832504068564772053893011156421055889591981275165263366955517365925573124167208148413889132970211649032617386905900234919368297960380473624996943508910335629751371397951493981687094470631955867530794998212128576404418051515447508715046638718634043322208631272311922827313847325974178369325390701063702322970469778538592248728950306313186791774283862764165158794296159948186151901402190346214131338400057123867979597830152673361782118554461784228351142992993986777518467442540912290499115630003520285057567325935042650201861840817258478926335916141973358560549567058531760327815323466969179015057846716535844784975621033032009635732267131159272793734441109326916819425035981076281998978328341202417214194782913881066375612596831170360378566383774276745834368981629197131022982753663484203585405038547309204042450032683024328763923651533754622197378412792419293076724402893778823143650626884933648727296296873685945501187001316994829646545263211183230199919636090728152370710578223971047274156588799078378575106446729580231787884377975479842130395711599936519088005982501436189441284684555024302775122011742627337192775060615652472838385438195174045619211893902454407101416721266319888009019613157466579379681811364316941745478893734802247600518966216258175805678353653307486189298209850233673487779756286693649963519513031160698752878521307502053565182948913803482898525879016237582078023358507739478379998862133732362353550638324746297511879616853189648737996624410839839784928227855454128177507749577981903902928562183352677711756624074400167358722205305615778361135556054022539743246950769488679915486386585565502710228681398026306670426711979335901063207370150110200235320748731957298517823926467978021856566842990699428158553274460193363909472281188873659745239416880911559373903877004565135035596484080307252300068959600620501095885497376288805816716695424954420834137393291209532321971846274404076641631899796538644941790635387901100884878720864024920238866193161025932875103405879057084875925295704829312657821068962186507821458383209058449535674250454017039745723299298005712752337088365982563024323144080476251836935377219540480188442428783552116059024367197578942843294621844550739543063699803235325774110004063061793027444864275837691350999507826315220104855535468844282306212823396625112354503892662316839408663511846494734411169031149023780748226223521526371837673224670353594057081157971569782200323132270653204524539740972525229091066080150115471669040814060797062318642389877288863572003540390177509534822575222041492162270457295806381143855943648585152065744391887078031079613537666213058368446961020901005580768622654355021908790405156974355701927720173407480829271425012969162396830375893578091134293233350981498529360456992731950609328816103088125877464098777628415225084930471132872276055742515764215622155222570044076155844955947856221384631867388361913006969871882507515344644268829369182587339124913518735241343906267183901789063720535885840328557639563395181484067529820110954480379021427243150327672845262264184308506014434597006675703634809834781845628904804980478335463287274170764121549758225265415988793704776411811618981502497926664232465021084881138796425277625353013081735630035290748913100475039705442091170826270092935338158964828653475944381771613647100192457143333874056644608241970285700616404568160151696898219877714136764536862846823796664798431774223916218351345812705617132330674780562258726894334576602895688495238110465944956472590689130650402032172452282789727238735511540076760289219938822965797312204505472248060026972047951351580112420932469290515355361215644705884160473614559324503966755726915646573334855129240218213429017296896843098683489581909708311799423819960595863887333351872177934291875130094745965223660777722346166103772351337669418569722796812648486331898112452562835734811011311688343531864387554389723103151124345615461038773294574128583360361438701326585491406239302890164730842742502251602526971216199623313854844299012044977525490300054073438241997835598274346015748735163661982707004422806661058940693095519888267415558485393258382103050417606827611028407433834578809977749581366810919560233936558328402797046536064001420251691502422916057072669350664495938046226854777095007061319585401274830745467952501687765021395799705655615286976646319481647171951256875973336818212824136993828791803146238340751310073164973990274482265753381636046654039185222270667252910201529567000176427680464755330607693605221027995622165703472443245854594060778624596401175405484114306600157334265898857400005209455045697041620132168322410064061963632344511341236215386860544534711569365367116653010326107683388164960743505785969283806568249267086660589185343914860456672673824216692430712961408528760942302542579107505636493274633764699148326464842913123273189431795602055101888540094624175088646916107108316177502062524050804159009289490626985233339632568745329382146353720280990551088768214509060684498724991194023923647244062735384117529548973718682788670287450229537759405514424401735054911231024307545245701197737670636846723112171453521096717035188296546625116500364352667951034052723599063991630694033596632531736980235592471939498073336467053619508720827059664908082563599934192984837678586028452390572062580703572680162285738635679292615589516302939477567561690597938138142085694431195015092289301977648422248596618057860332719065764001978634452979444883536062316916161700911020445652952885132258694119180240685253002792839481910221748627498450772987855740973605177907891710618070218125084799489682154620103908671573269141401931008926011580923397447487608328903951251459751978577776257421696272207154336971694228205732892019220083823690348240932121277217260522942221662346701119386291163249143124976065135518720157276041733464465741744497971304697935439062149685710952912806271387547268520632161504572763126154440637290735080134390412028260081091795227216877413805815440652339608914963612348475923455561883534123044638987362846870940721583728027027648741936333898629974495310125479130062626477834240, - 8563686836034372663506925728549205140027943879846239009634025548234429948951899247153662429845528055767252837712555302245585604062188258642999031673464140926235424716925650550107378815608828870442724293726134851831106232826397386534117090982941138746786842088713825472809588294188645560765263739170811615290987835103179702211798643855946659797612811340412293774522302641157931953097593699039993549842241628431764495318944560536733675621183231528933741600135762765782102960703405090709728951146836769404102925496640831655496576748903750273118594984845420537580068982211371577016649688251920058704746468609866927279315275232542240974375548280502515586143083835251003875737038457293844083304506716756024724901673968190696427064419841606353267738986169179294789956082158620051477254135923091662104441337435539907065533464437956657794024856982983758652362663728986915800235828400617727243801645263927932926262638906966845498072950764795232768620432853801047712696930830818436578790736308792671273316224587590148132908657536638337996513829494979400779598025052530312187798756470200084514630387276936642839712673595453070881590823756410180358844582951731604990100765145044090747934981015684611958139437630836774966692876860281295336024372413012207369880866920446538067605400556629127113507699138363282888716665742887685084092269394489527496118329692095908738071204405890754416443659424080304882316560301031322492857914168313459851763984341373609163163976918086199615799852036127311967304463192697870593241848148233757076721719997158268584483989038554908552837024734369893161991783599688510954182398220646130516289301827308567067176840580075330165683259036620214985360239048126693403503689083865302638417726134710824287286552987592178778457442236229564035929143693852394402876730855795765284917298431295884586018533060539030996614223653654166589160801993646552350621621577083203461847033444409636853535213298502244406556611549553523777854459106159098133892303888276784637726218198509457611792532469162766599063292468075218278591809797590084660210200290044577406949857816249029784161000417540382577479678801024860061803878576329161413347242050477435206605543428455867666782870674273638721218469571975529757471438078107445455371107815810515940052683367660362130187600119957232662813774004901948837437819727618062057908598105307635325683479818085080664761136158023787224308624769027728733332044929744265114773289195777163830646942727729921787434916085946725276183768608945614774189614503266750387026083301440811082126654620351490886909888129863887374432962662887301926757204474241751606127013049494504263585621218122897773972830787119801444838005102488452243796816499769449953804970888302655548680871448867790272788632309555198631925823250599058946559656272576631401556943451475803374513037800698896262601043234644181603280381960026600179667867302029145235953027761786203879843708770038363611947142781999952610714593043882632832394998321082215713005159256291323623863556164589858850618643997632944721966965031899576564178896859540547815276719465805172768804918743003647522063507639929727378460262386557584905407591606019901690830720030449833595719752632482249537304942345396916642036355719469976731767212370106347843427336661360508339645482222817287850122131307749321013245211867755900999192429516257735642863936008669516077232797815941808839234912657330313143868785853061876172742195076490032685698110840383469385858902586614877745175864270164193558350864704878610993299286919178246185379912790982430287426840415931791112978144815489536291186719721822787119966086378533562949732021838545236274537158470486168504590767772560510719509026557754250592235676471414039603999339186259420215648580029796797298760923195861753784661281975277080735249037912640585984253959033035699734685703721756542866728480096110195195414497744555238688065499986313984713535059185973282887554845538591412760266827539699257859731282079893169091452532359320205031194810305816538910418384812579496862646672048924513349035503741145901188208388499601367277361893457632642456170686403340637507911895027233970556702332119197329950278773504247677295355039142882447431543644401056018098132483051267946745113031472478715357728905698809282030641867824489198396352274090805582101875982654924329166412250270732940989334415862349163904718152827674603235652352598207957550200966152661631789771502212834867486252864771711558346368447368388888816744086146466165797518481400188826672337390110571347567352090618352250981961405864757766474056422179722796552421548719968747595945967807790329881304015294071161463806390786556817202442212543336261483658776499534412071511392616472659500658654856373658014973246116899044187774045169512309041759365597011598245618693384212298454536308246688061662572647122885593807052378186415764977042956573564451109153599331678743804581046845094097300027883241808312110675788840280890207311041568590150813590516495195219706328740131017781676922648252887589327812324136686387221636881595436697205511666298888191009184570064140005408021080941539188443269740172756339358074288376444621905848562370150470596031348839763532120222572542972008288087110507035658328689469954394574114863937032809484529839423824830214302898120841242479873613854103821102026698925910392242332556295226103254743750670900523061773209713802776140822459244471585347471346441631319141771940593962772237973842200218034789106749463498407539929754116162069574526747031404561113438385251678007143751596986545953070902129770959678110226923039945055198568451652746438096342892417230155297531377117595396037909263380127053995957670702405448369148538472919919370811772687637830538213301676490786543150432335710245977178572260349679708657184155864080588862640083096495477294832275905514220391811706936515728861099315779036330650309151083387593726617658832446165465769292484136377795769052294159228239029763626088141161108576884632238533919131747107184226810286659555852973670273847584162960626673806823646233570725002504599323373806208630371795516959773140431754348412054012932215838146556137320279857431778529770755739737471181300473819117866801992814836568316252483767992690872886873990024950386360479675566662746092571229944031264616249848338934091451273078279132572827580131244401998757968551536200341424819409866625834083477421744223031164001548847077970093055231133795780076701081305473296672481338656143110554755258246215381879131411944618115930493737861780799447976235246255100748258970840043829300197295649918865835631145282448935016846405692435205566357431208706631574118543216737235929899599484732180694979983410043608209939943908223733658749938436024145163393993004177944836749708747998034261112665914150130028047734289054047706529548901355256343931570059731512081296474978546606328277158063842439846050988704060433207939083528863604505759018992659760007921000349000442334067745347580479301740211617111616961950315620104289355465223850991442743258855107800841025260562974828764851101324133384684311213841780215291781286054709746743632335935841115221303426961311722072501747252323321775515956188961421928074855182361705313535617060164354017222679114247251503628291664971111653444390156968211722270835440916136429389277401112801967846253211693934283861110342302150523854625144043823427654180201611498135689125692045869312117408738396678796493319273222565653376124229007325420040710699508030182681919846051602623686820261774744297403759325514165146142357343609399479186705923339330519800005453553829604106834836992276935641890957366007882494341870029361357807934214586961017239017846806610636547319294440005307871812147143542877673479496514069446695140573515528773228991939825791906345700329887262529282312956637063560186013640887360104042348283269727667768447124751621105646666135737982215982997816106171497349279406241238482944, - -3043887612253105169726327045631219516373470395943680443384714705842400161999811371006577221932010226878551461029335150403250129129520456695564648347072276493494963733728404193549291765961179119129975412697528124858157778271482740277347737899018290703378218634270899239746625393120159218659500969241482484122979795044232742844448637936254955144333514225720280539470709157611478911911235668483408296275623224429407471210505990689301110036957791326080581767835208094356280515323734456553154677606490157059782761474909377232244012672057651869765923982011938811006088758442118673766012578605548114221678364711407956431330464320748745667806034714643167546392143293925056015713162803165320714871235367670570016659036480628507971496597910524070642370682491584392065686932294228598535589637190999480300650207205728177122068900683839338386802316289404619206648923853925129354011042638685163809931423377297117087839630503725216287604118429570550869837443342378181385646571287048206892273346042523552817888065327558796457525015706966180613822463999903404503544708848702802126546049906367718290852749497077126350871051405017559399599964013512646933921677114960653529731521395877924960367107928310075300564877285523791385548087515236638864816858778792496024237890541904745099293830379674378110998675788148270896989277655417306700654308416467384449400282512078892223415756409277961856194107753515848782119783294267355563291299047410449350377668635515663252410459211073622927099949882798092461293709590903581749639618245271368927654279607274384082338101989113253906187177334626611727350121051221425558480753931313693903155176538537380501042973417061598678927351006822003959500084175240367615259372645936557553228944199327973553388970606323555617063728995784688538363805323443671414805644475603802786484664785550763308641664857162764279251412480050120207671032459897763940685907880846619887588930354412385987000840043776177401963347212981777662402996307719847668846905796462859907999395174195112126343091250749107975055503544065681244941362829271569550364885046659204891772981672161306009543937348833003841077417317205534058422783511421462719152045020464057793989303105578900504253372347306577792013201866424314520882412329675145546115944981535440894743985161430882568601083074992890864348372577705450097289022947192899021077637648586147503796379913256722257509219765503896150119787035726081028188831935289261519781649881252666109959135344575036036768684327041876473813394958349783953855712061220648017419525313646180234026546213019556518429693631223935045619832456298193376751989463256892979077631177540092307310493045685415793114526100174139672149663110302907341856264355348459649057912179714056559407369870122155057379708736324488167913362629632085340371464619978869423777806256383938039461182695463806484280411556589175707373349357094407900870855841392741859280214612192883394426760281435813123714783202108250409507989212169608974595183629520879627999112059088911614948470938200148591945601792201689167943147482253943945042713649393097157904328580580539722074411629030402113829484853166225439687471455053625633964356508983482395579557308633148251111337060827531926184717874842491421846493975357781517737098650942982375219111103606656332713552643356892006753582576287573894621009959644405375967540267033589082044293760375803130194364141328570389872037996704111116278683454695551261351461779546661070848150685254712880429713139413049680733970512116235803006026738610782968114938350016787595074408037707441420288440910027104049736312831395230165942487816967952835979276272681123140686621561099834308196381674534097989154978207596438762962010921805523789015953414100098417683522388963756512246259384738859292796084607385783366528770000185037091472048392547110248626379894432045649576412157182214679717620782383451232377174758530994630644646908694738929921895250828337156631419488365495036481241486008683939000884676214630178738652662692201278296499879824510723971501355093983871558507877968669306892819475939663182178621715424799585098846534059295465759665627951321880365398631573720737577534054893069620152207868317910493497385101231458635513454761228751796097282863098996996280679245062932184500781289966247018524073997595654642034196732196314714484620320415279690879965817577669606429911150716856309107632594690124442244802306825734098505754515503756074099977946676961356043074499607792390391278892136827016105335162451914250276941259586414374546013235712174269231412682879865262697478464356356763232639020615089980375897097247755827262459265899417319321327985382251916146019932080750114724153685609654192615425230722464999727799821869991098108503986096044924869581265843418966722721936078942458906967331303454130608609061479915749004939147813982727843506704603414099666497931527506636096994557166017209362571309871926025270408273819274021504064576102892498841631397558316710055550954204129769834391201427234668327465513267000063733806120167560920760828395379442401995301171221671575520524446413066085427926255982088754023307100280182837819519658679167228653787494324920214379982597389763724859511163854233464031555760517904402294402190031924257489007075839539343835594580178997456058267603558507866452703396313027791233433342333225966962200841858696180012021098293807948035417032230986720881610043767841619168359602788108716738139595558984905260346219318189306977918029209069779558850833985302928261547418158716553486935851776432106133041223282776081703966174532080449698657866270952581370945809013982208899219681328296089630929526394366923892227981109924660665326436613160371385052868418607256720917110506401130184873128701928496232890025645275150511082626607785365295103737639490089736705322469888591935422268034228130128519532292829392734495554412771663637806499854008188035577410281768046161550524476743589934882615519134589562919842016066169489249730182706319475288155430036897317507184882857377299574991788622454284005273452346955448992649716014206765357985893795464693922787631762677900378932450860526532153460859478179484424556718311984651027405502205533295933098051428944645486072106078190297826742062133449488243176674857904292096689264886664693179566600415757403354060290526792039996335811548099369903196138596738991287181622955204852534507817944213387995801221034068811380297348921215382201967506363456847205069620588582420552427533796144390509268072298810652520433457665823574336651175910699680079736952780539049514018555073098702121192110120021911757942602873956011744096822414586870651826057835749791114763480897985216352950651516466604620347020359244492797799596630546374675331532248150996476520782282765737500080704668808663079666849991627754615438036667642130229367769014211360416794930709276435191719915993341842587854881831427205777958486130690363974608584917620772196097445171803586739744308221200508100335644295507738149252271865961746010208039756856661027510693425236126373326326064356787508592642549937714991900073778869059641678397978551505676339707248129496671518973481369892389743966556428340605616081449269497654256803632592101726149931376532472889750754979718958958604152281588732405988026489570411971564902773321257878362767685352095948289728609366707558944926599162784351616423188027642442393176657252371396541112232427435075817918887351693618620761162575486504895735482247097556564590378954108979440786673667434575983997835112076385776728611363229137217607198172773667341804682315765199336783828374916185101355173871648601090255158505835047455674732549749955970042616777846509275688885521413732049073706438015026656082993983022118388258879945026030957362957108755894977130210133873479799972155167388132803454534484517007349003198701084476377894068453734066154691451401288667000569167005430699128756785023440490473563476721664, - -161315524389003500674453179171482309271207160979073509528359799362667138801793976807430673986164393002599044914629911221536366608440581861433077454093161573667174179395044477651695702201081293631373117301498922833307018261474609703080088792009572986884328299008125983284210488563595052716089785730134808506191646538672046318953911400705513381479098745429995662029910583154781624819031781763597252420472895337196839254196998619495910876622037513541173600372260152237805420417876894280065857785909906065266506725995069406832514534785202520340953503043214187941998735117215274832942688683889270521698941630837698399415314827830709007217925148261693911652599467964744700240203562139310120955262818515349943481799534248392407111783116482921712104854287220161615446012267605512258318485268822555068838630764943722698266721242976263151734172113030136400806485244338273554495848831277543983086971534395031916571343493592417574903326474897859858791680243568587134035946856501291089354251921000392563007208161291633402161954333996273655220898131251292182491058680632946251193986095046163285322732179335024058045869011747370843496777493690964734830837120764696143034115488026193520351336152482542778321814091745821439045663071063238250114511235646230371144740155326967053889218341673632895739820789964879787040214676088134193380004465565861446672635757145080275855507323823813404392267600525717455940463846179821218488385739738541593692568100876830345039232764552169796398264261690992535718785934617662225709822031190279100365828018432589979035059908354175472266448686371038422414843788193555435850350784480157422075883602910461133189804443182679754061855759786076028947681783668616187529433995336125280998014462029847871850021433870046135459287192630857304138266066815519705249007011676237303996802573807780578621261513606502680516954570660585438191154368071261099408524537420162863714492633803079703701234485442104206507619142417551865876894924725790421556834077823405410838862453477507799370814675546492465176147957364036681875934815168703677170937974866581573508943167325278128494411688241806237635274767068159409791161902130197965781939216162397670102785987055226438126269192787128607141919019149106324463455554064125866583616371097797348073592968893102606712876611623645802920540933916957342527682152273796255481330394295126908617456432878533791996151105708230603677115169323090898293116177482979874625905952604973720048607205997449740351139700067246261892233338336380565427175495517512474523516519960800887082637884648382060163115487532933551900823212379008001471876968653796524135803171386547785694276147668607024899014986622537999057161042334830360839889258868206282601876743819953009857568072656007167652507907464110237863918290997447677004389727509761072620677214760710041109224257305742923503348280250873032548252332954624337929587744868206836123103643446626758289078590521518036308898565479673908665059330216682431293553613293948544584003357378610462752805249725736024720874875383408620307213399155539830002855313864132556535712637100223458111016169565795160674370925211162255719629213989907192355082465845137267227531766470702950709985387284891514012313385057217824118327519441856207527721277178721016495231717955529434381724573584140438092088862736189833776797478005946882290029476030316092685765778026153028145590379847949659041484096114251203253170002623316865708955011881932334437487732303555193032129733507406970929150794793559916013690147814739125037723561883037368827581681570550980873527386502653895170001101615882682235745697043967859360663065337490142322845955237041925417072601843714381272386508918125234401496429832656930877781575726518442276671511948742033420987462091812745289897946027722332760941510170179225849394850286036248441141104221692106323149186784206420702591100908064929664392140853243709298326611579148054416142635536593398164287045152674805100528583952728709736332095792757237364310075315058882077394244776566024368885934329659334698078197816268522784120369266019692386276570220990947122191169409015579210698955576972940574044617028315972669284348120447920696702098667888011460931819750189109983545453037937118202524924950887204027161394107351332391477520484236212594217177698132331880642687572982463286527137417376480609757391160287381695046247019624905483431791293006639094264619030252005049674853024264067052180472470662471023808436160921349253043388311577046517906070234403190809966565595754044862542637770319452015519838178721410289047511739562806930598466164831543405137284637637446600226963797551777145082124247752790521881740211959620544488901041699393145245781409220329258324205246917001802606343701015724019634954167243025162695830749685591431838588621591399461432723396565425353459525664943724349776029568615765007813540734622069685206281772167858619292111631366300594963836531321835146169947244418997021270185638135234163878142133060710617686978997220542313013888226310118213318411596987880517115451464836943985377136566569960907134502784574822106317683190959274645007864430485133899086906268312107435649944605863459006035258627986659029718868145620896916399735954563825261961376922690646988528631827174720405508674750524626266627688932188420291526889663014467117276656608605003870477171824640160601475858632102416721226508111179268766140644603652363600328141859402583850277326260316960916711221274427633152240500558724238763494223297131809301125486808576034576878739290490324969467247322201966140479139322762615888435426824195319792702487760768460705853911665960654327638786124247523708272772713022413214295638696580233397205765714719224410273276111602173231578988314297382551237663413667956946509031381384516480062877813838767076240793777887498966378598555646970483650976862885185176896133323136589294949142430380992124345831449498617976424513399378033630251040351534604549357808791694847942520466065081047357855428572694032531811900929373963836508263511204795478976733324640721511552625883328589418372081863193601348792594602661858626271187649269085301627294599886754746491347992540655642959804249582577726839511528452368234816648503608421573633309794056992969840003253759667712073346459347062902668305179274029012211099802629866731893711035718325704209463559993306607286161342635928117990754092047723935808884398126796014295732036560739991303401968224037260461779682838196801554313727083924011073336887968148905495357475740263536946949267294812071123763562502762928930774065282998813011292479739301153285865167085995364832848039618724000977775285572540895362452401137254244470607709695745557669958902996904624086694678008174629915892836675191833032025961864386175105531204134877905325149664696810029248754636555915307589765027033755558764809215573301218166819627888627275488894760058434621771367378498443173389831469647330184519409406937646487770937294226923394711307600840644635487446348140475936905969975782129249039738155303958487599332409109768834164459605788809843039835633789425057388599682941608303963184021291549581813943220428632004110782468623394682487418850725621346454008499199516035681426071912548029799124839246668521213187298620824981735140969618398959624234730980320963762139524487396827973404678271269773089921630137216226560309104852029917260122553597360825814784216334024115573306574105489740237208507457391566080318812574117654273527304805052672927337561351300520846596406634212421079069757491309695784986775172355813549569996528687107369653325422461321626292441441559032331542327794112289374522101329801678501100557962565326749378086065943947747151944178572253328207778548371534689743876797513900174752960909084936017551328603617729518318361804192255309211304431625531268069956153473447006853916421337203088819489782154661084263389219681291819024384, - -4858441225052151630668911194957010145782548421678324638243246631585083995352735907234200016073219446568684712666938137593386027312386214941891499004685701438374914309526919628955924765359502142755267165648353353387314912089348242980006264181927601430026195542936989625594365790609905834756465587871243594497459282145966457847074752305592622650219725983768137984711940084330378595219030691457499508075314423953316198064270624092565440756883709513255824523190781665862406710479557418685718913265165898537746195978371674170670335971192165330864979676363723050647939300168427055585939538953565432982287648841436393528514422128114161988601504195237394782139366901319592816361119451267828583382228034421609236016613865793907410646463819965224231960689227052503214737206195051370809684169946409152854432245779042552244047219981025082235430445848880364254951493776670895804545744443176532769637624008853947112349787319464026121142265820456574057677929899525441641340977461366082590624319389830202192374948574717744670547035581580570759749422439092334513498722615366377388192025926369403746708361577495501872627540366288438275873819966980487375614801904100272103713212356450391323234561899725245591576620146468396658273482379723415873920634724167278189137957105991494715347740555373755141298544963810771203191538310212127125832826683554806374144577702490219689554784708092294931589091304772667421193227550392891591625218030781102725627298823899536507138924439793742170889950870780954603231892935887679486275459077272692911753943108158421769189684593441541634829210469261026647266832460472468009277413637748295570379841329697591124181769593621430705362447769453502978338568176380651040369313375425422873374634306591809106579679869312831633511860947394801436003983526358644244590325544029117145659644294007029072864347670683149779738408345448464409168812165525504772333639722553947393490588687465818498253217597525209703811373841716984636376737786258353672348178957978724575033678019699668765438723429857719764797501242337221605398597329736725368673458369114557457596404528409692056206036437622148829755309958981018804462592556709752982811676843132159677453010492540466386497539034753239840582611846601322433161788759233593301718201214061261818956402713037243647073843256179822686855219155545153163885017873507245581902399873410456414306113940014156191881715233457818556615090916996029349849380619176520794994897357599652312614317326585349908491531737367362524400410411735545479057763789032802048281703405051655849339673574419214513231126351274429292967220139388317442462575407714084561479590327245228477723414031142914259302456891734437558939212267825919818610972127143039257588400666242701973206654177543136579349826280686422162297396870404155057482743841703785823970236050740598302599769993947278009519360703014712574498342518953361917358656532310654396872999088708388439990583611236629900570471803616119355403982310259836159520838487087270490485589700182754262468345641162169977615297984207202009944011769583011709366003921935988069112638416260038233772200873051279220447269484538863651064958065914442135535070178205300283432332780515092388644893731240648095811335616372632526102793793631836583439870668312049272707323159053873205402571505192855568807104375120495969498731249966465674757572314492126341938167583737265628499627754232810580482205941936305394193905862335215678247739563784603835286885217127819511038699323467326294852553839688863846525216896633305397636941274734581309497707865603877511769542410307870469360527881320949748292743258845200325956849289575993529515457549572377767679344247438570491419429693822784191676371870404651492871887852682666048872116926015604733318069809151146531832823142124832729491416492834264608987989504616755901315902856966335350305250991703147559027251048031801350238354097579425215354594310320943763792855252209964374359344795177147309274080657966112778400264749333525378040985009276690618526892375737484278052925825247544639372398596337212921279705693981196542158151331898234006520976799329543968346125883405325807591954310523183364314251136455132481919628640959471080267720151065001213082346260374876350043899503539576627579305889792705060989562112582026497591532374511797692593843385774608067386995767257477839538807405307128072730695230640319775939210559793420150764260290099944607347188806946945580008114738085815016985215125151848005303337725739990438041919241517992964804045299295286093466531234518094506080671287147690563726440689485255306737242083097607183224200766467056193077852478254665111577237847880716136625277169906950172785110082326768413358998221219488860575463696114962837780434557945958445872445496441246441061771572516332315567298352572643093739623488854100298875155865606542371083560020872391449702333454461688881426288490312921279957283190231477807644786589601170007221407311970938766760997706192123508014980845566726357247958865190252901824706193923950342110932601698729594100122072321221047054149291185815961102610113348155244945723874652421980095634285785196769039535960385079695262098229491478431336202061680068389968547129525398339710471327586346427927555444172220132516436708545288377294800740061466947916644164661674207805667373911471758988482682812344513630777034917829309352299400476200459050153776284516941563646503932630798360792473086358933757837944136475835883191322399635802959605179790584718508588176809562651432246014319616380676358134046665867766493503686589809073054627454549850654448522262036323776063055171477182796221415020441887310896049816839221076294671333275097816441074904903273330053711499693005883534331333426689917418642661666329393920560594953127802356491363111542394100875631674961861438519923249417284849758721708418909522702180652406334949329089205001229602463042493069931275200040152207137338780633187609871683184245769656672748828554767609370944036555660699606600396950853632032158340733478789304942936281114052643630986097342997801010901926962781281896755500481904595705945949190413273829994519209627266926414132321712386630546168604095000676495252601738873008531072938896182125076580960259836551131937156315769487848342340530988497162423616668973632930381462442709177389484288334339070658990028120391746778769584140367023336642572112900073374367946794289986697351432520463291611434693568921123240210095714130655276272938378659087472549455417063410844121234805620554739500750247566926990683542012680058274749351424116722202223021135711008716692665296770686631595827316066526933317319695767181094475344076548834870191453862576735406441441387788581093485639035092184078716424753338474777919843532385791919245176248276704782025614257366095180398090852424387555668110527056655448879770525045220294408970940672998736894468776868106630297694798810837852307147698864159833929839594465027498762348330225454258262131158251266656875834087779909497897985523327497538245473069398922967065771977494610893006817142906427153774554568710136032455981148280760299385806376612946709463459984458162581008427349628654448237248574915566942433205149450046132909530263127137864253065799301588878176871709106839277012201384959754648924271284015697267662120503026402959590213881680288516680012059050410123220354344145458824894141834711254070297890682271934853872608052512737029026800811005791878440184130048897199758498142407457366391370800976092520934227880659512841991660085776952762059356250664033258999633252087181374602050086262632009328471587048940122259538187993780616521862942619600744432771068151364105795238912527273710705734217416706973010226175416481613904704278040417552574587483176391877800859567915654136374694491038684078556104900083890198541226950431949910331100484297968113807531715881964704276414464, - -77082351901732301027662753892499598291032161469859309745877222059613575424225143007974958141402475757121820555954497341406241125288428090990594802102103580698998518033010170958483483185911992291795115420892434740640167109178900056149638055643370455720529156379718294936768478395509936477058744275997288928494094856265905337257018504060302751327809265515655227076485580635748988630352502199964142267597305288857294249463956543563223552648785078760975725079082647136656215026861039682563817111470538464233815102415853214593587934166306610017729304651816241990911194875469155494697699418861971818822301649902725681454540633914972338598124707113937727419239716337173920361219620483634081437077473798161378130450221776791892426644204054961692525258241412371837372556974083082719273666592893579120589765830649740032725566672727301173209879719532932440978976567967091772265918843314071224458753383268569656553987963343643455749073260990869596083825807456482559232705158005406180558661634251673745674778955345021331185893478121929322714428537482392715957237893284789390151625214083235077078884365048916277196505868209115945040419092725134519081359802546784752008613661413849769854674453322048504059645682963993031127361231702684971760925197939606133518337316680836472446289181317371528698741831940639527166383421243002720781432768569522273713384053070432493751822497692152973739426345710548968990554345430513555590651253778906196860249063595808350899582136564012473612321321058692977424051904929874112184793506135349936336776829676760048444093277861459599704447619064180661696011471702101500523851883520000507533230198134049489855253648448081263554359412790524129672560096986895611559298999332068064438810919465746124786632557828621031961092399806048175057497160239306523614575194397140402554786901225738864483755429753058741353359663789966319220057061251976555858292050908908567580523375239951942640209539009167273223443647100692302777955482485796564799203269558262801668831360037030573408556398301190326623767654949400177209333535507147202701412830490748742653187438557717275058505503133646309487628912126340395656541196111215633261750840247612368818457353748308246754176072112783818027801763225646615920380246607290601422212626394311113197651176287836389963325457023359693430597403874498535258478358671655757005152178264484830781371980192695361759826419208578850121741696238680979968048679900428401532740842185901384679834933215514113916384295726842639145769369551734099173589261856378125920707106980135051704691644944191661128221293579621599877694074204404462773539917231517782880501170318409570263507147507947905416108281601226039760146434813132958156389807777293884462938289516881149077600883198133108963736164307538354757948774047715157586719700688473087401934953253168783537586906489264526270409851705995654272532555518272828015013933501940910460215362982453472645384158730638076892022793254796614795650688859806806269075158513720515310401895474729034535829535917382751425425140833214146144543660496648946150557089918513448128746725985633656252390592179571545569729929190313665527700908369904440544096743423955323811704591402458743119288870746539427522903662652376362026799147781809901639971196133286312779646483761272932788621178482874484633352002449658222996137429578865761934843711860598155089378651836599167432812257966187587758343405867268675664920399835047567841196685024067427615924285666971870542575134936825212361616096831683337429829757720444346121142525886277061845611154917949257298743152646518041269488699097299126947751386233210428782749003842056427770166345230449113093610293761402341625858653572612180787459150493602664101481437507853434895620882117980019323829101008729267453751367190136283084807099425916833301578378225056659401060592012930751657771829751618941323883153114522517648942558766204647226542540280605231304830945184674690353279150538856861985511544345484023825216445828498631770709200174773744943861149067500383757443195475740627281668194070723950618495660760474686336145056858695896698268231364795044781392109785937272430196497547577132973308926212193953624717112396786772498106144698231896849254547923512843613528381417096868737939989350807408271342582534447123935361727420471345458527442429991597661627625140578528333535897924139648061916192006636713926583561432401802767391222588696900923295777970462714370044714083467412282107824974263933503867641382496788384477222530853465201072471136690834915313584140077716851544684835913340494448758511198654118892866562470557668746507556504381673982967344156359544437671383244971175387799657266485112049301862787058145737456494943172563856034195139092228993356888413105771899672856023118942175897345755831043225325531762200110346839378868241205748400639511066582427888070730269992999354466406389018942621371897010017547500289415381794089068157959909108037676478845787233290497937449241231059718377381431640624790797827985748717060423202198580520402138118871373309839674920964104199000955344905952174655964703161015978411229581705781380652194519648221419567975179178210437960525894414296556392855183837460310268963629921027718177084983911423314664864139504197646342141927381932043977251881336760780046267475651156222058241735005456440649969816420964012975861504848915294468387939519869389677543117678545782416877519419434178985463058046054501668527939732600290539506688228386602243413477097361939938709167159226223300188130888683752095228139108856458081180213503302008673372808440061490629230470911380156050983859344549371317966341132908814796092861698662750031137368146095694729678669515557973468591748885466473313309794058349031528148341994767695067536341299784222595156865749393174570287270233796571406819713556832033841086982945256681650743530835106854093712019951069440758734382969632376093321517183659533394452044938114903077155337418234571113049540636255029312494914737425310600360314786872483201290445489605848888339932704574389822536346370014883094971392673574995423682650332995944132042580157812281812823587085643228839233096170017407082243027911843116863721757624464917056092462500636358792637817026790911218279899635815608599175519315884788063157445680372495012538796033981119593955709659774846544617167017437228488432012760705806593101573864737839783633553835065617842928660813236187097560775330619352956137957644130570329213116521984042716425265699504733378598274881499003675291921629477223785269229107525267393587250724676382110636017220249083115090790642788029732380712185748059747716775006486379044458360351011884457655389091910886889487597260434829844447535366424631044053133541133293504746727702592441473126192812863297514806289344971656187960286841750250852275339965824399297038256005637326624368020265240343589233417409554713383485009446362169396099995085719729145953449019971779655721405791210860070657766941527631108456204885489288395513092384603651887348433192746077940819165461255376536756953490684086625979843427333304616625925975745909459721827812750220425895016157067359485135348853196724138469758650177581367659378588062535068584865957732752581814986234757122692836447439529545559532951577955187456445875754142511707723506818606683727277428443375484249607476685073500158602012901268338177572081331174463003684289078320904838309951922045720305985900059680174524773854629054747720425952727702689246664983992131580614424102609542723096963220020482259665076802741166452102433925081974937356495579201753251334235551940328057868993072019466899346651008614740856336173023490030114554963978323548721366898170164546052510479914885046445672765249357043903315661737666347825486539972462213226581399379452074848397748741768218952749556146504080563272444613545533898752, - 890028704107678286247556663303879653992562124972030966928299603356705438679056382968919965531684712945497319143068526000316290248201028760212223919280984473434307980042320851469551402253482156263587264086372747024736039949601830282521367590083252471548858416101134682842470317303087514438349804739884080827293465230713310941512192305641375420713092524163163569048812161515358824541893969038703621370988440862175708820070102716990416817670434683778510454043862235110442014924541628125612149157257143623820699681364878258827783738560466783072133458799276998161290900704554677007062125584519221733712430902705329484150810306212027207611204314581908694155839785667664934251960115698511322933109427814397699839216571407777684275356940683573660103492885203008682258595455658231653712593872673275722427480686483564820897497832257819166563587214654269451399824123441622421293325806381180286553771437241015931902001234156339313504139685979590022322313272534937141847465047566087432396608511445936505556306298424472522805803569790218289838668150402653688608383989961927352661662492328519118335569755128124979513789683067607402247314820702192004811787719116073107055381910340553885607306538897008571728159670692446682979719953764887419734503458081735826229123628725618055882021592338598910786994380611973248897808651910593244634833359509625978819340461694238853605824173207205313779734605653845519077302573678006140958888157137527974353118028384156328457372577073634246653182908116608223464885193542934281651112344383966274014331542769612935296789029451452855803642615115437262305101313109296637482769027162226832872736855329806942951601511617012851658483197040025426551220568442643529598641515338527186965273323249995133650766021341037873695206647304982312152916638885788528052254941603184948677351075410755372763474989733079277014209112003194763792838874110764624977637365594891672289641048803878866255283118203501605836264453307023403521458829422587648681566843564446929915534019311771924196986035081448370851087916508296281695018062995731586999406315504340987188014180918963184671446302250495965146180951560456880470928256591550761301267832305129033715133068183777685166605668777586034191419460769953097969725645476735938836392065056349671111423285703226165916919895574882671931768216260051068742584171506985436933881583915617347070397962035372120310547806664991261955384076973192280781863444829266142212317503196699986571089713211382453456749816304970008521371508993646106342840436683391248048533459014670692945249400601571601552131118942167965730262171007699610981263794889655948162049724676258251257514913060580797784308821333358978057115379392507828707148258302642358847534468144920002887203297848560359253763114300448149632603133431896960146217130235770600657129549123038332042194975211687719858665216035391929916960584831593127853816359472586269545047573758234322390321704656518497841483766115476041941502576059408436631780153245675840438092726124160459598926746801697954897061592381441644236382000382625140403296713020017741243991666634072770952426307316185078575754965560549807401189827150177629104829352059992769257727569286239636340215543409309495079777486907032403740016556902520161869440665486058902643684376275271751839381950141410193527255498466923438435269841953834876277782931658948863235582519900818842969902842115991653176924665577005981045663866834120816108664461932500596261139332771484413390204335299765992904887703152777261928309740361491646973134446872841262237744870230445161692831316903597048244693677061769748921767921308094163969082365370492848061119393477090466856388123671328386403296400818478806489573556067695446951118177770808564259798851455280007203994486564223053595717403167455270808440651227524246643403928851695107444761789263154794191495255970352771362645548694079250726465545904558047105977324444754412413675792526031489476251509018091382894149574779191173330094886464426640649052525217308557073187859542130722426491331006388256470567437321969234357237381902667543109419501417791596949477592354822918205851742124874131145787584858138051726439495383502854450371306790247012734493192391546387590291715529254009132704103533630545578865376343294758709147993128469876756807434429710962685912226652541885687799354660629650226445094304563532964499205615914050770812638473268320269961271799835732709318356873860874013047671947595767450836245748585557036214905082568525415137211918328741866064649300816487940004111638486423419886047594329649961635286780878438007121605519297244164753754718283427369477997796914555858498828678965047212438689966776340324604671309911681583059909187758710839507606939921706784438631875892691059462658765484619458329228834073334867242983044647602648259596998143201198815215296961813493680524953336732463805114662125560256347133689842398560286600125593303192261067085522944902586434664956967277057763212230373536037089096820160592148656044190010986026253792097457622786232658746415454148186520795692527866919818578737249579765488676547031862887310402809287518295146726072409013169437200298068235545521339591156497128286309685004345860526322438226552122286918927672080073679887506889167507923464014445724021086525099420941126736473036490444842103132540494364393627448603026878036001562496043202273417049596801341080496078135023679520382508730880522674578940564741044638602875388292506737135253447190928487295174547317210182660499172698541461832746079299823616132444437141260136669279157737831684158461228024334771639258174490662232695225541499286129155943369767839879500411780986269174749183064651855415818686275286202788717135091846047376764725306122376945543789167596110218241378201122132856018082385542892469151392452014211893652144898619508913117443635461042137502614264970066197388713992733880706644042197670140799799158831726375431394823772150788048752863255958797747586629682940766936787421916297439363237908310284780791154943251198500995672845920368707565862011060283272479228294155895911478361018228507392710748033616742896056452643593258629335695042987304809861219833750883098505042246248005315539269178858230176140905824395048872719484720544273708335955208786649572395626091796462879250548904218807036122004674405139025354987781052963331267473831152874055092982851821182930486154629246715137998001505279155777824162092083842912812937202406673706101808450204677646416799004549910240946637684884323438466786794360639424136918797945125191049832970985403777707787929346953743671020617405332113833036041650005775096060549390190070497176461677421220565246427161249168054448542946111188898154427606130820667794899988873096702957078014580310105683240106142566038335477539651929131877542358134230237046216642421433781350696630280794130668322419693980281820352696004100783424371141338422452033090892514044529415249585117746838996993394757895977122408827065710011638940946401359879793071683885564076466609093234235810528862356493933273702567417618274898788725152382541126215364491632981663286449773925518688010178275975078328105524552709698091204729105711387992909911783019467034255366681910787500354910043101781631354584513721935248019370524466874357825272091714963574748184985079563154359457613521202393337892127254597928687480167102890553830934875387885607656926633551678090594240395104918531832506814385259934791287465345224104351858102310472190778619450619181634252628881070765766793694743569550898856822900509258002942667205509492111980894847862901464493709380156283279390612780031000576434401912451028231043584396764021556966667662111909138639960420593381685825297317877473153015591429713803801613868933421253829915721385273313917862075692172549904842143492750526331748352, - 108021839039649119131691468302798465824202580302011543621536764406458354570939557490964264836353712026017851900369013578328365053784665041574913833155237827602214028091982592821770436922462003781754875314914879626181788045368117709730458277434209448873027569978794442625003463021528649924784178099030227997263806005015714621824688389044974430363097276202589160721186368182609274039152737816559616261997278498963340530040085369383703845899106335221261287109309139442523165049783864663980393994075101730385090455855739589903593706059328347112376304973398516740482743489988329251472463967192750207672421770990300945347992069723077012296834342883652538617141192791730449748116566183555179088851931699495686184387811327726307347891528718272898480060472250445479763674952580293385367541152370570904039335448935410715654449086896544011360105752185226125595475696989508414635597578845212998451198735151453679031138454917532743027633891493316370345455772112498044894140055916339978192961537621125331311436686629754754484243670252733813730425259329759025540150162154027063171182484590516207664044588314948892426742996994654333690161378152837461893339873419553663789239546600986451239143963682973255379192586136295194784651839265786957238359558440488637389891933548877823992411201319222181847551250300836080640429353706649276151546020827267807831786001492271252373079145863196262210143035548362308306335464445322894065048210735128635813216122172917379083067928884615760509541216918958911162767317127279014251455054236143418729295184188628090044277715900000159420421613432997848552363262197038518710990930521784815975942034848501526495128992788910960758770548224398040321577900204127359112974896286899410385921984788297863492656535781731669967530935608180912328522767389936187841569587086549306976724076406607583011995871057797463301594969038729113830826205530827501037186508779098019968806310039658968592929539426994856342422474515479458936446364932976469633088401148773864559245377670016136269573502714318222359210713214941849764224992568354499312291222900644278084497618271656052147656994629431536757932938174680795266642779190919776880001553001932614313326179243247008636227671624451072612223968789745803739984290975974338039814131776947271948134325194098317825273443690213133051370908973380367468079475359186407563887026465102973871364062100588790565987012948098292535121768688905226328680027322157764106322593285963230577511593776053660935093455855817688211011845838334222705163777751241816349823501893166062915827526575795008895544445485674023361364687777584189024080902692909319378966087978981574631716062537547826667941157356450152585320015357330216798600090242621714315221122653675881393123214502891431369196264310778088890286705602125280669641926325656487198402160958984250359005253923966620764988344133094108088540763523633140536510258176578167697974886415320700061871963409135442195363241129917095686361666813037996548775483718292546022213550435229558250722176687994817496937331675029312437986868795785259525325553177946592875566590056468705227352851530915086343648426496829360985623870174187603207900284637839649019389382756701740604623404191085455828657923038024055840790717436408147310639874108080918452374302301312461501999813418974042988776822774985421004445297495154503212973621785740948456217901624713900793845961764463215786971096377823281274358161758550585110629115341825273331336515762526195178854491957995167607945847008837786684010659122849212455767652442912116638583834167235546981648719967380526332472415639254585940885359815214069758252780532209825430511159647711781803922122918418687738647265440480791643957899791354468020056026728026732722022496594155060711908634688639322351977295269769347016806181033983569901823118366877323699402102459699004797551054156188210548284570026362094070499099397955147032697483698125934648625609903027416865918303029205521323370636429504617833377483601121672846991312466514063001469690489953939198475346625250583763927166654672980467197273831130110597975314832349227903923342971588314104156186691714330707668811997417246698713425597945596849378255655196333355644698551482584126745948140642854770173777574538045211703801329865264672406655078647474195355136408824086104116290508950289886293977424403781049514490956724396936104687638508652000831157229587347315395972304069318705956773315058022517387363909659890035877631131159992984360231889521867487693287211534988692867550994823816435647109866284831617998342442357024170663660034700848919741221083699728690551826520973686983037539769223086865914674768382254002141782975084192459056180382806444046238935380334808279014612652130588772899079318620234602017068456863857483423080589999919538821763441964231953112722248512906479417436890554277661228108086434992132983068695757936588137941244181947201336975950718229963408324068804926098434824925566038468234128447590796556129399195454308503928955046898457423765171168139286568108002703523553445403883139204539086671240352934491215677286229635618970082334359568615926840378730956597411686066508813230505644778264328453855397457530551858645456148258678861652225439148917447851341266537798447131108260203590660044974114556629903193692453069618777643372268397341604690552030535755175621942298724688991963123314844142180209545255013178678058288014740297614416653477754148451241225826172893335451703496991569679243386752010191088819262542977557877232216225848090146046132465971140525039660763208023842780628840105403963630420423364480638151976145780835900668913079991380128766888157134748676121622046171092221684594814209842228407400794019891834371684244713306302331337099111690867690100108871186503877036586972918328040144483486016299173010895190921461218993704061454180833954037824701938213806800304614260147572995095922594389675671606888762190076345666675565493381737458400248078066003172285261404406140170612129869597758288769986719823906208472741576884157179801556971214955510797618598474822413709843076746906819970491292795206259653166207804551896600856267283259919594365074299289222282143843115565596787799751886860588578180432184540441024219964069497841537312192180095225655154525756497846588339693837967965885682369493851579765208804487846950401106615615341804970764384649043169067776495659586229733083075785327343832754242198667523474550468940280908953973647257383526763277171203398903280895028624589413165194188990220029206799529263699829893591289514003157811446166654924305270907819321851508492040159128583332808177279832593803193608470327733116280433349524925984291138333754303277792637202049816935196297102970857502664725536303406477485081079680908899749757598797548747365709616386766219148916158832418995153343656562437705068542100312632495583090610011501132713111919593282877383413988421862312652932140267450948385973324314868111704492275907543123860626112137406485007159325303077418027821983117962035623473537732280271511219130108687690719046023213026039275262221084654367474052281631043108859626965360557250597272508426687389392036903684858403422586982565838002381615380669473117626328020129209710017490656186048584302421509713882210280561176104246529598442410861861589355599682357042852654671456518723321171976338649876371611855280400456564903112954843276155500920199061726571973538623084060455467471592548427723774332922574473383186106286877258713123928312553583822777897934239357081893377032737276015904665216210145139630759179138783538297765552415971671677309999528392217284605103101756123405132736317562413680689764744065585618697516745444217793165020174304821948945998598843487245874047105539965879666256998911320018307011455390559907019227136, - 3975111112388090585466693928774436447063288414848557124595143006587908088332038744357839984526983118961537704529808651464226352077009111637569356403058441131319604744636322298317326794586306332969824365149641274123652416198588150017361673729870164737283727815027408648412298183448973746813210900498078034365529731511896811402719245475888938453992378198824728944080425670745443255705436830187163600817115460788075635721420038684715333613926201541587422363488873041026995466673487144715960682789559757022519967469621290717435745926325193935997083210906407908867021507790595065941272189438749766073356986355798502357656275630804549967706855761643778874423144176766435851805421873212233557994331483087854891749300526777481220228949026605732258916698670375293405139558049833540886845405115975438441782930808379474607796352979061851088856985326326486351698988076456041351787695369391503244192730925873583658030569233957960263922673099752359829915218909272249639448289800884093160149456241916759463534400661135134526052688089303250596179506997663418587951288081299367679611079429721138609617166551319818503114067893858793064612594985116763770724260001936724828552565116394658909924021553382635073322296687028744904627595175549430451042982295627262927301310326934432561982903464595991494594259098217935554849347686096671417207891926016499733230637012612860979880911062227317597960689791622448802084493407230348075214773000573088806600829765317675156320374466788660564716429995508134028620115382243045820702966693027872969980626511733764424849324350513356251302995834227053450208853750500976328787163015875986079617095465130129650255873792020783764093979787497571576545272338279744862302026426884794746528463610895720519508005542817672837030172815636467897852394397537051887484786428891794030361775260337116997951780119516298149469982287176431858885057489449579007208842356065194970471066344578606142731409540314926393753909533921808571663610890165955206854394395801122516872684356648435352393189562083198668143525983992138885674447882394133594861411727628752794769797338508643651721849723794817659627618912566333917938247809826957681328596009957910238512371677090236756680249707267878192928934950222826472293571095971767299801410904033526815521568124134182006093706907585089864875464205455895742837682487961984673448569388943181141382260596331480601544303139546909130999104408139676126741297000776555131975398042929637153946697645940143398145041771357147004438805490107724384650044045963068720301301112011272654967450426604487919251365357990841353415665696572675663538726466887306637470298736338207993913715506939984748809763412395155956607066717561983415765175018135326438885832328241365238670540939346024379255583254111915580752141080344081849470104692535351492434182348472526422807960539500917414991399035590554254566509143038021613968334014920417890891573936038356541782153063587771110464127047736445404819130874897815912315644449753008245342563872592217153045520232108009128252939117188660071250616057447104077628648304142789816490678952669719476208249164866107711623987662783399664789402873124849104403084471150352171471227506921279624872971850782216564931733499750952845945527757903843722744498403012973741758335237731664724325461215265660319863531994556471622512142109838695607161402571371182433935122161720816213398384780984017842803116775784116920206565986141168353812757978962871972368283207134176338342727946465242065078494804510629735516387633508187263045187707413664399179128908246621630269190207200898798031366244826561520987763257781965954220683968174763050947504842430604282089282506896267314412752186185759375177418183058796122023437890837945350105988288378911123643610592834696423869226183287632962165224014708030960772500912102988435773638399830140162217594075837393021125758000618771959555244574775864979643568231564828440287705843386595847171440625072712941773365680824915764265621489171312551879837539571220020842392030242691238382445894361150569846335765784778400407452600665322147800097157203003580314349747414053797206085640019341785061271563909164321384756912691456252949851803702135379282998210697073773595746703442285239436959034955236503596831182231590999946477352177366626706986973146340874198341386141739279264419052592247850960575309063723636422839854942704518446238148629153229203469718393644380705355010280511771447161632765750880304886529778306170199491661682134369948413645696933445074507077690989155646291943581086774547011720588480769219973323368593909775726525126216795760419320799848378853369976589192809490104699547438742034827889731397627750295574120835849530432189256122381241233396071395876998648381307584840110177386341925817028660824405044854740849357533989586909395057391378316197795411343944508873534233193502749247630341989715759935595475680765796441535329500662015710335408617681800770947839787080618625585745095316511848681982540755538389297726723873927734462998296701968985603179533095975558049383218418658458471920008684994787996015140362342309258840403126309092741423551280006167803411544576337232918853837625664258142065698657563389692680205057915339023803633726236684545122556407206255139256299398961994789161640035056334456845892020112195638976078855393406102834889544552529894741319361589365479047198319895351950151246491582638209744697249294255594316631974591519446223024568145812987033531838360839653153266289298049153351684809241367163434924807101227506038950349283837695777667123178195540335222739184505168700959501146436005810585892949789430437585590862905810800184700854780452516363808581005182439107961733330936967017413545408857997239677902103074723159484559351374949282734767819179498768579184374900823674802782469880647604379291130107643676901371262614437391823399729032004191552755313466686721558057599315948434879661293183832976018689668062228878026769612038178142606294122140279454638219819758217043404729150034717539943324135859810659212343503862012760595536300203477237723486060755820123357619603314799441348081419281050993190333521589863648304433283574759553819593432473217345016606789041176008256634636477709491075779650887344961147390144007605921468264648636567081798571395539673692748826679381399815041159853268267360031880466803328356127591463376632594412764933044505950742358782102553015883940983031789429346646455820861496062517011771607290632722818113447546889084358003269124186565124500830691890794679909775496332595853171627423544405198430001865010632671718312657284747411026789050304076884711288542186749597385716461996000586183414130071869336463492474975490785151287983448916198082299752328347078093653036591077427011878879147012937288257482044124422190560355400926453090487822091916452443972591059292332994140105330522245901466118872469023922204894447299027968543783825579287774255937765534591480449096472879626038146462643451820704397372360527088754164873759479702141732297977823328406106958868111768790897616909420074339620971952920977723721868120950880463379847185014915188690215568813401812909412746185059451651606212346858220576267378962203699336437561453567810231359051950975991989523507159529480484563643321032149838841994636982375356421164940666710876135389438050533350815767704524393124833147700248445008337396769931472561284150623047659819705844065017801659174808068107289389827683080926677330363316551195011771599042055964123415942269119552358427738446483834188847316724660709072086644719669445676432275455398683452478934821154205153812234918628087708722556943296083099189801774579222220666383573113910619480499222793755811778121440016713014172263844625262039178416906970253861322752, - 81210883366628728706170799701205271209923993634581239284116511988309415844506937236056093392773305400578806820180021684269609130610107446053669943265413777739916756829849494078598743751408521735716741898059303463335680599080332038121576603356950083254229916049421315794552852969410766551055675958565266509333473825673556702549558276555199703095796340047600393817363721278496176009912155473850699238497450480053942310896848940588574474789721180023923205911786683890016038290892542537063498565119648130155795780586031530914231598956862324635111562668499144362438236686886362306214911620361336030550675715373296393698987279776405937006428922569728412363194250276688415753166201822494141819393787201449057764968237714776428640578241388463455702890449453694970950419901103866705287129386244370907414663879603345339181597276457726579007479452198747288145644577606276694781600843114286679143464527552811168832748752307060211434053835534858003433745835220723244793610541321400239747903549624550054660329777780359429276145279438084432542982708667233271414181322972201555284332133147725186780756432834840663562365347341055229817512702058078472883128646773768091854786938313595653104606719944401086973794475287428213676981602692594502653662082267907974729321121943806704254697875212576105397307631829241954433589763176036059802943260124214662739625751308264916457084287240549802893155804307885542425359820736379401734567148571143609135485575150975461354563938048079400650993888515654185262065994443322234321732719208141977217650368042652241342171489013874540122080084385855432770912277586319108294375310661215712403080282997389643374759263653892087016097813375737511724917972366480613620881546275976772250187004918016594142067293610498061083035289860910951771597343515345650926487899367198913738223576267287729342123508566628055406971336038027433636443413418734333992531110490470064752919309816512757791424347605685546584144385261915085575790486416882786822464740572160233677374389728861713927767523274713226786535949167725095619304713200917965780799341914718811674321915340418719702211660139475304836775724395058335413603981541962112704606368135185349862026953659704576985240208447360390686571752159197701268272700451607199696755354403041129482211287542470323425601641911328877197873530508339905238265577098985369278137588745277295236820007359353781454376259690591065762702795095190872671192123530517530487452557198339232084319933628454025858421720276091033394598012006957232093697233100079131560679350487794806538195699657139755405598654234438345649414814863324651185460536563053085874619845499911193762348655833339425693510132896844023262910843847945282378002074783583559538100479914360341004204680274631185513427611875135058463105875720119434848745602662642731904439932033525862848122103563953617667478971923805934436148082829960802398651578417340624683676691820558241990431599553299027607345081929880343005324231042701181763939336748440241624237033774077585015159234553119262279545845681019947389402139524165926676419562175904173672685676946588080000069363816774611179181519649043667702047057866703303135473139791453562282800436811245164045449674381845753253663723572273858784899384067290247829671491070578763189419510083796168007681544257152900500207404754238049228964804480911106557878663229660824478704734808603921182851627234371406209376525659709392386913570272747000196272979786729339374413148930650123979794183178447814122626627298003451554635243407296904763297111084923011138879257463798962939419245670253940342673600075615460473981953609431948489239122582815575657973784059494899292740561893556250481787828176839356379821515867086381983463716339640724424311674194992030575840927421179436579487365666963918173996429557142827515982916708633113658767907210659254585082866227382776759730763774042699369869468253652231795803192280200327489111930426999690460453814143293460235959967919225461321944535235125086428580879322956852179116145486663716054076111215509625474913484777069972898636572950151686133997567544870311797207554645749070631302082571990544096615997202033965031707412114412701725222250140750719543577348977287554278268649836647103721550215701303197361551218972835374885144464252672909768614733609489203983387983320397000563473520403438070647525797730497250220744621372132397800523279952315927253104539056892087704219809157576166118121227871687582526061108446455649255232306671579188201428165842114556149633479574427476830973411946290149314934905924239196010691925879743045890663062197559970235537059653963235073572136814451776809759758279737142971114337111453074045085488290112589934263423769246810142302144062868090021665800577164494777232546375539126252356775951638847835390788875251765936969184603753344579169735798874877022261762403083664353432172064584881676274450597868886946956036653675939295990147072018493153196780895148041876615174868591171066969309327021003969295939559758343098886586266247212338706723189373134217401075056926796219034771961521072230362005589473308621691109495105040079763049495900929353767001114793595956132506467757082696824751248552648363907353955219710567702843549279929731085178516051483366513464477042306294452161211360279616799342994586362620694718108271818983069759263689610495462384920055727664492990438878082594162963851337048041707953990791939304302552568021527642765573472703791015948013450885616238614659972513178253815821032339151648735244959852497258990328179228355172984891376078564190027632280768457350526950336197929894182746901874808448055323314656887073402710189346510073405804923420584942454801813562703022491363488758421573633639883985623668690071468252002230409813883871280973289245138340118851058256581714594331595617061089551321856841400277862888969932847285043169691106988520956669910834936770704249170912965871677320087584109931840686691414545139519566781661347438440492358896627982796096272781483469087052799823861089833674697933504522559706485994005446280011722200059137788150110772402572355758225372321079881659732414944087489264950138285109002103533407180561468789769392400623680005261515373164750467757577518290305334824251346812311618641244613124168152049748457800621594450784202192981638710258494332233982353293573977167925306809758866416119642055806439646365493915628394527649005243036332605545219865191578691236671117414472998999264222825712427559052353448810384172970700723843590118467432083624265369544152258219932740122992312658292711999984759619210165846334988037378099096234113866598553201748181058477584426193244440154375276309562077162206814099790542606988589842423433851680579114735052490322207142314299748505192266630945007109446030245849326535579691329847501175016643297225336692496094069536910100499797092976636052476742455840182940844581789968447285774027194601996166789056944768564572624701223980702392631503745635526885965872693263144792748936759971674040182732998049191201799137140769911554424918724981669112445390816026714475326375621644782400257872854659920816006768403639886515876666488559107647422984269728823475788029055177576933331031502285364993260085607452004326237471801309731492432744698058391111702039688426814397111514643812380304218046289135787401245373310238939207687876027084913814346759376116735144470512063843744608994030274328909608708165328935210317171699835218953836812662519996146264436308619674482056806612803700580388447282572890490612104030340460728172321578078418436121786532274007131906141395714762018036577292797635770958100191946683289440107868792155778485445336260879764922165587180321210103978527188674713989792509973661483008, - 242188070884968796351705024744909680333345916587005302817661222393556329071210105454551483084079624367599381806209127056318503590922230564408327937223564791636459738615518697537474458452015249750953757324573142842821527514859375156849983925774401427050833832929598613506376288007186608482416467784780276506187726710117276350323924327073195102586540694024096252019420375117554845800337756885629364714115832007334786849717353838952148456592909913572985886413971269588144424093644551738117650126210713649327380766462954121105009327026968144854162526396022222542029445088694807045791101986790422123314071300253818743178991685168156682079953414491783418415694777039123302852503099682167116072158653178069278030391169629364684126339879495060176541584184100291416478161001309928006775440042110402447069485797387643729823531419544937560859135587607967514992948546696169096246534624429802925334765019733040623498237851110495193919724204594411440680862935633113657653607934404832302296131432934830424326327934794330949368639421203829681050973093058414861618192781641274073699888086395172801758109046026864900365564136408208470451381495797637649021663984439386207086057596196235247565678511096385811626491561439671583125184897668140233781647260206795848737733288574357585369027238261124451322600665102635902202513500448549361868321074298637559664756847162815696297930921248887622056264083850770241452407430738656092340201291328374084566956118966810496950437635349332029403519278553608335917649353223835825895188169042734706729810756896122992116371470327911133898036041002358914941167331517687158884514291972078083084285234875128207308887185477986071737178337499867017941493278902912935629229755815708857569816276782892695423113325184351548940975335362160528672761745936571224212517402172151551862058500004595147120599550581845797269688382746575131920711120890628137849205750128742835189859313372149964668687786512937273006901040434566046348478447867862314829260403559695480653675539032820007724403521585738786283924763905635668439619630163052103474022611369316534621960504511616089135580787514516357286443111649367977208131056296833688442881306317647718734604525453018070043669107040919232539706195007373036679781776312507317384666491268761250157252917041122858287898692554672346150503002869698577833058046779517773863541473657336237103982943740166682448140021245353564461587574958051958688592379102080245204579496195115969695585971899726539294170302461374378764959056747427673229886291727713999986553530434845572246827750988279464139116723264749962959790085049681193236110949074134992647273412418184921260569625951295373955194786479813349285576103501759768414431971043039346664692695577618533761285366832076812426174880130540497233887137913806807885507236038864453841754723326061755275943080981654238170992093570277969097298788883630385162961519569263494921924009212827992504927906952595821287244200470558064216311354066558776532083596812389903994869677595478651141845038664781208656160654985760284274427922289755554035494876265789917069556885031652165734586854598661233017601596783946626838351361354269734061369833043873641135942486366555430867048494012556798484422494942563545364607523177373196241278170013849466654734733239897468940835013331526489166243859369764083967321235095982219826722890340782305084981265145468572431719010328744323232500818892572320575977357651249234421544548812303549521133326081067976204571919818598783962791423067094551389580920756409571320391466360262510527026713123463391779889688960412976791310706418785392057583029355900391053057215166197895689092770834569959668092064921258063339768315177745334774636638686235860468623129516079912636749152269852029090274094989889455786200318257872760286830284209431690374200165811465987955666663398970280681901241832630800274234418125463271225957994694366116233335316166838835443045147962844038315441981705480036267831172992231854968507866967100590181372874211486259919773785418178953486520764329409943821404747515880345166213118851835898124912898229585658932427925710628158065495474719953203336852032739982868711702588469397144099427006340289037356565252425250583956215516761354890899193939897863923424277855418566876681442207428213611086567165462221162166442724957931743468641435562734839297279393086831378832066264766791324325894803873863061223140743505554144036793836847271718325387437074787522430897835679406200976192951202091228199452040108023301296150102237283496383594780148981329676713674542163648853107997333396010925135104387383109181136009404644145436014338609947887720025763287331134282101256443612700152325648853497833664918785257902107049214515029444585773109218449845533888624268332204391655181318004298366117515890036800084327449161992097725175725428762698641240382959909964596297589371387224836362123980226199439971724591066269551808546201260358720384916185443993346240452120144171655985782632102295405907475357765906806408586082700775640579079787466431567547271832029034338958166609036341717067280762935951150034869619454792732876803309898197616784996144575975613808316222573335841637840154157457539790989572939370411198218050387369900045153034865237820412296871681300484719251543682437773182935841201488373794460914513119058713453762140295377579483456863406415799808944953809552638913061549115232437579715268872291753404658163598941036789240151700248308131794233398669243293608033192890602507012370696792045032725506799686335208879298449103988321062090078489307046306938951153337427974539495927744079462377815526100532802301764167348414763092460815408702875143616443649611621921059462207594343588901236031485724476855798558035525449286460182074204228516180492687611318707884654447155521576450385105808792131275730763322976390982050593499414559425795976321862395107521308411616877507697515902025640968404542339815925387595068901024001468075515962690968641623391197677487976392649903835679953349077912935076855033967018485384741683605819545015877958704872027021297431621055044340351408048402051285923625015735498380716139269094969171953966002487450381356262229452218459092322811256762084285074375339356802398001460590471927128364390631317023018663390027240476208302222315851706671466034981089961777387204794733040680330294479956457262627829644021697041526829429664273940875817071545330085580355511574461825722040502487809587399850024618732671813043639265046667737252338177564034019548391643311528072654487111098083243671541982787560738125985184660020581791266916846222159289792717565949864859529561260771518896751015189561437686634820901174297342801169156051303366450724603008293373453308588717998363914817065150020629382881696360295318907017369826428537622517995736808990983179717943397159407990525725353461742697628106354878916774689541893395669277633010856435778609211722794480574335858688270237999627402406108859086248057858275184301264359426094518187914642604061916559033572816758575189275007570357301728074128417228009575940645694427025173279298427837691719262816416010558230485559953855235607688687571785987884333853729566146723677507238330015164174649778639796891818817844178908935599489412754932455295812266718985346086278005457169447333844645306141392282081898995636197808963017003119776467383031203038982202818068168505474364449598289487819115524664462967141909139813881141778002463765476871189329751500472039356394212708758038267360228814303042375173732948106436693529838029404831893784237371548302772726523356538269310927838119110450575758467555585096222995729389746751420126957300520979272448710715603348340580028561682857984, - -51930192118869311831159942701322493993948662835438378906445080655340646279234465440251770148465065206878643296350751732536076476957437562801009042052831042210129434704798499266338777896013854683355430307001140882298205808153890217179212920207037259346171096527482497656240207992847996182734140382805413472479677332654972710770143385644603715962830170661823399857856154724972364519962605604008835501598206371926656667128070186134684560621514169868709107158936624196500258372911005055333008039271142222241047181970500976968595646715545483971612964090594117301246668578206025966582944477823360412358285354027984800880124129829887893094460829465828329111024318997565739855578555880442601332574304762238576351711369521209487935508547382808074806659904807741923702033913256255742258694329171504969616759002530842100106441736095457751496507115635467481828973382714353316465236603720400706549469766593509480828764079380859008703359595586508544181129064611777576945684310835189021393874637608086862902782756356979275473919519064999429331610220785314986354743120394265856013501558606377497360509477553161671818300292738709279428046157380598925535710848375479677909842351243752671101301696660660877595207488424192246391705579918502327799089279772864973793735884996870275269346238696894719502118650258893935210927661374380880096176819290135209792307900562003456426754019154660181292166119882195878889670301837601693916429445280302851635040344362599960595008691521013450744751006636475691020141164208870679584297933694046395699931336463899030712230776994971429910863027090596144713919197721934762417375293473226603095446306911101561755860333156532973999354599971173514719139142576194493511568190600007523848313107180201298832904271707004036654715468579718353710626502461413819674409039570136534019281485859211304182994741509208700354181262167233227365059178617164499447622276888893012366009875231126204487597099360366618836194429509030725270644420556162572896069304598410744564132747625449248203217360946281883182329149707123597867044211415409415659685226277467798807815890666219083553191653351266785491689585139120174914951015323026555118076365716867941481965449717061847992539823999254615073136468018547466185787077179609081345085628769999631967377308861504575571812778418688145690938676600656805532678195464880555320955607703052373133570179983894732855812790576570545441832113692368156843622714754371016883692231798697076067702680874341565414032235756755439245911222789690890751512719973890309382824033704509381775634142812782221404554051594602150769791979198925682002909593934346994126829000733989964605751986351344072639281515677864979494565092462782892888765380712706709624312915893504213569660508037873464973216888954389579359642640026796977455602059999848308044671924363723496664299057248175482269883177848542498754176423184575486034955918645713457715736150047911554894539067177423440524244768161482364685451593440675268401668541136819660086436111476122904517001536898880063458784994411807591623270081088308518812673836201807571763675039100068162248262407336860765099012703465834014941534456961258083511228228844980675826651784765818739345294959448136024069167484833671217598969790010032211351546121028055853043916206420637402155102456560047468823719461487366949238722010279701190086125756958991518891886213088901369307282769109100006185701690699833354274614120928138437227013456999318180726972309178249656998192152116963239113019936154399569975476071918053430506242119231504998976560065913921780717640143010887795950868554626685680973543847806374830047205781270887000122542049457952525476308932641063585017930254199774323145798222413515575245998554715934047773107986623739148214623220552377537746226950349011745167682158502443227967155647070903747677583124215379518668615153317918938606118519988430805070488017324562616743016982933349406895185224567336295706280395800518573075804238221693152672547794979588956415296628901573489237022150705966970468099827471551334809411944543730657237919881741233606649178228084402982722104061304664611717142952336788865047986324970804612472479913415442254819295063495913037503458137912297435069450017482929731582996560756945145353492828893031788143883170681900317964057546963618294460562534332373281902082871510023200564299722178355001045308207925196620015218569598094528682757982240881065054039915070237359724462090738037276672503124200783025064926021222050474064781861851991915882566495456154522773758761231296462400833161131909922755733721965049887992172629360204051439011535985581867782327796383402186376443256815316072597345400398135209431050986968018890782475519435579257039166701321870180102790431936738208682604311574182217619248022920761604467604965071302672171031931700876081144668105830029173268351168211061786090738159886897576501530506649682363978653400503582472270458336618579909401289865812862384486799809297516255566532397264225361941937298684440475183860204413608884580190064184345977519208916154292689128046779191874169484849927519394324261236311775731281162929956100394989247499775441612302057911828575502259767604221419927144529955974934219990612882513092707021225890775409883425769745364981904067837861980082649072946805952165143990784712107556379990435444760462265260929937211132869975838950653609214299442814300295434800933953255765246225568655706129531496368664233485672670424131625904089757546927794107781524784751928839924469103745421404616646295895931129438331388612412094573246584265751113459839379583262250999066331171118336285634584218185630257127276171521583331176273603728614249433432988585356765453029679957263866156736471391655091786517008050880156971950073029056463699271152113351150375728051406737959420587547929044456654408556439110749193041492407119754386643472655884074437366273744657976090713884976997739099546149958558358664576648824544818674393318212872529163685498107268618124517380660072219384642727975053243502615735056111055511989544780946251822672477279201797773618877753235299513109765322978305287315050172202367810746549661339866521514122607043098572857180712475695084121700783561726384495474352799915878537028205576888160412289629885509089064989378556617635267957231042969969392380427125764718607671828990087660747143202119032561830680608665159518655142668443529185364642445571571600445999540418096210800763481145251637186507414402775151190014733454181534980598063097272578731093284945373587216442162624260839442330906645215993543682754565682575766010983265087136409520633007966800250241661453650544425154595776088589428895250138989547071547515584337250476396611190499536440439393642245729141301692421565200343921279165691423566574830055480698543195523868349125651659772807091317479473460751930723803777932824407630212296134394905801454193332960252697592452279325949846016875427118461365130656068366527346185226683741137098633861870564381749112947784736410172252058960194630046883808920670227078994889423580298601298602537346761529730699953745803415064024216600032969096591491944713597665569638592760164951141155895808568816880615791801962366103909736425151331622732388627838938650001729601400733867205295776814627965780662585630027031387741999915857492970317545085176502367830237431900035335176610106252087861000268672513131552073581834650147067793131445722175921765905504115830595481504682641758688166414504143193016431772173963786035820810048649516620952217950372605315061949618062878542315721882202104495275318117194551796879554055999820264829036729914399901928069426478855936276066610285931152021651456, - -2232564407012434178895439094605585485073360192808489401330688639575806044861997868694635608104230736058899441602463674709973321962714552539944232719204238117255288709869496205675235351090419257208011654038786009338935787453004426283001300679263126527555753884758568468292869659798909297563714629453293155061834304322526917131219564394658391128203546587999016598195965573279333491791474338643115776030940341899871322014766671175829084411566985426594004719893572797939737748473076284339577533081982957280164018059675459320328848618174336406099092199636038485777195249176906991951238255872196791895752756205938668825353930694729333374824006311050741018192491384909761986028940771381850947866242265912906644165700068780265166945191657061823359957428951362784722633350520742989086107944788946912425241696199501859139628750568258852462696540047627612890463804450544420934398140044636290137065418584745795189212835818554743140410069065978842200452787865478589339439727310515976375476831293803121281652538832738585178626413965775720791588293883273330212957019534503030894024170623592636560338832084541816205514115121606161434517294180672415704319165383506984159413429561653999646389879764502277849073103588200330723083926512409263440169197213165953700843252973938321412859707698396076519989031826357278653428762944991041305075577938140534148700585243257964648237880637300868739010784235594744342733928274829278151119535682142375951071766609424447578237663075198093518085499995736183666456729255164340114476116071347286879978582498043347116737566249287789751438241849267054383214222105468466867605956880756092924038296159568679368097510343141980467399523643266166528760554288387191905095189272564254533482293880901155245577458904152842822645104675660969172039165125973471205097373419081136468986154931493545509013613991446642172876674914326793830617120849481737355887793059706499180513282790523773912195547106398844046202018843872995524129748297163968380002944252523647316286431121300719055692694120320732848630832849596501430888156409548787806335427249042534338603383404873765703276674816083933086285567304712764412844425388777943691530229220314422510664937166962630139593318012938847091859905575397216358480942580472093270439733145335806988752692794921161473871746238586282886925114189065734115748957147592597604130373463971695344500690362002286898553876869952237934219331556861199499559642676005350170234024797555051521328468512480803916985816780105722681178637130436750363716186427638676291224802625310022023641633713617742339313433828969581293291486209597487979243891025439301689148992564557005883360284680724733503220024438131000934171744666966300627195413552441166738229489005894965274899179895971243331194432558936262046105431417070839825104597053434475545403737499983331600131429716027201389475479260684735674498334014435007963928029247871754110184194635080606917726469347086702449897171444163781152733558985911833198593000360726904094791092416473150137639422615819522299341135067726693941852491558108155514939826258498473189914482196416393592196642574427845682972981163156176121337487985605255171237727367147321522465481052793037560524095641743660619084907640715005296049514437099690999357384451898839749334421665218158630344971092613240518065910280211892813664549808635797449529255951712074936045252263489812701161018620261085083789613378017239275531973275043630803683543132606734940419892415665616144545074927087022927608408046282196973850343811478551819001366837318228857268258439562962102297111724645577298586368168056059328596814500319814013999329905940139519891261947844236431922049406959323311443535825106677053173989011708093369289420456117676436333739896169743167896497484022098028890531885952048868030521553060207258273510573893325266934883787899604611950481913126653075718166081797200299415365681739796621670447168426447628076459471742278430293384287015885389445341242844207880702658914361408160379700635557984829793260922628650278044181521259603988516379305332677528982384965641127417466386349915613231965209643200888816063778462047997279226114862276633299246691978954318245448278635388793854857795187441001076519145201432802376885194237645543281615749206047337290080035922354884991072273396699735693720565910159394514814810861778697411145952851404411239801417235920540949484145506449214873256040012769264814207238193006369598299515644900281463698382789573904147355164438773735923359727417184016454561714246486686000527859158791162483867862160537856937191110014705504401262267478739637910954620826847058397835984722376415259882632953270804125839790023103328813492029882019882075638492892023420487990510366067640737815271649649842134119609818413006849630050191666999726402881915598810136293968979267981468943982997681082582331698026124343942455290796808624836729473850926140268785044390164788080719615699724843068445601304910542465361118191311048111601341467295437970927794383755574997949479628703211826027644708590487275009860933674031205313723266214611887594381476346506419164855758371303653342284560028482058372179615044018760329711879428302524787867151747235572739315804305407033529389443684647743884683132161268795304229853069817107713415854582877166275223198769783383187542754765771987400367044240421652719225427999095490546707242895869012105454636210329063638454274741406439311304955731580511867806079806395724782579663308782464215416415642638510617991053538251900405768647163835379024624986650686957484549242522328092155675302073537557676609889720709181358794232561785539788032092773868746501461140741913118083620337198250324139497610440634379339907124441593481098133228741112215277283596909678359388660700599268938903008725934337172669748401143717648863546247684540742719969858226296641077241925413252919145554140045475884083990423820981675541666062285345430295238452469130674029562612398418911107163857682651727958370496515290913791873045098736685884812014519623418650179315598557343338073288264324649949357752938929143583221811358126651092139353174112970936237306115964190549396027592536627908733255713335593670883061773935335870626880094767877301726607850951522320119035512606735230834082157725745251270660478994685708103936811242331449937398365082388378447189491209325882054944605788138859564158345447691266380442958332034019085667882960059771052095277887358194681975098607706189597323315076826230678472206586288767926284497080615387442110147197836946652206938216567266386856458602410629208093972604539852818831485465502170126608922983189169093159703435982295305966751642335137711957070457641481956640886910517034052096082961773841650620233182961723865549824627937900136738013500575296464553941617588200598709745915883968927727126304061770729713045760702990843235132699842254164847801287539706298664036803543061171064212951260408711464279945740448603673052940231302418384836488369605232707362480910736647403561582085626979806385101521935626620144674967948913678290207793659850903516000987993291187268627349970535289721675379864915098489236175505596180387150930805039012948840347127468176550794839624707358518886105490683806494656875241601933746407014150607171437149790817638081168176255807616742599794985981130420171783400134691383113446103296642817985302055487689717455186696266789969284672357042547616710813683025334310811979997396115826473789107617975177585827328034810350249694731962738862402333897462343448163583782461789781014687201104459890422491849973950557186586666373063749955208958629417650007307128675768994998758429163520, - -49523172778335386259302551616013144135816623349699667747164144255607088141472252655219223697331883110151392743197072939937838867093534559727955026883866752704172211137942413594045200226828728531268038082601997086421701360969698803103166513861550171126760896460471358321833319822298056591537615979125185770597915204265922068431312829273056870357602440000696645476404719271857277027036006670365968856336553184685916059474792521403954877523410394015432690883904018165864548009678585723379874382252755099812206492940939288805724533146699918462004386234979566775909956867583238747756278041118945087478690524877593435949360264221218175225714197847987097130277741057153780058322360006493480573981809854986830166208814104760852146153691469864316568291157892095366594033015062714323504218079679640765459209605695803737664311923573651256433572290025023708485910103353484915305810992342627912894381994074677086871921195480803823883741893579769736197940003249049832631768182328635237413826137434979674827973358105997387283647714644156262815273294339654033042198595771464861768987687903121737721420122934313127411527868745749810996383829405305934116204108648882952364152153861170183445401821031596260575219182518235680260944897411471715292832309781636107754390079457489814876841381646959260295660943570749242997430404748965858750649325894143586278819809099603277653383630827436702327274997337013822715498896403094395189716644911085675478549448843649092188581215376350011252875400075468405617194856403563682901593195032081111832129809501289781945980884869782734033807453365508121520603479529404132399109313659521531287464301831159984437040651328270502338427442334532022288049170355365882766244661025087630879460371133959317122022581047296136510242124818062477839179585103511349000937796403514392258492084107307730831693572273397143145055621983493145540146720063042451545612014803207321275885124866246341220724244656245186791198928452702775272640987195365941721444910468341927847794313491213269678506654159584147367876078185294910532192023755206776586565446353564454763784422289883676138832299827693757487871049657202154862124165460680008768674804487356047052876191252075559009940453458245932318952253815821673903547122930915438730693843552197598989403507305403644590957115849427922089111594030225904825856837364010068306049850581234705795402366698289223967893651791613988559808622308777490631157084535257027603112427000729430153189759731805061952960682246967235041012460414736221717534758427536756441795098787564389964010519604302999955321205514922893440069407011934789059053605209041283702624497221709973284734137944996777513160111574938910892689233066675549778590213003817193622361340138131272911831369254106142540041100535056789184900118698856318692086458626560955807712136407872303408459866750964263701552950973301241594367617030052302898790099304943037178233703404062717906783045771442637490084363411666245510368652692122196794335054843623517325397899127460849466195451210252255747067943940387735360445625026258168660295162660303208548945083338190926036202941746929524418951132590152134911791812823782856068536142482248576996981582305314040192860230539182316037038618485054149053557192529816390399103842229633928530317901072368614240286009555407167419863868648047615336735995354883384290377862278704351334632237640405603510744207455037268480536543052720997837706566807508900042568757732515505574909228021888072421576504038927224683899193719039022996484825112269557021303731957098495012156402934140855023881838419746342926989780964493078044363096312479319354860496416207605113562443765035336456129134043917264708874569217647599810134490512409689501189316935708746467151726288534728928745773847328866376996962727601289221515038798695593866536613824505523312338166578944152241814399742049961162304874751711298619594249246556418240177631614287358651273648369969023211050282646515159915445241950911277055514063382193552762877517638201797706537679967312217876094705615381181815709153770019102083004151705608840524400490897338313534736609422937917046597200779030536256994209693562241941030193269257536651776406885780278715244112598761474731569444055234221980392556087784205394290006236788778621818139129932400936801689420488401829403317851427758569842421153647094913410710932013384004078119712193186099136110752199468677214153892810746667079676860953011666753085071384065927975137093343208412934128393222009087977772000532820419109009487115631551510124657365250787755672653240711582467483292365150777911278871136457883346194517474479212776502137858761976662932776786653159261218305487005366005164806764673427017101704123958323443229455726323976269149755345243518396838027415963909294813108462307804444575441757140538344580384065246688092472546558883125602404600027911593189127126610192702556480011395976621269241187025457008297308129883157014320302860588528716249333985913997995355323630757798134814552363420069734582862909027774087984494216138413191708334024959460931540204122376268978829231658778394280268365197400958159784186899348868792715858518139742403734544635326690289813910076076078790082506598601893937624259045953756719589322638398291454930214968107559597547371429241392276833472722421241177394873950823936369111029611755140846680661718641964477343434777801394691862432730616999877033164691230846418337141195209128412023694941414683994920314876137841963886091554840903534029295916634156718418815104582429611067288160699495842276426300426974356713798290364524683578535164683714091737554034723773189896463724815810051148847396516103637670018207439874247547973160809049562100805586397615925850283844689188685238533712415728170932550875284161063657235390311881186235931887065790578619696880801665205066932705246665588003724219323726719411379361053248454948264250619881697608400933041543800119818455556634204190631383534538629089694080976421818383282719615668177696900214484808844119166985363642421585035752949199280362866266470654241351829903375969071684105647476456801383443866679876338535235002152758391009678894910153299050342776948383087225878062628225269453140003642511044059034695506061258730057938964440991986972474874327398199284352861297503209496136454518300351911299610806624366115720657787292332632409836916739901555604472283412569521229692701702387807161747665408539210323956512351475033732436781290246250811928949754204476133840741530146768894895050868760040432610447023172214940392199241978080256205806364781374969630195289836971363670537909482281267166991688800543333878856742658641949259303549075857797597613789302951129979373208627962544772976313744341880796560999356990833160494820971857644345516003057753649945008147648439138926670503102151434522639440068471337247677891485519256358216492405509275868937182955992082408719444916135104730199730560389888987943337640861610630199143822832574805817343256625771664220360800849507714554400953035633210779037509470862636409314824678328354945920778156781952769845864248741127649295417443043473484697145435739706446725509650277531614168553657234589752290729310198019494369177679481562472462309206923179586898280508496550897944139183283080916542134150845431596262653904874302513394155550968382442518338538115868317680412771518364929056229184715981901728287093415830705052928851129159012043302623920982629457880796094844481071564118975278644005902807620315893382568691701903916639493243063636975675409403177965412838295487310432424174718430147695047779064359678768739527057049911296, - -346227843474612941416891082644477189876661780508288112785294741416130601304181710811059160837730842361353801959465980884975098527295709042201656997600969620382000262737965720071068218465298017717159143846862974881906813187329399102730065637190823640391359676885546531310473468415092991297821237604635683802738623687073886957657737471924661301899801624871829974744285557327888814003685849725176471053343674600002998777732099737036207352917033657554810002380696070771528777876016949537174976587795790613147293446977128808848916954936950546937350215907344256054122029215757855151819646712941268135658182253523124753946532388981085731051145483586839604136890530607327169463044813890227072686180307162999184950610963772587001362113185763121473913739557401470540804741868567192025356123691597214868374767960376984903088278605138493990173759819851523889185230600168933647404694698954583980747968695993427321924142927179387033194371923576329107090502975839070778196051485982476420094758984987599509917058943453037829585658543513551558764860208862676028237827522542279437133310998046387791339401792132892681212118914088445138745685675786778182137495876610684295964438004626120304497986031629110173095862558846569071269742689194727258377410181033888378739727399997458299373505807335600734244397824994121663722718327949909320058595692516074985331471007520802270585471212097582004977152678631646570505299975699073190420533902266298174967973923314552105740612367118156262387256082356721191613054716559500483366724669991091415954253311474853760765384803001907116912210231123507392598353552408932801459058935551647183944737817266211898252872344059778948120368683317125139742347191543157715645753096553626291118814370062051905416977123789698995658918326281279054221939434085164146130048913750732154051553520066706082214575474551860004687111078078456840015842282947496891483023797430584093015560427289906604381233475815301791558459581826936777636470071947321253416905720889609972612052767010828812507916811548020528539431424214788150677591632753467563962882442707246716017360184910082803493320829568046422937881608007507673058470351525004965357202157791565299020776090445915264793432086445512559674102658855325042011376355873456179303535111690250650474272952856124049848478752565140550188735204335341171084447377278367639126250092420201660667177060850507758040958628709595165539859542852821608151224839945678257381445417777756369503720033384571345556400517104813138683614397258542289429762109745483786021295930254971874519407733118894085103927818584436521365707256797533080962357950863202527364526233128577562247482909790682569877053308650446067605540320586942256540178687258467751444587090986511764413111765036420195881542517158102813209338610541821176563390220815480568170392900512204785403789011845352890775433784755458565935595193692557050832874695469127434774858717856703142771008176593155519369765030753018371623633621303050505650624493779232093431663842123285508068542263017186690490890538828472700514403466109002802437668805766424025336534374482391443602616708896182012732877703040654900880426099742953572484980033485065330687142329618967964939668164557325644216389566344877340470017202687819959317244585252481359726455969768718756093769585016532470289498033905788980339163866151323335489161188467886620012131024475419137983065116315730205962215477223359607746505602730622797026956337997021463461887611097743751236539636483926938298829521862793861446112849719956017983453860230222158091142281491252033911795439130238749821757960189015514745054918216988347965020544453211220841135406582417027917441921258618481090816157606127759728908262753509227349497817471207904248110152147363294690688255667045144186265723627251682001064459633914461392888027604629661932210684368378243718200379879182146269252894851556886962456036384891052850462230549327660304164653902387163050609542412650667565792393004833413198816221764189118351110588090432158078179873388087937820424569264699979797170094129907152240346285819313930704322936574972822734363252399790201933372862912565072490190782473503474388193926800023575707267198621559278897301380980594812772844907462247325782461912949007938003604432904620007035063554044067318739936334641386830227272161681618195866745843515412141394269182273326134077322326834683299074860785793016994661884401665868215375877554377815760781280414815769947677669902822873810969277164631224809255283983787838891184653626126520950388822019591830062898495469219164739016831164287114250358736648193544709930958572874712340235505249730290623723296672290168350575636810934826283211002305871875682077950353450062107340846391420533141827853492607300524775621097134126645350984954055802588939945328107440743651036471732891448038666545159731707535523309422704683495338260294857838199924792140175131075577311320598901855373742785512573750030883870022265217760369212065888739998291265389744471914960251676456273972078852167423574358757526427998440522718240528129104882477777000883584888219129082239886580820770105429704381297635304966367746206428030613973969703121370576155415664382193031420652043292033086246027832313152847088565864772600924259589451346513054383157965315589444545923083731273343192130980356464035074658398554625201623569950366293656144043264297942982305373084464695941856016471335257355137911465107755493307179687841331418316387690891336134054487004096276630318361762694536538288904694258586395868464123475452581591810754532891709134197182252980205903676126403335735624478770313102562002779570822344518506117276666887988445596822842399938872191174515149992349924458345535653914604788750759029760764766655000518090703029208550347588389178371507723986744661865524884285724683728554256518986569241552569391331675721549118628436866035709247432069882402475849978623708344409978729769565897537089537506800682818831533474156757365649298264391483308207947269782622328685389389478853631615240894919383142176335654687519805918035118312347587823426810465549468682186488350620803203123552653514382232692032601381354138769003323132815730470575139286550315916614920154551519813749958983054412327793366967924284561193244425204578441587848174884762996527707353731827887679105784205348903324018981824237022066649396108822490815993515660826447651723907725016575162126367489725651792488343984801781464854930840780553055391787207420674367108909196204004722335957945241506850177829003227893522717028596099219616344054600055673642816766289931996825034865846919004492629893777851180811197822263435294367102414482410743935723402544565004902299590396692720192620713220407385050319537466142737077749622558031278040224393544405094462056538302125277343523775657994191223690374301412958765299478521983768021214858861357478286262228379936414785408436679765405777439891143466396327544184684175270790663670054534712054370149302785116147444650416300122654433439376782362113113515524512745239214185203909260424210521308135300838623152293698695870177323062203560581855772928116288653576427120036569301155743237002839130331925753332540535697097740398177512830366762743383718830267638913368723614721210047959352681773494546634361824360158777152709736621619469938211922516778461846268873994450129382339820055410591449366563976152064319978948880228187431041713034291212101778504035283654956087536945635689212059836410623467836665539400914124895294445581906396142943125329374040569439123508803915339398381560549951778635605974928326656, - 19768736382427052126140189622775997215827114759701521097423332735345680921120446184206582468612664966969211820281886709132329204930075760326223073989901261102940753356042905924566429419897594832757503888787756077375050351648653441383297078762265293134618895877136578046651039608855022998391106800450156214053187389859472912786146350976971334240568400104807591052145665288161471308131830004066321851162547229409359456637042056132973680384477597388900206838972729042902574634122455943616254633787500386052537734451593984086412796200062849314662186169812666621188210070370984533870428989171254659452382752266046744479688683852724564900503094175384253211672082579103410694863691286669009051519180275752491412621055800747860373132650974320375907462752189584855366319919133308491249849793904625016621510825097292712481920230550258741946410674714042750622991384087004775243965459423650549498386772552457475951706233574241707833873957608047772565356961086399774413952298831901002921204391910967073310774550416234161194891857335033224412117593417897373682022250165091900381957748014822729636413899588593176915145902066260165276120729805775003695031042687836880532816326691348688424880631778480271296406402960050734247046641026058306067716850131783318747642198827803134965520010634795455557966048218721084707017832021761461505810423285814934911280100646397067343798132866288792404238941740546768448429745518026822158924336031386635880088439916723144700910986847905498047228524238814169788812517671638773760350456425037386633166118046711807589107961343827498167689128848324743167359914374822282139886951148538630446385491561800237032965623685917602311516819441159298188496602038866047640059965201138296378041107578297552803016625901681074182327628153800054771925836270171682688047308644151362535429382374818238192522146920041606556508810990568259098336392669234002206215407525576917071022473184122835511506402096759247169136142942662832459502457578087811164492993041604844895929800282591428509391000625735240119128855862112960659909712755695844273105784574335688147868667342795122540671734679025906251570110981472832350111228987867414872830125375036479594943244197850999908159528234431493515409804148175943688229384898974641561299881053635498763638554859422403463718567467423190020983450248886323882032026839412088736391494173650154662144567478271334067820621088161372573294202106355219942001366643293247930217837582362177578709676220598023405782364330228321247655238805397955733702719451811862300753796978922563860692090471875039987665201454874990972108993910194373657389612013099594295467714645745055373973566835586643918817251109808179290341412502479137258731090989129122008410613067613519454312833198834640580300356194501071302997990045236934250236490471088643676611817742633082569380128682347453407215576659180179084285072306203098385281572382198915220015687519251538303154951371945911879218129360460028473558888462082368864486085413391615290053524696690671661926120867956613087386080909189021501474427884446995117845396451613199216889529161876533481690220191924449029210601143815404917456811725069155336792363083966251488767603447531301573708515672398915135834034966811084456324233535915027243638651281451484993168934167940515521629682801978962736177600859051815194057038728273510767590502899513239467587359218484073915033049160503985263254198691266545482067798195994532126392641122095702973994352039221516910015108319280244194841813885630362469803705973688832974570115510766208693556864413758835232599895692154231630796717650349294423346693256922968177793057986808573188424405029921787102503371942171217022527353972712399131342852848877179598741203595546858576593624378487502223872895987327474930198852134168508253960967522883056674808687315531164982226068767056395438899578352959725259272255102682149847999607283859795679489507110146009154076808529587983105738991820080672591077899319768487829778505076829578451268096485203153100250657308593678915582908562877828441516538399417352652881381672834739427097829801775628446422695080149420291627848402884052429548681268517242799000338473890689359290015085435896773624144238478330567826907613105809685716418436113180512150140696900580773970376470373966486951019459303647253802136701181033150436626252394481277826227322093130449967037397861846752145091790772663089727680450162268906223124948605453740148648688937589315077606352734895983359585843098122222818730635351040523523156532835463045031144016794538565458179009776002315977240969218894122874094389212562969536168306267137430809188560709155966949578201902100546450268685279296192805819912583345808797721238627616954946355962087471639544758290733894251749385063489245636666985085281062197933193080801444941939837794850000254147885087935148216020341267961120500817649972614935232146175753598331718202055410996394763200641319531317310944458128973704740879840517823952297470038499929623725439454190836868865873753970659248053682447504306529848464205406694075190306642389255027045333428951551732894595112377051805421510400208770000959130794834944394297819348210173303733591982669837382429765751624010887723769105276575645140130550921754846738188543689676658027804866801614412654623035366991957111713063580540540226143442694349124587898500622586179611906567214987992469768293561085955586645409017005705323063313939129816284388966482556519088240169997939076675645756037175524081897087494277364610846782905683484497182854036500510589876069225459971607825945717985603657719065337485595306720484704819026641368026251376018603529957054181637640702516640870223777252669339024553588044334490679568526115659864625545814468662786820159042721265733840890795425941907105857588987362987989510653704690543467480778040818313561644623606769839432088030237284143283387120896299957510694536826428900291130751306916608619299269733213887226928100642205601550570391652150725238439319678688017813686755850436613593217616892498650870516689470710812036813895987760152983985535304924655320768881146333961928730831238107836761001460721842823306171471893393275803462229138573899050748462498856941094175402359068423427748729220493113776204815998158797308540161193633762888198024157399590304902108515671724658840163814015463809988435034330754200549629167445978488944763692237937329097320766271063572230433460283900522897747583087533308802473435235122850260990375203205538920288145906858336301181527906439770323841570167852934493492933297387499662035823262357125248502023404845386427713177707144775176155551255774013827021268260321892044321137551195563942429058116150588610828044635147187923625563697021798318070920881164773789936220930029877362091023558409780146466035034605558968559277271832940348194268358034064268095604653965082300863503328059772693810146361976891630240793589773671231338842574342556230025468292071657467941819674858426057672708031845114757419338880749601610722508499756298946563616626383977817655751282998535771234073260198617213308846489283764691263239407783188667679684191596504835700621948649300809659174275488696614505353624010393316904016728353182280492955392433007463034716510354873900787512834761622832964422668356640323196910303251332312169143914990555532351681375018753219306971754291987766631469153734855699058451930172279797641952177573493534473342133518888864039997296471774165910491717076516203415896766851226436021105624079208934940337615606586320676725323711259398435183263744, - 929616559747017067637319167499748214382349386593409292214759941611510335484797700875378286256139659418865920577082974863974945793388344227230839443277788969055160178033451045003358168579883071379755333914546116265290938701727311000106524385026114354729135515490882113747627645283944817487625279305432292004077395843462633826632453908680748285348919282449693411542776409656036340860257346236101926357012581341587522919813715104907421461285692873319338820719018014402789778040423617795126549174028946446749047135365007268921863479135644381285529859415052992416734927266550376973907421414681199988721407097336524464078064025138638972815411324397700926905746863569761227618068998906609231048014069097296323261619276176176642254666840483955217694949024351241741437987519272566156847621836145072729970830770821472377654502551060012284882919941863679253745765652041254393017518556112452460813468337252123012565950996394571948577020632040030985649529205134551059969974920020354847166434996543875427155953126438428922828459758120204420961651057669467003809897782223746144421357946080165510588437232692572788908695819971292280510254513480982854227484082875475480228621311711020673324948339609043422351350335372747998720368397914945079004897952626258219452253286011806355068583833035860739230173011924656288175792800972386089194311316829571838660869151189979950445592333902667493016624556492927612991195663832629106826418500378039877149766507097755484051702189223263827382080364730939709834146168287754579553296791023169576049361111225967394588609013403198535862643875668932089008390296323849170209077856781500028532180850393540647430135108866869112840799371365789136081188436592918138675952079103120731769500574844294029579283206656062081774918656226330741821935212961341183973921056999568114294451361476065262520441765759747991628556829966158543592239631766797207514550877054341328076162010629930181988265162988389448210405845591614929963070913353053312484624357088840889169568547959457729971842204717987475195511672746532757035199410925059606797359620100534427457178029482700711586528209702805161278274699610014757249505085133651321990749622072589635901262497719674901361074499169268070465822071702134227738367861263173455876824648490221852616838733501553463829319587646564640786975620788728267594353771005983789258578006864850552610572154928803894662009393180792378802763082241033193150485443373422911288109490142258345963669962917048024333251348824316938183992382356695113368239259850103189920677977362885104939443888924281518104877971923656072713121765488766581431126883168712646492702902105216440528518720487779709841109144158947370588865830165326516489566113694261375563552423636493217177654571219641193921544991017021256642665481928535637539443760179477488855780354143537572038632884699851192255543980944147719359071500624077971881315535876759331091766406013236269590984291394896888215671162224311582096839206962888255145896463116340742641651282775581941272489125135260656954592270924218938490010746270571512641221068279275053906134567661558011060244162597771255984422304656178463186081412745012083671679680450953153015830486636387672307036199400601840975237095793742984860734324031311665880677206440726058244591783688743991641004526985960359353639054965713317066045700085867181897049696693570389693535602627526294794050177336279729251213332306620498211323422929974121949106681282490176948529841484984318198003764211878135976441449537273824351713182357449169023997291268112584008417900360528805563332467391918471232080971364958119029409805537314919136620151566079819612425251310809309391088280077869698911151733036622917239870306718207092498025162807467419754671154651439167285320893711140910258532676357408675504797015991440634765729734826329598310915047671075430882429357525397464334311965225397270861113462906343828965731964064703128128113682337997470290521982133748831888561943426377442156753974905999723103330605794318334825258563108469669489615309425868307977854309248901298901214180046726330503988932277087842859491548879318897755659813652668927753516848336933224350255154255532779290363252495785675171998303944789414772492752368790361745162686587714705634952638208954107267565889656431431490311693891290890093416013699654939393805619200059147493276765674470967070987326750715025361056358972355380175123740582303838244738584039389949534231110906844944169053836260948995609839891170963851882071021759375495014374765780687181438622713987360379505625276460643272808290406989468590015510537299153951844348491392582469914677975986571708160606993811240825105912802220096186100988338842162688274737351351903709493410368671199502197384184957256071391218809137715594304788618266842423086734170560774679249177388983810126101288888789462069794587841705317712815230251384238405709763359860356099527487624719115909880820007571089289760724819467373764459368436148418599105108755874142221154530928792728389396047630013761998394875901176584268142089966968632895992610350882276126489668705501631968142998735438815364331362840997073182737416728329274387217287066415522057569772438381988012355915661656584006969745357535109149047345478738659797275339023309955444355977632681524945742707119103314686601150580127667972278760441130089463862866185077342520642747576409913057397644298010029986899764676993546801335947110348550989271834998508070293223479260976142628591572129954838692397844923322684256670868826164642554535576054983485850735342026520795940284921555301060234837541316458508336389643901052309805396951360199625031160487280794463082476876955189890115237221054622250050965153598854680623321969326777305440045626144962176957576227540262349171122874793857931079930173591351613601785704252948336421986928634317657460079308094674551427434194834201857274294933871641711555527224107202292686955676125184340769459147498333380718872012540535051877093443527214217366413492933288052741663216185193297831058281232947855909089334187242949368454665905279786182054012733386786907425382790730374684190358275886723031308435888560339846433075313071569386127439373463597301654747063431653637687743037275661967468349776062933420369015986909776683745478194177837579618726583185063434488744975908185728455491078385316579158231154753919990380556782109856036984347025940135819756665142179435160641372327531222447169387043988322654203604343795597266090578924167365646584885640024529193363268085236547873551084599758810359115246178632653400949081240821722014560894531790171336135601956911475618207040316573878477446871442757524914985714259013922070862203243779462572179978558030209696720905827279908010036637621108575160931647088964183019044081413618719927163789828037311590111813317097450409172447178670673016116319654940555368527711681436409037377593991010018059614125408622301002991387014009321587866677250541160276355927867596468662279073709809627187386771800154246439334366719925628227711550458929872460958223529320743053564335532355779281934470833856728045105156150841237790009891104068499371766281825429732047779425568190987433398155772916817980641701327462235711193959510583302258031554954918088659422232286035626233665835501871283115649250548382767294845723151329134287837355905521358514159853705323413012162178557852840749443652116123675273424332102568326864471785147408426760293349330091601799927153804043098677562200048698239914876489467013270667823895679770558464, - 20579099318947498166177056674080729736037785136549614438213397127307487407936847884645306184992908915408431651770993342335771589115955862853749321364116221244450680944090306995541674446983086698338415310192193153846094836433469145196326341800095483395014607113073162733386065568100289200072172131846748588578022748871519581471429673273663556237058186343623355860413817507592586144871701211537186176505666949343653562552912676647300604267991818614503467293428097412845960190087350984237636053476362491579029218396080932240169390713306543281893506652293454264860631978717305359102004066775829267025708722572359783924541029446658405459829963816369087841188900395672986909907244661158858183123552955579613977526125374440944892176830953609612330599425147024095880388104807588199147109286427223633537356868095111321430332955266133759282241526691351817780573968620773115010786388795912040622758016547131992695574852268346535070705300172912508486409817659125401097371904276617203566899023440789348207771415751194403246279839278171461598466670474462112291351245456611204352886316944130753524128753644657788192187857827778570813061044211007155670761871964018321271141705804515225553259618303212424449885683173038567037014181236892250397742511161027455363261312301369705710607248565354422371293618631320480072218178134045550606032912045049431566990259161140298397863500129707147553938113460256235797437364909334304082076369308644946795880411771023051918920837827172757245197366963778055847004334643305846979315716597225964170003140481051500841130069118218163552069161233468690277023974411658412783907602842758858676128576777876808394465952786559756769289258981765654853722025930430394486035832114212321026602740271567379510946932391454151582021323072542731581317926047059548395346152402891768765134450106764037367102727302056183730924370587234240714778299906998263655035874704951906404178390026419697687705168276571236257331740809572503462493087758183925736746982886782637951092574635875597253373344842019848235749913765700600949513996747199654541742013969261557116796642983655061691011232557137240023042537972802331562786419020042418341113035499891325912799278590937596646958187274765947742979351894746357702012066018679429848778752949833981603739891676642880346194679453728932193439901688352710771910260795966006217349541747991521903994831320852709412637682860454926621050755608470926771032024662662808668979484535065877560038512180856415466546499259862193476405169741641558438956136083723010586018530647822871193827380263080422598414116252242225089378072699346820050029179131877082173577186321064469151880640767951614451240114781754460121212472653426073666532503630164240908939425045147315711066507816783887681452164261906444793172902544074007630279912180710078096732704381499555382046051248101749826004778816567032100803755582749843365946676665737628349841447231033546100875296632527933278608617355774649935936100359222912339146487751570380094767157623871567895396293646622123844859465549658229890759645433127584499161221483566540839493937931747899054754872010108512139809732439267487936922267621819768371320002383953706105837756863743434174607452179153433493376417926721501980548656995554302941141890775033291283368182918879741164401034237575494692674532970684617591517715059957753921973111156302198404245434781326501014493896431469688055374212713242194360710322361925027715154902930360654565821585223892969823594688407366531335460575781292376698090577566687662820912819711459505940553161351326412038944659784469999828774019766066999728011051399590658711533962549752174606895339534188990059563235984811002373477746020227136148135237054925377015971551563029602622922309222440120220474161481211409440818291568481641827229795723648064391901671589677643728673589008029434580888278225848710333607537521151531322376592128881167702346264324658934695893203642984013861219119986377066110274596057708629710524893246261656205577890418590639078011260830477570643562596488012053033153125528754114697641505752340120016837734276017146294335679175710051609923524236621362913999039839415013147379042071436937125740024128990726305066540487327276457600369813376725551681626731878856650536696153720698853594362757887306882092065860789582506261592968827113188549569251811025432173427638262254082621305353459276038770261724921901421856128566950451469010626460114869185995650495711601826211244642570223248164568093740551894668147151554075419409176621481705172217130056089962927497262179185601122759684231248216255051426017199729539568440402407515845356169356485927630923559035525693987704667571404460103772942657489436761373888316997172566061776471001421647083908559264178634901719163408342785470089168287963545900872503396735467200258344231071311296984249284471653605404206774630301773858940290224718491421622668724917456332783414487632443609758927717219272583183002719937512156923312940436854360642032651247863850325325749003123984607667389282683726426165112621271072964692611076418922143980380917181979639195608127363043001477206982559699345572453913102610901978450386753995183143809691073926794966730017240913057367375736551053038837979286982726873226316685032285585876722104750900221289643445254991147297335551212279192068712014884202812184832109527927996018870631224188704079417304843702769226797129743614436937445185095771933845459638541527302898966524845867999954792525721352730781727588864985550188498993043382389151614573139135180726753543071253327030429990895470616848968618663875035938151293143721132188617600379190668529508170252412219763874297829561283291383056441441174354427308994907239347189926380215213383931360931741210099030632593240611319979949672578677061335625887434978528263292182891853797341555060739474132557544872661252803745804016301672440993440713909488569650864152999110552004983249873523799727172358133473160594902413624610238860957558851981311039236982614215681358529088842523682043979320256385944880098135912158019261071517082274376869863366758650792851736558314503210782303419711565757005018172954282622968211294876117394824779264872191974603012162386489629278063836018803633673356529288997941797680036176545888494806820015880031337827923641753923421144071031474516853419926011007132805442734442199729611130466600561676864896433513160180625991828036880531887515937107709458927266417756714121734820737129113303918692946605284507448800991397315004329819020057215949153034146818562347038314826836415695554843733422012330957657923298446368862813025199940481558214575099526226783286001534352152529274067250366897658275835262448222064062528992702098719137087052725650788343842598085893402182451943596298884270364111404146406399355591562538035558149558930859625891441728194197437079052051667174922316967533949605496697602599424321157764667555921488303595704258312047420084384400043833967548164731952781975252419811049225089277864950612458409227277804002941318558019412137844644361679161852990005247838510540809302760447951838330685513189827162554727818928420786754022178423173134889792990257306216706480436306045690493957436554987300140053127003813046584565980494404580526479812138886571495815874461487307603077891255761038121591214014570069667541438229603574101749494250904564876796400861587762733579394948536345090651250683430765239699956689036894514476723328421065502382203107649983905034147856043828651430678364160, - 159237630742007348059253776716707209076746310395305595310081456490397313658725784607943032369333520965092577829087387267414521641851993144440230240002023386201040850844145731125465582999037106110521241876013123068522089904030828559095694816251516685296080899962450735546597435410052100203171547538611875835622499109840982165799778524251322842545034850090580908529439520704766822706243437874767241685441621609729655262409840844435343438500905033917597505794253531881751846845978943387353559268838386427700083636138429910496232816881214239859276015354249635342065186585514040654788150943082739006614831004187294659849939855698413711342691470205107331980944412225006534598981958169845021588464471179221887683274114245488764457890265551836674667817443285135567949305674937615626258266846486886391242353395752733816686967240353615650316111062993067527076920743648206743981956153717485726919730021381674167509662414772538365526503663206701141082324975399821010727061963608114805836020431614758322162036074097422805291086517532994372960442713642624784159609711819512252682251152370797363767050159672106932790298851574794303158857567194808105465644986439112708276056503021014550118280424192327852822662634513677756137181814601889371468831229403434629356086946625964062711968314711107009607140904658590607676260161914909165257804626926686519975947134026969313215155992725675825635233956759080865800454880202192432806914813219320388121190662483435780655882213045341413356895894468920773224717170117751161952767219105418266807185590102170048244881605497432969882332507052079180241983389938006449384941116403279280608137949479987839842656404085017597021300790676361736742024332550216059389870546846065913848711466685545557662340558478474069572108618095477773183858173533196206788080231195539512978948666835709080715543829104692083441127467994338081057137216527356535983510217739827615820071376191312682869508144566470248922523789216604124086150594793706908738745517911031415117665122644098513116771471184972102150484827460192097647175424629415303091925948733104518347227394930733623469187082697711259952090794885737704092006376467320412114543332565480838870459712531690853475634254860526321230607432606634611425516276399844291360919580342609689746339868577428879267878190849318747074794253722454958309138605290915880107091256552294008336407603171933897949095595092507102138810305059828799533955352352835022604788516352694950842975524289889841041192541754816290475163132981489642412616677748258466329795280598232377745787114347540918422722097975563562429595682364153469763509669427464862250337780197826687173401497943515991314208428959491895878371715155619265361210372857568098450996648222646567445642982680917258968929356111719027315080780903805778612671369887850892326803628289468713302039944271068464992296107343072430724430380529447375911912449081563813428148038124585731108534719282230952959001116396077635472984672862440064753832344922031326736652138650005920631322470385247176170833387602888626553115344737685152045683297975584079597542306185879096081002325434776272574928121488862971919545475155343200878830090861731328641509584828324763992627224943628268001078007525490422004406798189153835835035505942645671227537750861992288678602670902823136241258790931349825032442407229151911876747337241650297355592605512289304490149650706077916984392792513546275002410301660402173404203182586892655130813140192770700390773462279024837821395609418471750517457879803448519480632969788375850838718542024585828753120404735970211558927267254426407621770546103202088067831008239153219754328057364332479361546988999415359017861499303595803546410285502093973623775262543908819439565824402791039553567995568403015869019570430423982900406741222679290786964916687196658643623971534898024572071257108629604709484260045496153483577273726763672395272830829470643329321480169858375643348432279349493439809663658805827696120117456513322610605563656338477308644135334512619914329723306115645297354509838571499298554509621483108075066345370589643235799546914734427928864428245297601162237468743303966420566177640004604945593207100411623734325339991064804709232069384289244244363674187655674044042251294274568541918507339194706321975674085281858436723938021323011907857024689047499544590874806391333677733960566110293059649549235827206264502278609553004594129696075144313369715238792096417636529716178567150855861247126406155274822431733796324776545942699058041121921252139837985082327873752194389725576791848733497839903669597087848723139205712764826630948967193290006007669968704870951865308903598731866371958174005791315331494931441119836401521585190736819949428940386605444819456295681762949125473618547756879612740873137098792849939339000958669849027109469895064914845173485482005674907725835214555574140299368926582328440830880840049954441306419399356798864060856602203704520658756669882246974723707388698094549630356705884216999430360103505192979772918067896286791424353444047964769833479245021395570610289251894988057049093783504174787409957138590218048998398561151940853103592546527810830944849195703500341762589509441440874459712044904791336407545376524338810244701464855460758744666879583471437393951367925541976946319121708458209401816994415599637762143014017516740746839810696044273538523457637784627781184470124906298241121216084388873985434169624330845020513869745345427717833391797976224926435567829752763709492685664819351449745747140771651480128210796376884603801080225969404276528290188125079264709676323588683749897987828215855791438546578151823802404605931717906062906258742762127251427599200986884539987890700624627830204304499297656634701505676151728190204535209400746105178690577122896292626403805300698647226426236619689876098110282113644241536218449429144950150302223778959651816725201878723568460406191161569162710598146191106602500493031899905146928958036050712680387807846840350987559493246019273274829265211071455466231141850433646656084187819420298319622047091073563721044832270380332037768341501223528112228874246910009750751339961715808535589726392269302035377565271386805405681249568140846689287851156284841779049098184696584150272845902691986082022905431826888342727594439341215408558066289985396800815569158909512489314753557454260902511031968233759660651995982217900575717883045322565695850555804760240102786924771958638903765168802008614885338395909265157976890172951817914554786050588547378351345505603641737782825196902784189428194798269465849698754519967976702400937813724214623234717698625632103003632117667192098841282924589887553364169480005249140697295870023453210368435569711615080176629340607978630867494440723162067992413529704573975554024203837566850540373170874307256827804659356624078901093652762575225654522295016453519110194103642490073124886610392928335724257994238315372939633091762886716820615849971552313470653664511125468410877263869932657344684412194114262450154203655956312739904622721315115728103192103225117442839886054319334061257446967806656510739583038850202559688985731066626964053853905688645405714861985139694920292878234100971628534255923264814845934260081661452580029266127426574478695626593132314190501329574228524370136282904199475164210292212554001965323679712173750863597666262832089493780071529255996980707478660554411405869182317046151889551360, - -6333475529289828961138153030042265409271075596644744102498324279288328942202665645439830547554820826845806445286263275895158847142164040067926039106027028475755951539460939919449560068228050993952299361920453489783750840185419059808619009091791672276958975345805132809481829708677169468178888056752982503063030007574371524745753543832370915049345916090323610618891644313239852805218792241781341667601235183262590237686937092831367426151489848662324410049936520866016647673474649974360083890268488681649134576549710604802645566624020369170225318719274852807958352481345432878495816979515927505040812201783511925168892389754490253997354093536493832845658833696517776233549264207360941792178926298959050119935085584603202187980536628446799298738740025669764739965454668983830650256527563651281144369290323491682204956293947298749339502402999465281902813739532324181290759630368277370457333938827098332077593168271441703791710774923260070943138226734555409691762569954370745280999848148164679037448350496930540629830646866513622767470735227930447613744456108731695369533820944814283282676992162465144105082641685503255614244249250736525048821894347836424216216262369565737549864945621084686075439397948118637197071108821362737727245213367210552313312474320635019675347257055122314022528048136149600477889675205517489321436175820178304931016080898246688563125995655331857100814193859067349548277087001668584972595562955637795908916649159090549593086465413835441912855347675487031217368362337182247660863329946123391317237387949200022515480141065161258487952340421456278917296908355363204824905376393183458973936666921754560726923234903588476103186522440064029704232222219584134051530564559660946244470638447864717039188449860028858048103162450841559986098288151703494609845279767716007753274413958570622077349884862388714067994895052657947377745909454305665353239798997718797642314977705274709348195381310263284920472747777744896489118275840680696833105344942993060685293387055150078828210524036575120823486087864452370906124684873707091155017682328204081620049333545030651152655580217362977191689410284191547674562653220475074795992841581931172641564934740813316484510871049683143521713521626907465855544452745352987339032849557587839954220567777366711205270667031378323897417497734755055630556069267831388441459057368611028995839697249419075592189252124611366817044796770952081064922371200074584664562104177378188709103228939575204514271037478604794244024415345707312824101446974071955567657121035242382761233891947192541300984636351644101049182299006490634026967700356651033526819003160463071181110147303525294519971945475667437974032742914738029014832586801512521267915931214602667185913189397697139275993414363243165165870622672531049352456824998768655202303803580470572953382575154136451721839634804210417340324157285998558986058475323316821167238167718011207720876062689213715320284549532372105048117791239650726237373710774528364093814561316776103506525155643419968031810644690138285298614628647040225865212538575112788177265573195857190199388607253725227083684145701198862176233051715913962419546978229839529275006095415225907893709270953402711324531768864849397943089830719964240388658113298917262056081966753512706854181772856227158117362038634565847897244834139993589392875703035130797032502274977971052733794112510607946077783715158577959589141326152260001411831121793067452426079898052699706998884328024499875836905888710483949469905383388638461159859216187768552040699937849482132686349473953216412716957092443624328418190294919532288961478586304941142325097167729511090647406403994595935123876735729190014647236876393637912235012432225601487147234331153676582899779357097485744900813020779715923720692692645872382855946343445699864068885519284560372736481994204469926025931935442127774495303889754993586414360107360326143090914089709711818238726227919316073562403045268717398095135059812035666097097800011040678852774328644236762348563150358220206980174936835046048576713756213809715902591585029320257935119666390996774358458648311281060141488617757276180282709446184043903433903609277199428991136338235068811989688103184707601382389793092830328394028265182914396627873561616371357245294692592158498690698485495572853905745622933653883813492499077498832181339502350530085335398855576775442641194179919955425130873335261085708948779125570078949652567217006281370238294296952299152817759114809840892320073728241321165751610300504486527276400850730805342607493348555717813006892164210617089223090995468054819192186616118899562499582357787766263451893020354140988140215736092910254166013570490905456336968174677142872975560149940434273957119286851609552493821219149700868349638215797155542291634943386643300085658728879492126092380623629049081437969801137814477498029968423070768573493053090204787847105188401135157353816201288948486377600804455748588390992811544417780788748398669279527874080499800210915435766850172484498777815658126115319324184022385409877940558934694370872362687636172128855969391530204059454998776505051498019370246463474428039673656772344820656094013854976372016816606421812073375812806416550844079234330427279867924432776918298295474917451831916378434012248496224062168387337558069880043655553487746160969527976413137008764529416948368707518850484144438808302710285162262335187726045933147260355980747659116237139216498970037385113307626836042692516346600737430608737853621907671350534082865392397074131588066153701484434552195272402856748338798803685511533147237153940439522815491143491125383053276611483608629916612806454958445287748597342964863924067015095623714136860805664791905127433113340122608962789624179891688092356799491259620677776683698064726473031174642945726779574518876797396361995806410592474721680943773914869135667723395706071161623567434459883783538704266941354161670959085085656920763258599447911039011757552194980299425231650432396808061086025647753198208491883963872336521289894634446141270538099444089480867995869684709004928596712769218895580203648340304433779579799415215613138768429174364400150661146579488627122199441318177879309320267238464133729682686035378174695759022233396340259235825635859251320168403583474487303550104584900582795974650497354009357992761800171120517250153271150835409872363869341741017554575851276609781230722569656558275421771357609286627758162530530418597060537771603695674226802842007038567213161688066143290508011878379770658656340617445931712322589238174610248448027737298193632148709966201714100617528685959224966927698085501506629171078541165463137958859914081001852056630652953213616716368372615501131464579004754860069708096859352831543231745325958882657473094114275768887496681172930914981681898216974469455876968887974656505326749086090926914799648551464833650851922679573588406509289217110954303436384641244789544369461476781133430356862463293140016813982676525004717349241030006769879075423472479628118380398330458732623532824942475793796151950137180792424128859080813245901831078057827642577218080247751986001674759508307023216788394007656412401883137510855371788728102534794681961960437668661665631599092706205820398621111830409930437975963829479637938938163804744537821307396118184104793375394363938739445754227372867914529497825948673575968707790399934038016, - -294886009735739231927403473520630041629245466502921097256199905722062644426473033258302243315988290598425203419129114604396973886476842798749178588623412870573245885407561032784438737106522969942937441108004127316545386687798940495637987389176247577984105647631110313516700323034407388695533158697314583398223075939786499085218206462054958712767305725800174858265119511923429138149655176047299998650485325521145511462291201377445342981629222611573773862216470905961687713439104702143814147558120495817375410800215375222932699065847698079042642292776550494336483675780243099057339889370672390604850679977687355341833885116755199630369856698421670791540356831196555452434215908654796138702005179618964318981138014238234700695083748618131131413404364196402591464654622941442962346748041368449594320709258387463103145719255305377467038564546424374310851197809921997523119333078929780228564255424164625107940450549122169377213950426239806340912731497018134973753914189034945622425554830450159573212052411508684599992760376132055678626357420381450725549260121983499652289806758584444213166613862600507955178080089314682888532172658567074185688721193683795434255425720099074807262798934082034681418123347239589171489830369270695012771357246778888556691815246007215945071538295070176322666475795602146763255604059301693963109890225717747745741228519578120600034098299665454155690282036684281201301469001296532947118244084341973220383476745421964011396212537041353479311498063571236171528056096217376330598624081918600034749124127102997290463288994776456139931205290586743845515089045518642544206011384742540964163805447894041987696783773340651116018062396791497803290896252684876969720229089712120103746835466346767781218031139256188493192401877017091542762321029997529183796247849076561869202967319393968286561634945407434807857005812020886694381562278468569859094297368570700058671504369996556392767542595441035663431608515551404696189341650861788157999585029471326351958663768210951748013847832806460181369777307096138724845614828931964350411494242783130306264043641313716142343511848664840377835766844042771328067294606917110360512070013926946405640170542074889838623860888680862382926346590058057443418028313312249701729824985470618714992034358118067085813729352249860895331788845895729344597843773692116907525499651481770566705874547164101939418334604740904992789220603171793720895389654395884080752276347942254212834713182534680449849348425720798469363391843110011701313143784773844217033809565591157615244453392258137192959974056766968291790545041623450137315387995069538146762076580943248586798858068595113636358123981843968838590744987799345118025159057106380913400781077459630483624201921327614291489862604609534224755801718995811147112915353370480509005944915674174366900032880923827627234252893818228960255569765900134309487854434328378913952683541153925472754358302737384140583947116859491303291733352266811928373340310915159495216682935120181959839150538169270524840477024219706484890306504004595248531458807739458504180534650702865897315448186616028395050986993318180529225022559959800757767481978046669599857774250190783540905829620841415026522895554062980009660946661927155956803680440526667009224676650339153153828970114596873772667227354746511916011604970450701857750784968599122758810218581848067972793018799043656576571588389778163821829439780493490920741648791664251079905167752741721795605866780099856515598893921231620977651085180219350931104964950760488938413640913962519075237223714574043591403095741842868475301919450669767383873791837474782492040611336825566655068415372240899275355216555727952327659517752170438540011248951103866075645587138829551714803597991383093644024982090866899987290498083480220869610629801304402675801730101500297808212045731703223752443729683885351655709114370783242405664207142851104421323407087874889476622438075914316183128556768014377753267910567710395615729807802825188240121072148305201803825144611656551191151382640851188235699205687641722535081996081617821922962534742934558924733162041184888141781711087332296566392974214477050655104314013151507990001661272865929805357895751867069615313826384125276514043993186483068326026957576577251756846136368293538546706143801836631849864501658885123292339955378576751415302087375498018039062099811340440378274515147649046992613501072116402505465824194245813902336979309774760624857685798762933328522146446307022098268382975612776168718429495665913181847754626729662629792791595562364266305091849281371623867725419543541007115122852105826536846496632386586859520525378621836863875881048594112040480466564449434622533814245317412384213505045902314139472955430846246361761987358256195861633268503991222358648861704003642742506515560402458332920625278442828154489598257658739590535426977521921744393519320693358430666463570029939461736700939363867513515038350319962289578978044525761638559672642419974913789779682962559395601141488647082344370147489967730370400226391598257244509060848403515894468972354094701666617809549648096581785141337291601160645013643887394966208494760036132616555487466312889175612307511919141932062080835296162265652513303425457887235470662855251069042849855103945685424068225135362614217374613658043641324028232133635465644096640353268098116801768806853102452327957988211823400605346450008695921256151754536557613922103241959627312450270832292368682229707701805157149298480424188407896093919165777499210320026906660597725606598857257035449484338143899802960834255950873817225425926432093162355561248290743136438703497017612965911758213247258243117955498070377278259930053348332160656409743363268755100627580649557980237711445134908338572907842325178231302000822230424074041113589647302302849221109237481805880012955310230675570662422897059742323749132191792346006371463490012807875659488340955582732797612494949276976076100018080942823799199423560382485080244117815797689048376019008693118644839635420869351701497252260368366583086514193972269330164321068228738508310128538171767576729586185779041574928768273939234332643559398126576067237259589379798469419463261295581630673009087714418986255338151118046799939170079878373954636395510593381300006609056946891753361028330812283775991928482015459433073237387017900406183764212638027226503555542634047542449443835245359895417535118296904408851794522323150446146047167509833698324361311504470033105665976315430968020386758181865427797628496570056660502506083687315685388507075984436406985742453085915830776497855646451495633947689802266218425620702053058778075490976807239353598312895314789803596774741836368810079942681387677896074014006849020752792451787825870606346717362115425953757689822756766347229404873156466085073207425990152173155885852000315688431830728245360553536868171396047473844703758577084688812479640183800440482171516477092267163460603227495575752464524070931303660555684285629730600419888230504331522176553505199633312210080215258876707926942253598513001690723254710954477515491388657397071422406744604473812898461858354926162937600055348972751206743286341838754538851226762977997882791068808613819986382030672948943957972819090762615300911833180094138640364839189128962072589097404405925713045070493752985347365833725455083642859010830637203456, - -6120858863175788875201740850326288306173201459788775365356341176336230260340972474195454027421350061510230770851597118025294342352823821252880511338360384706561429952959935593588961384763126652491565166462445631714014125991103952464268295653345305359981468603948746636838635832915808973073150384377062520232047873972132045246706737824924018537505785300036383010014830635374254820566377672264777690163901856963472947052309702788705228236314034391452438853344012939244667946322106415312992658142874247080954182329147801549221373497812386727829906349587861025512000934735917545926287079438467541345857457086987025620617174819020837053635354109063238768520861484741875641871894663947177700170940339680755368701140804724503993082478092007272685293916323932524212912719172076168866285164027061475213910573758246883123595562838334715358197549162835930211754599064679950410726550847113829876273752158876141249249920941529101869710540051259571608387961136964992434611222589383038297902704740003721313989935469380736704401404620178655398072724874022319331271480041672357453529747444543155271518913730122166668523768462777552668850400230172855283188803178956485095519783549317266650922241543893714277264230217462609626889536094415978460191779439430831335790561500493836710760558808509899274156903430836564522795687242910261873401392909235022315190084290222723819763530635590642556820408411578773973086394466713679062545724294609797358899517188398502709883864264007686561278709032536050825425841806991746868505161947000350354457926115815010655308060608837142098486279112063793752765480586959854543567776200144407944030593451869264197059654073951725642710554758837500857760013884828824598353496082008102782142308679329768529602872076189716739717741087172591605495726226642312045192445999200749278319634701504076439610873306547879635494581347852104573587162921978596737032161525965884601792772480518328181422825515513718484515997598735788365704028254437038052726004869907415002395103854348621401294033040174325545671815540959627396976738402829179919037593236620571716555500329548958468151192594217433480258856583050346495323155926496057400183039994891304177099685021585712447882364930916200668162516272415456877748364302955396904743424602334681150502190539513548340419249174064604964800224422218864244133081212964168758866650664502743804995331284410390668114594807359204642083229249704869529024053609224153279505969034673909762087350268595176847222433618634036766970524847336699929202469083339690788868842221912395705808664722805111605000203761988642292212702207332074715570809861452684390104181339575643247859883116401216070386969396866126910411772389157110911198428127156075524171178319085550422718546029228458282221531380608325110257789310656080184270423378597168464478539388958463394375333899862140994969627148822544647397792399743411506892285950804094785738200687441324421382932719624517851596346875975303651701501754006516669144893137964459704221089549814047694356125239536413949976486711480728782544382679361744730685284929851482621652354841515949380318035144289621343475051516244960730157026238501905377932129527253478523296704310972252013548917991904696937779779858745673395310666442822897030736858306296951520196742619775743038777628976192958783112604245299079381106861617314060707849314165860824872520968865786651342873279248194831404569522330128306365069635017186528412258659942641926591793873065900064795305539743224189036452268095172464108930691265678158010445407079969225812834678965798223764034007477819923249328079896097804670948633155765883063182026837897010179892299708540683397037679533788387085186188744873983019827758105468585451452188566668788727961730512271977935796898393281062015064981072414072640961660358401909896335724960951592082924872630909784189215426319566633799702893545174197404635965286942940331706348168287899011983652002926915606678319886871774429762415876064647437303378941081440409022717677940538705722184265946855321486273767081437696682435362580879222326023944793360328922238320266884678831479564304560108324627473210525116507932813519640172286738538045196576160346485082508228440255362796309287438844079799960023920679341062569999865466774571545327017858377203546171649860279761818259389045880101918677470817554556372287921862998734436658063437727461541268767214183461682448501585939212341230080987036936037101401005577231200961603514221226951202078119441869126790540601588972724767400155224918711159696509473159704799641640814422533285231858939173687052447294965113516296445235779811680592529535252342126290828994101451104807800926893241601435598346872192361344658197095003779196884824456698236398191644874477021506072816197380010541127697829709003065683883149551287268253424366961161656426967083204939271142806348404289452560905224350810659427757586568564478978752689909349495720445145634785305467104086534873490710315866025863755474503137803791680789128345404443392372264299246316728059606486956859785195636691349245533190548769420977110899376597186151725876069932771213866987487795985755169805773862182209442718423109967122411393161204749325447233859128660951774128217579136578974856374725737212700712595511248235785609016041349111911864641582323365508786862324105043227656816823324550278165072112996045465946127357209578909796408713271422526962478974338044932379525139635518752272048662710022411005932552765725580912502105779728345109382396196931568910372160275571628854717058981347317047163993678183836452539375147610790460179809794674595804836474175669739098722875109990890893047913868762036249584389889592439873734999996932318684360208179368912225062055450391984902479187413888785512883660361210759778219737054725862401847263764525411774377713339588224358678995336564029225596801269775744566679338540230272662294335581046004707503685667505852590469527146153676737952959924669446087677901485647924729981812189696797103894184958877918026918920008410510567935509436406825678040244465252850199180142332594312956044790111701620265184752518219764547004403928275383262670578202253893811987814417287354640963280353033622206385950546395220303267293005817786816744700079130976839865175943169059046135044398093579305896775630434446156307658058167954737913549280821912434687418498914458994799415907631579808096022746628444582258590057132959136139996303383987910340249536946077504368420611782202824827275145838931585935481141944673249799097346001577939632111408056996564352398822127605785811307858100449155117859048142750333518064722284366465468364933421402810676267223952895497549099643412617170880081555640578512557783906734749030343023648547678179035552206833204345179687486786030350478028847778664314596559998150466348919413272810890708014007147282599477506619879847586438646134129659802827827021302670150625013044830141738380289484669742699289467194361414701965297234645374288817220401816292624683595173695360822406295331637513755096187061344221131082766088574130485452511946868140600700319949974839043704873437923286890265602402973645373853402175982450901172446813407727182414493298285156451444431797959265305215477159501904584364575455134592300969650335250485287394731929424586148504903452321294770562855520847467125293544043496439959736323199022385369184725602739945472, - -42129865573074443726811651412654643639757839519683055145308361920411337786716202966478768696270601098627687803564666388283108273873691802580486201188948902162453347552272915491560407600502318922856489495098136873105287054920138486634479260840246568226862446647936173671383237190741188232502819890077071168330309759780960936306564258300729415623556817577395399015805129110684807846908682746293564279382751191147478174594893154687512785249004779202724941175590441474851940605684646566769498052199916148265516515112342594552764848632693782285923468948045225112479001179544803761613379040978985020251239936029769093966419833363098022537674397209567644825144018647220583378655037168179055680382176659072805181000227188484032192424238644642251922624895297987426757442750120540514716618367336297386539983177793620883427393554312437197834057696143958133738065765986717837546053094746936018348429112321565590011840357236143939929849169341976874280582156851534660403304584722738595151638684389581401599636324033950008547904527224623699633610419311803718802648781637143381558728593398033674287095703954480426779464214114563771126176377652779253517651119709579311994595880331863362534209212232066764583280858528252111414498386508724390025568200964906359481076350553301937744574925653656774280398623861884788873729730925480189983868350659551678839389135519765927391759779076467188652625133896866186370906781635668810658200300814046172868119860740323117808927564972382712996551054666421650824756522257454444897123202551239297423532789624768944310153658080146487074106214347206253658223145346402272099637138401505948364825245489832054862083493002842774453193783397263133329960018843671733881416294451807596635061179315197553572066652809342466943693951564159356487244569339607247294463742993103788512116371977979558776911441833441043481532020239997089252838555718792386928488280902208392552485970872805147734017683170636549443421125612227318117668618463069458913870132200732802858061181897728859378916289011339132839362501387282154484905795649144957336848928930535229062804943848852365118635194272261850717734312016840730350431211936198887316186213193767724294882128413121282751914057256040315666040313938391003819804703318463566922891401794100522027353237197881822981792364384185174432009838061639342860730330997688629071918814958571509116234484671391394991134329020435764933313262558739532519890492838442424806106589793268324302761743636816406631468815060981630309395698096909579896813635033868437215364724087747726836140057055034681034440668681591358272630576894112873127785276705151830058979754253459908028894124352673398769681651572518151035867313329823629447868924784740352426197225258322308191482388410006857093640869124927470220831378537196442972674555817360536731820397621156124455100649277135233944603043540812866656948058676471962660743795372444462565775650766967617160331589627490221808293678108734000204338797865766956198227860266640954513272746408411997356956002951750758865983500090103811871030259642612883851177511674164124914598483103799684569654778026759210838364482756117750960820237429177587726406670226950295093591017283247347109736703512970456963974813218042679948604684141277354396590731076499883300912154664843252527530446892365284289034430371245540306964265736414907756360277155051092287870522635176475955916081921772544503535132290322191855113420169075067841342804609427068326658841140517496052723670642427674553491588353971754693584320560840846082875522028723118987650149586290627480392379882671447760547912587133393718648761694014054245052976278659166383460419115174791826264298101410042593012698905174948088928926709942784232402295373913724341203674676684298600489615540729755538760378563776347440263877762103627860365868679738665328643009371811148491940087805409858532235600146930372847345536770233795120422064284926890671757518126337915665035852567768696268929188575060319772643875694865192895864018832585521816607077494981643644427439835668635430179305087031620248606629006000408966051667592586416938367331304262930786478812493102634823782971935913597715490198418664941095742773284951387231791930246081828311692587034804787562998397233990322848685153562316841502856728810834660251440359839136420608296357201672230027983378131669045054962464398026221483684928101963217440975892043846541495411840508503436260760876870656043506707930568433215041715603031035881435130461438076942025106490803251984829108717488230777441086151357230805108714746379009812183974108606257527050848535209207575409356155017815029434376144695921071942252692075849485149988362650411160063295319175961017240680447152662778916893286086902279391232555562097432479788084948420119219913101533401940967299104810591200952971374609717550738044322929323635220358977684756471463190715512804479613598711977558504422597044338790297913647374575218584090491302746965101599559872041308674890095124029530809898927931030793367555893934151990917210356304446245048062464409161233515763008865795802793628419420815433887652862343292957393839136641565839540518981378261044798292794283623428537440933554680477082626431145776032588855673652934633323730575379932400288231803249806234633759321326061251853559998770137169387341997449733959455555871024228310868742347600731312436229703255307400637239528496558746038796565564555933158334316707668511304129193221946145786474688751176922152471963143963964736788479832449079023365402693517025075020954517641494278822001767968950044793521981201980090477813767878341738083831885144603547515723914301081970893644973059790496953109240131924927231745300693312459337386395908600313733002981576692634561736836938413647098361030454322701256299677520531315999256628890337740810106619374267696723788444475386999254326469512268425686053501436008809022459711408633239977158977118916088589957465925139316008622599155522516960630025841495585703816917985230919846935569672273785117159787356042031753073205523539931528872870700971373391426601751746716837016095018721447381337708947377079714386743462174312210300780495212958621794027121389961984532908006635787305169840895025986455802706916197308919782049307034973745639501132187152050374206744208836294149974607448878459834220437523869905512930004344332537627824681257295748905212805899143840462027403104449377970339051367502731642864876694426864437544941139535545911619440862041304038064375720725059809708025236348422263368708216281078093187219750397935739489569260138322851241895684179071735133474106545278554494282791858712390399315979266577292752153977355415985338086282908443953454572012003246977254702611004034316253916841217921915572910217888848269055183256461853024616986492294448425446295356770805500693954939903909710359561182750178716893559972012162270704270596256336037620125060219836359564295408047241228134598473607206910293800858736014464572138727145149582630114442088966318609995265632938801950943514791261927021876446977137656203304554746404801186687024448303087319536386323096038001718636876017677315629783867800493036240707897420373526994123108305422911867544273308270986285400210696295468986229030678529206460899890378499950345672689144784298625671028546480291218729924194781377774315524420640146005983328418660352, - 1709218610674635442401368082081744869999134583781740933566748667776755624703936007080273063946969129574285554562510938216200540483348426524606323961048299925286194786962960572950883745280273262731348829798186594040412603674978709634638402360982864496165377086842538339742647524528181671900316269042175011477452222719421337934160777796948304240994348994097230311781459087905838773080514466003070490651809990146928157800723507320156337469784668801399922636890819030997811625531194064835020569421789793753505846971994394888371317600967794970789202368137860578789610674134558918444676137160886156077756205705988850454590764543460777131560066705377009295003737213863010127546765213398641703656451435905211313940684884689096103101196481943488704452855832745312466294668134518484108687976997677983561795995301418421506575650967127269804978953303542110190931016854567105566155591085425752407818681575663303021844661197613045711410119099141019128610272652243500091334028051426664463828940613374334880955105819879785081089286247287745799290863674595386838084316413608689158207487015260230262374276142337126398274745844793412458435798883628153186527212168454270410902878265516998767091746032856663746184616755241180978103575189553352561417049139305804545325303263649752773937917168400356490673562605895880542220505568466906924947528042592503648848224409997231495781189812760035133101912906850602325984328414085036867762183683924711229010173034921659440338906058790289950587752965616693146313558785189341789045624802961032166241366853189785763660455566088973778581834119102261624251038819614455767288812923005082218854059652093912080705149159663184498931215086238542723187587664906533245657008766254060820283054255391537444359104785550398139647196379057886825462257265834814235784441070364553254857252274050225975454227703348584573650367812236033723541550696998170249294610584416579886157118615272787514223445467580893223420396536214331430305851581559694976090137587313492255923682600308710182054969227065492888903669255030456894502004348374255964696558983697558751662950328516789422935694520000627056923757301083460591028542102421621625450629059397974285362048952900849862257008513100937868661481420896635506998210436910405958838014853285022746172343925714317952899291917665042935171398457529830726035644222995866122271070098241983581220766238405220488178462517624245459283850345855232845171298998074381412146837547983464825252391727938182933544702584755896107599965953966936502355155972088141776385638911566250142085623863950856445917574170612362286241051325590783459600004034882282936902586386458185130278841270036331690766020537836433871222499635505451774212319697915811615521635351399389617165191723642860131968365123543227716817954821100469171734940297833685179084919607007888766992294729812673598645719018067325030677526249670944677685440550066643582306442346635042279501609575191578341423178896403422262102777285344648556506989205415072200281476887535745454870728258060021150435019508924297515988407631395090483036179517006607138610895675587489814767520035774555935169389441402902923001118429964258617532593977152723163509227692067987595500267715382806045697449487576117186865018998446218094592098414646846566669507721713275370804994417186007303178276243110900572422159913828776084578258296166559336138139743008120948511807607093985734488509591284946839966116293851385156041089369111269732008677161641889434809024080758231568412860575403298568984765499504972876313706095068813641353169286621894489737412071414525032890017687528617643672716023787050775814083319814361944195793407112489244189426774509158065400869523107049158537566342782849762462188562892584367657344928057990260465435046912651388092638081731770364297765316940496105051267755741800506548490669379169127340493510856089527317633907018650048937951122147075927607657385072451002966437861800361346165690031991778535102847486769203738794258872355421206258335802148653035939253769288302259666325190433555389856003941557404044091431319986589916505464727552267930156783084207869170946477689561662290998027724696393819602069979408046150409979206816123650375989325295610519834542687976964021852304395117833908578268641109621274146869963080657502753381462425499075975509123441097658043133251714711877988135654814511453316386076177689716563218728795963826943038540392805465048352711111365827335486354284675851744599183243944470971247848463454898225063580444753150809064030257423639240436199005717954813435180686562642520739641997232755901149818230283871269666552007412837703338096412948395348382857904113143711230550124210650451605256064731513661240822224843494627351115966727915815932568112942315103042081967175721948946679648468387687589244187483352494179159984921823983486937091654710698055330766857863182338557023437196628344217048417327058681535327796029987455672042629541115934838940392438267412097794594856433524134683725378374577943939927657784627299867881949614389395273588971948169371562593955423608212342704099537322695569611844117808384511126212497402355821124890728588943383842202011710501085188370564384840419918039951798090993682355656445564746886328979725200105791051016724352055550399769670191569918552185347243734377767506633607403184618396195044328695558222122941558718350311376678954197379062255431749730240686247182980579123469869800559804339905980483687724289454747190995879740487094823069265701539219343716707280521144340748661965761770013104845250753379601201740918011405870742704878142330769877567083041653798965962520676935296856573083404453586585126774789146980310708846046341048760067923885744282336512843831151182136732215999114044353657733966781126211695882117640323712436739339705087680411195275056385114771302685530523605685009738972105693822476658330094795015482751593391183114179101913197748692783961368577660637112424158285323483398397603899514003220026898838334486786195901022009904917116093009167834013485377950558671362061196653374898531598142651044882248320662332709556010162481638242103356970917927073629917570142062806565775700115581850230553868051643563063463985964992467099074343156219049531878834614935994848615556539216493646714102838985815945487121752121190645599629453508067184459822365264873020747178278523707952902094125267088749488920509172832097547382641877197975494963719037093886123552597131489190492323379874025970935496953512743344665124472556653665360341859793162491299413790259272068603802846582215707836416955877712381557079766587610458902090884148247658359647266738423644891036322139692560804887713839969448137268787666264161850098435362223066733599218300385376861244299989813750141154688348956555394847671293570855408813026997408052240302973643208859133724701285058746346799402505372272318767529862962810930033929543053499458703927623164646800227191697392826730068012386022766210595902724871701207540549333370648739264366848841089853833084680803299795229649176070158609446799789284269513759297893652375131482437857289676173179719231738151668502457830517034170086130475954382453493965771286515286419408972148626025743803448788886902528345899388630393236246624713112019722428239049015912905902385810426758414666139463819779119266756820992, - 71367021404206003190351752708982984369885456676222315874244835118559689791671878087998971695964474372631406223142628254900699026475923371699661192367675413083270995342823561488469900188165522125023479956513476905378421941077101764991279522314265152803993445834053160848205110083041934778650206661737282168243130267679714585389017501666070446270274101791952934871827495844719366081807221814368562768121218436893761912234724181162198779510876879189923943639746722469406066072933130532841363816795579637772394541053399572855952250253934568161264346497750019718312273491560759999670875855288322877600463390201738496346415540053971857058957127209153110455777422627891126027614679711140407229010316569756851142805355962884765763071259685816575782647266421734255130323265291747409823291629694340094769457236752380691887505662585258972620980398802067974955526191181955589500205307835881757568385106435878934511925203482768159581536943413974936984540475897701732822786149690616303849427379611840160416490919775630122417778629442045820956083088242240104238245232243270975022778194181766202854541157596918813412520711764479340994504196881243047872842859116896867640602936337716952236255361592952498609945390602549807605454643199301774451286025864774168075720186772924335733147470105712029392506127369593903922796318075664809631413960677632375040711156423993895162108149866727009995028086655990529829899610041734804721701210444610033462351305344971699396102353246511520107717270340281110990024827607214081775311249839671724046281590815324496169680932407303519044022203682120443302613130979364597073505236255018447599129344498539818568401042123023225883954905861525553902209785829764614944825215380459890247900948615474244339868508924642618012033536441317847297300748469260748688126131902196000996439718086652591052124439118118620604379498095026415190895494908769559831532862028639785291989154754826400852111237820076654101786494339031750618474332140972151111949504077283384754207438520617172387030070073835051579952567460864109520598660131022536545472580318778821986022061045375439538830303336901302221186826991556155391643340838055262605086824034169575403513099195095933720017953269534031035184076231348491366865115032753928886069513345297320160668599451220967935457093605346316300707044537045110359564538617361171463943226902380888043108040472647016639686300992524334122721591815193884755645112361648007709259358895206390511210501350131870726946266003692194404478956280957920612005320955243082427717551414936576612120946189101640464372219574879144964226522008514879871395156883880257137219375395726771975359668500214911943927640758705344196764201974102563489596627412800902374876273649459964210720491554610373787142819091106876310488792110268368502338276173383908290690719996210954832204597920708358970724882238441776925570746022635616000126145373946602346568990586060000189454828053207740653967154921440827786901445778615708142887367606047846945464131034527194834545913778510366167829753338517828037810583515689811780158636546441364227770167816149440127051222145789331374971427702235408538444837268361611021844986683801323317244073137453646652491783776368479068290940680752992981739530597038731993124051125485431863600012952855009606462636749942699250718750815480525413251288418730800622506308874988208852003868536302482894951767254514779198733419214677800536061478797929044742364873488172393475010631135090268991871872123132873898566879146604225262030234518508107154055437829448150151391135161599186056962827366144353508550007829024445677615652620191501113264608377451870432626377774448479890589238941031880155013000230049297738464898056189074755828515368169388633718807077144211681509270789445578607386250935713931666530371020439189966773759679606712202189675561772959656733783274325508541871471177799508914550427011569388204328052213972441163056553299127899378127548385492755913911822871917847525699236458492218546302619269374415526794812861837237116410239913681895858987467532773322647402487295254280816469110150933554749913154921912529275798257415257338680116202748696924655205794043037206386436336583363887704435111896101408196456582852435452804565353978104210909830966843292268134795147875046802435158098442941904914450806688445711415547750317792222488680175541415146779501779450434671410267293125449621797239233685419148646728125839923286111372757775486515103024265818155468457152344816292631759458824374297192645187330886381106980393140155953698949824910110600089748144307008677422187176366724781884620663617045503061602993132547345605190944781578970400877768835956609410386919025445242942158966309609365895784717257430022567606672437610533293980271690203855623283758918791865222958230963486412885029481555539928732299992962989680021849350094101386426420739447135146184602803426284469365636785805930128319371765798781922473932204791443877609204247988494865284006435990662000756748664601703534590070956626262391251124356669759744311796414756801792374487525957087605673932740697861380695258434198442482544975688553851989910858635437701302956132347803675627590591332062134374815162582158826709591421038007460385346813662279498013669815063638057225253201518196286963522150539214274282181717954908532072658059937092892885954900735026367523962146804784338410419388846199096292916766934996258965258798901466963224361619122777520231063926549350400240115146696782564953765333010744667235860223322301022908264489965000394086460079109828241744408622123020264142273560924275614477013840544752421844022464626276618411363124491043289921707923436453193523076337831059764320339110920958562190390774578854194024851553746759868742848150912200066436120455167084572235142038661656499313774017437296843835268307067181067494063020090042021209815917287541241679483062774797594349511866343566252491255805490362621175951841336186072111965261401896455571453919235098224960379158302134952237582388765503732208685724603603495259572712385391176700722767618144389906466864937859262705008525074006884946867170377415202838550278705057977693514128054612536210061113127503601855407149329954155279231483107629055613455183708471665286578075979980973979807749859862344583772284484253393273173376605456617976057272503879239257524425322121167275913436232981469762068733597113213896228336776508302140396765900770266093555462917674006494124847983669490122163077652706557629152748029474568592462919758822302973296420464996987535470333500354288532760476804203660277302762229492249804062589804879282860505330230869882826775801749811468401488911449726016284089502443966632223278314784073278157768646107084817675958506250547717662364744223829721747661692667177336674314482499646642946282409941131615870913929220868961355100778594997099925007816558314155356643311103316145971412130909947826830709012566168965417478861245890976147242326946692002258710757843846832889720827039727496723868234846949550329991150175915134970332349499920240849901475029550857701874434048916263104400214893746859544705046691986840856788868154565035549675482652257327742376483690111177824404005144871663164794921389893048801278470603685035389988727220530014614256523629687837839767633920, - 1322459690099967972499711735481824157372856663802818503798239273449615640040743638703169799637914662198379857956021270422854276516944255534608476382463817487554100498531980688413673048057143197626791407823188989267173993630490856550878743300695788135824054436750370308640681685140929012491310408752945680345399635920721749150045366799368104428135167624525056479972599274629150537604507450022004965565318661654679207950912049877284536896645833498461347732059106506247815639970610966597940298324973640509934420174638055877320545986747709545011607345036453136497758193736120038884409590109371256425695581871486548452779775085440628218058904354145951260812700157773172928913132463031783272933913895436779501512490747755938541872574987565027579009508698549838009380816002660268549518300234771170613217484814783297806591657070628708839970826925692758189771263448716338217985660627408825926007032307810112584985719380982422249601220052291167280430857464471634849397622640841377443863740434608237826472133349838055062987170386679246640012301485600645017801941444211499167527839487965420066690050127405343030401723116444342004688638604674726138209692752295636900589991165516545420075948067384207389084927714702997100467936693494425747076465525839720622061034045191663769487738973398270826108040250280530706600267659646302597053951586644509033698498988797935488501353214247033757651387051239685951582302729398389156881851552882733707960629338365416462123814077259145087526362565395642385749774543240491675514219208972624180442478262263038365377769013882063189854299815020262466835873052969972123616820955693756858773577457014798603160966700798123223903689131911194044418753087755766874529650471844175478514451816489095349182799814822692915911785602302476294316804788948871032740807151618106668909002375985429726777392963887125463494897500347875367426481243486768391074471649785267478282070936272321293660974075191255152730567129426598191997242364065805369147158052586604880294045652189187016435029807605277997843061107133983449325119375399301263658998345326383924396317637924449849734511211226295659072769652770670893650975726238125992274791479951512567387024661738070523480007781576123675272888889104221428834114431603414743098927174283545849960311636830307735376200848689257290105481071201544690565942893547665233390889955179505722795083712856417296360285428246829116571770488796127369535394985415831491778939830138019044841383318138093552452449816587012680674896146705055226257302568605589515235607790319724155101107303371744506611704372056615541778209902709969388813866033466674825316515566720134710993354441207576016440386243658728114018183844086344953868737814871862078935749658564281625107131208724511875389486660579483928141268991696082837197264186585279517811499679245254729436065812559461775255289567005961854370729736636177866545123733749336335720862532881931565350688876630977131160822713388235283909787971084105044205595400641045977610614661460136398726890426081585658740857159677401085983452703933376512507675312833549294447025253290901646890075429094991140266353474254627002520301883624945515811469020627471441284134475604786151429396037732932052877912350388299998347246066097799578209291179430729937946538665373250304107265887551596890110415276466026771500043224838794104480513951978171479175773286676833665484943553450491402173617305759194348664743213620640865661081003472100710760325498510677009122020235449639638392469150047244157174589336097198784928318436717998182393436530811399246946527942551356997859695850796250017327749972581387836719725898800597639125427376396587399688929641359170284752432138610390713114105331998692338485143420547993050158846563165502201588505023430992048661353690996599180061595126854900912823782273193975019741110446597888588906494876618200172415359671405404955068064812560237493639238866277390756453167931228165490292555075460232401948485759233943814955585165364084920162354682435989330015978443710497260519842488768624371903168822770160394756961154131954425247844671719889124074654557499892415400477559967902514310910189671782818637975152480364757603884219690840198835502332118810486084503898721035149289900674231820922082462352869981060331860463345372686940240894923424645585964582192639524097153289711992038788985741779191257051260874685860685004159513930461894250618898654687210934987500347959928622760632971288279751643877372270830689165137226966172326871957479374811623920453968786933704518193296333065364290067426435411493402911238320067176532450257048197848829824551772042276435481104009865963274310097785040636014730055624046104059571905794703112297163889065451535246232412608028166367602268700751153816378773935529559451009548188318085733069212297179377243602671070678542831617165547770935218504990683025488211811956836402384125616443318625197679751383351648515942683771946401977935781742846590725805489058136162413213524446634179331045675482000006308565203319184454143481410136147995026993829332501491475669728311233756630673547211107359710609055196919979273191968332722846605530934224446164290408984309482721820703157736609004431352431054989622162889883535101583002873824240038071393390504396312673532248428461121275430157828660699399534921820067047113644909269592710739086923891858837395393912384243046322616457942852225659415959462596261082530716452108948055939199131973381579574336363919835969778891790177847362964744175146130710376937535850397289772711561962341076709045060555765925115392597451282097347779360976721624590390590600195190683801286968435708592718426583790951924838434333463607679820047651980873643791249515968948844775968932022007534267562325092526141580437958105473726510449778568046534861163675410779205020481073709495838317041040171415835083359106580039416239499802436345720149473236012568539385150511524391872273903837295813918370109868095344618444695430422423797833227512272094674736042222092703835397835869712183459313608767354669112037029065084189431394541849154645483528476375543457272569180332422073554793529517682369584772649949506041244006130076940068457849480456368045150530494899747376633485423272387418351616254807000588410450277654055014881648379258876161568531822420178343852738581619545178333006367581210020323196903803409080947464218335816060409156428952852536288187169270494349512572729113674814208986833496065561035349880051850705504083364187836662529338196941311124194016130636364050848373964405322083022832838270315997719187348544565728534995569354167000020164512056783712882887993759138147370932460618188325666277401482550197584516397953213124651367854096021751279751536460786014485252758598890142885997346542913358838389322095554087680764057240634334125287925313945997737776711058646271725362908541363166007851006948585858672325921497093761326393265774031531656185408592683536529031893458892185663406803360476199051116452449757989707269066554198308793633862711119283400089002894216277453063555955031158892168203073129736601618813609189700534083878508153901444601959951549948271864941287106422121854310700481819435155210704050322547615809974139782001707377136065544485826299616473547748952506368, - 6742500778947240292390442894891753370649896289552387078875296047565464914756837421036076873085735879729309871624112965422340502503616064667413586591342483821278807652532319962558930622333473461701787234680604405434282643364279670557460933336105794357191154461277404102358389127244954102111112391708267494973351576991355103584655605830986008570978148363406217758757569814910844967531822679755464240085737149015838277371276534799712935731506529705303971663148380256985564606280462964458954534902932641567440728012816139424995103435686342573465796430056151051669815746505964991099664145486135598511141602414724730742207088974142862780012064584153694471132562261451343538990868475850960845847982408136868177269651332752261396994095202980430912681515313857805924400467971101700921118308335100190201652971385638766423027404689407647096829942777950559382315404145701059448469885933305973756952668177066453722340140036301656212111674091182531716849639918361592342672133717287061189485953748136796741697830200758006383704355261870313598470902410313159877301851198726115157110313141159245728670554951802964488039934156458113543823742080900426338097282726121802578077780593322755976716202716562034356656070024340664277424126589985239758687578710323895540178948786220103787263415673694188424798235306045787176645764523623912258848406591501604238491936043718301315323503192303640776455555637247978153966468153892066879707063867179308607185136899421210565990039252664370335710308475138336162866239088334741082356918725812563663380226838599582449616218964946782276803978852271955755138993840892549834836170525695330506125593654616358599578197845913628759593584698022576833422886709891814426623186657166858752339034232996725297442696403434562355933499821450473148004882930274408828501990539636957595068695289570598729780600324693417455459642775470761526807009266860782235237626827754181536878522031050221956776277084977355499051372525704610954952976268478818156709009552946561003110572343899002755109485744713912010846768503017796633852343939257712450167455264968766293326165557199413828152746951780028340515711993549084649491691435594995524995774755083779636385511277513777907132992184984366164535637925862640777199247206639771615583209435594446842794304636497065005922671994000083880963690813162917556787117624337148592845929670544324333276125050370929636202251242200571685516491626181634157240133406464789198251278545428668204371460835652766211511899480198605034003846965067289727291789410107578380982891941144128572868903621492350218721944376692456830874813717629157610264987534990993774479598242850605142187820077852464908478929092573125579629421805912399173156257451245332370077428673882250099397682054613454800033617627353012178581356208284951064161447620796779976382832100597442649805559534174004399398957507125948451333918637326091162670128356732520673861481547836901961121133542472180372977598414033778466057170470588192058732702423297484190657778282342296246059699632196813297455584653744459865342642013800911111919051795433191283110063410356769225229131839278170543633355175932811432067977178563474679571441200550065055556577636472231345365729252038407572271284051177742061409476431366724830053088497952100057625051349532624757413234225038514997198918321585449854188858340934052905406948127396902503961445258305798806371093602214635140574362363705597608480498187958528359681479558916400064232695069314212688303198364189360952263811091818464451596499946693946066071928893545792207682844979455461985036107536695611001899221409062979033015608706943166263255302597260234051362953295864565142138872230951642220547488419436596357130971732432803552811146923011065191710477230117867567182607508928564938011804588080885966812811746104640205420250421530734935997180041801079044529103445292871380917087027348660135135347561282653831663018450260816777535628491429890593272647371714646363903758676911849920498566588363504748026039807998831733876204660894126572456886601469481161484764780465688030113182567834478699333496378412872202256991263082855559185695655003140284660727855405145712953447705745290013357299445304988566233934891826949774769675196999961500207659460558048669439931173542217906306591262550515962503479455686452043689623533862909831894502970108343442011238440411372762138216612843885845677738736740831744292638397182656005364478530863239135175693043922042110824121511114562722580188384209309484986580136601805497100319709174520828768144507492612301329151253775234815215537103144690809511381932509723031496812362325020769421168077055800431068999757158065899367613280939688174135228296804727291104843425588338058859450201823900335481155666687628180277530046829311482837717616904978508409300635050386739610831037802652906583120487604540029344316739439700246613495658534348159193263503147616962249434783929645849606961744508614792796218096119001750417900774421519002678575746042736258423205243592699806314086643230146622578588577546730188970525482421104239669479424825288373616430084334138706634983394166768426786492178169549968378696604330095915840216128921687856276806352577425710267157043915390824885618404036537857577073782360500915150707435201332193908244860276569304432912986264752039812775912332127603031071364652586568847889581662889759682910017201038704406028421980186336968390082759610319015688975795822757987720527309149980311430563202714011662338080106327807940800793928179985337056305250255733058588776149051384522305220105990528773684103617660482487698285332785295337040809322299598900216408744964276428756295101156522746298979081189652787978874822477368769576767958846598716314511950133287503668529530298674425663904863673952196007944676772887557275493038567354432232398173389969766289160989426364011209710690708702582376866747173040043201740129109999319605448698713681256031908250954420376405177393535294070216967344326196026285668469756277580091936709104240280289588958861424061489910563913597142020858581537757581275759603830481507283981651876758366801961835935880310380668019231568473951147619683151434327436875489602161795677278103945461846754387062747494107718445340218019475978301868416703300324983985650146062328400616223265443142313559972033713643914998113961431515308695243665085038971786326110633920799330005631394071058277799194736549426212153098297595795296973025894922916801456136675204298544280167294637107340429965702997618761205455092932921186737256552977631259790105551806499405573755996033203352992791491519923326003046579122344853634720055923844793715858967300736010361156638510452951513207387737081583301902356970804722275388427839649360054441312890282193397085757671912177573644574865711083741366141162541424473826922847760305871115321828712385531561461238905561519951091519653713197055623657375359229327373937596648571869131967180362932171920385046958200887674258567585482912916442205356980505797605905939833705253465881828512776175163893895555220513265103267147402155572971531597825451873579590494570194643986388841888455430430636162696157790332524137376728081901088587112234812284812943094678297729240127488317325135839232, - -371079134190783241014361802748778281253517793158342771927981199742285965856941446175816685066092627755102744688675067818699305525784859069655561346572869508558433740554737799357732534436349659493349152479910649646904964023413629992769239771864119105370698864756102507199244789266601282763296523767890375548012219357580641073467080362671766087304830118470243035135388391792617063539498673637368997748480984771056974902081436818947019563563850709587381345128760609319923205920742395950268005228973125209259661015355410409263378841066866944534048357161908840775885645041547053178138629877258576323087047223655956042228390836884296655017451106289261194233197186304160903720358211406561689912149595987212091678262761581128683263466716494528320041467185153739118914979456606462328315351839199815640490124916358951601425798590343684551301514094874872010006524900395580858625192003986842064271185563093272462390871582885262786836634586088256679727738209853844770868582529479914708287713811742729298305487976201512178460601051983870475033068019805631948153919144762498897218120095849058052227117879535669801036545842675269056697224152946053866979183115367202091990672218570091259323170405907615803696740803381786698204467578426226763717529829699882215448264732919455146013532360761369117952885138513765136596367056411245055453586298050055290598025292906248734568247443622342150161737510425926931217030721400254025366008867298655055599970870409766820715971214555085970515640921139699958604221400171620961060482810506767738942377881212495968905141101587991012329706740738064765607236449566816117265914040110624354937646787642305448511404694868353415540312519144785296822837558025736091753061473121636685109444299101346965365629627070692417907923574734272230297272842673593842450799950097147245709167903941663935733291802229526646813225346432454653823900964275530073261166920842802327458893897101451956359554786794809850962233583593448556956587204374015671257957425376781658130899022077948524809279679007955972158573597619428544113756401814989444322853714850416071345970773485167810148793054332711253964377836194145160506273774411430702939003954235069901269745931418193087251305148964714391222817658585723360023784774205037732757665048622512366979538661575674563540539861193970078972046384606552377543026077546872443642885387002778384053414873327979059132417057679517307003999892934448050032037712959695901677060098230442215759728932718389005010211014108865930950184749803809994661867622137406288318577621992434204255363999492389858200781736888275806330795745360403336931219942558083202131569590615796377498316911518217247170749401212802124534396471380386913697722660933440408014219120540662340282492310944649055730027517580783810705339147729406658307224010126912691404593032966806478684471962249958240619114977800520255470206031339814985814169587295118265185210991461672139047327562398734543679707750622371028093819476035171615194700071387904407463678758147387447351284562495021414240356491148980873690499039092925763701542131300782262040375947053468883989036263451452616605017424944245836717628972500282368202329252880080929720485724229979876330928046515298398011067283453626676269436826701553788182168992801471097688869724411806982017304091405429816113708596248195451972060087270567303519525595459018298332812013841395885702811047470389843566709432691249487811260704535454764155061659206463925266776837428724038809419205822492399203488985204594759160686318501582484694180601455240301901713796725092731893419544041396361364836903916297602779258740614170349621375616337382095906592476847398203264152002853104262260303516246832086926058746603337154239275160920915012627557725063738685655496417726418074507747198348789965982655900282703573195377888801991092237112351160387029432744854346286547501932034641328450882975574008737587771479342509823947236165266990186481353248683895848674737988130893814061142613384150387906736752843323373747475199115315625190866088214953965540509265641031924806889858505194097401141730390359219541651680242716922472869949486325789927273688077242369296621362225101155358997478014893246283829452816661433178048582053540067943073318853313719374915306784627724119313629637402187489140746880534404781740345903044269876589767245827012564612341082931719030777682700464203205451214702708939061209693050948745042345161280931713423953054620263172579940974561007045933490768838475190610135967296839105356515193033104561044578635499791426875847053374753069990952007296576563320465572169171103059674139474895529427922698543844615915177664876540412144711495261126207731705361941100469530177808882792925782298255731550728110570200076520269096170523398745696687832949120854936751842396758233569485563283493334180409819358109531169369183505401335862649871609189723793635813848109644453230949321118175773944814769687313576917880072497420662085798725174382198830965675527374468675901824578404788315380589164913354217587425115728884587086715557134569960402990732286450655416439375002388632177828597025675757542314659401227490525652696727624329172195684922121281203245024211972178539770979049782250222343734802885234375074722536247534444876177478893734918772922974391820201922517326840419200928811383922510703426761068673290583896832343340377381361642142132811841112173398805371699826259259161757366527257069825564346463995698137763237600886362827751082456881431071926400819539516734454211591231187869658453436021911928685301972343112370905960478053693114957093529680200701274156729502816575196744853280134851691090732629131522714070081025439668964919802112512386869991031088005238997836935059232342600251232131352900459268137169670011894194618853138242230707423567839961636571922851416667047444896327949270847429980391585799633463251429819735262023448331869934199410412015489788578703157441341881319781760923357521589867606416716371006023034098186858509939301967686063994507516859187857175147279566042035685806000701395759502242113132355922441729013655280457076674806586251444720445254907138937374960471569236163213831091924108169442466507927331952678403001086590311926792296072774964541293957121519288313620309393471160992441531680136053354870870431639639510310064082658932737018023659286907933389447729101686575925915037037353878896526688369640388822891844337517458534015143501904183335627206020764467427663465415673782798999282416786428315280243191611967027421674971355870042387185178081990391662457741999592788642934116276405060450223844283328421525767090460792502024605515226028570154906321987028682116105835008649949723469320134183473573132525770108227587997409448706093889831000647351785852031382560968222696961310652418527610111965167041652754506735444716812981943675612121433429002529086888552656709219518469498424403317457776603307840793878528667200076672330719116166814451459423474065576785314781128872873976652637018076669450981139707797033566277613485021460768762651022649224245461974949170072458835993644949829638199133575755327455457172235420327837399241953470488618382513262398665683857075414844277554348136052293632, - -13050363165668659106700197739898271807894277812954370651664536213856040480880213893291929165349098361119423614178629801435041305466017419602041109091148586960488090247139239486315068124861674641879158362605801526028546735929140854698834840532908206074304829523062809235531804029155510253436886529771708434494596184802232549905378418734653976116561036168024466691774443058461636541165828598555854764701121376256262436229755141403445653468736024087979682700158078884556654897820487219243197682319421734137302577603919021948048625393014260381811605725734729709645940151034637219311897417791057582627259025735031905974924607994651571193264618831141504840818825528284079395918629105025221438339656705463323753645173551770412699187170698292428769104151554372537428092525714286807089871851628172344326571842429660001744898171649313197758244077384093058870607595410860158603236699090659945689119580342189988137186464094679794365081961951304777507849940139169632467910524321626858899457302083627100220705121269643203663307094869116335679001883790241934012872388910834193144174024102537697465545716676888371037235530131949481961962810560219468436056512914527654256385120366047318021175011305000451707912925398598013132735451409309406176642547242225160675294223352037793153329450270412221532144287050299355596453883860291690069988928622539888702690044239644808950412717555295593053553144533832270343984952014269834039296353279278587042986834764669592187475431016179465032438451411093016243032138806727358082587671884719956414354741622750600475529033641486218519621588166912327339544867435436729166309039578990734507135318179372816117983902768729070068345982303290188686516043832730569956585131556479306097054930544908612962424580497686642974690699613278744878792347210864421533868567635461118417841990711929417232942825948694239675011707469813789851067586162919664822621139927415446805926908943438849205336773479505022095493369080533411704438137101964146314686052414506553831811921593952348803219534825571771833413396937499960886214998629073245625799140226155376522006265713280768995545580570948761550564164155310394343232978798356060293545338870514149006608552054153355414415555532692611487162026667653982632458539673927601190148892593098743020195370498211061076283975940832640291480247182660331802307789062545200290388026012879650749817029139006663068331232904982558652346351067047770915973467923668852860495196520860219529276015327751491953385023471217425197704191450316489283785225380443862809749910363948095575772597501014463197119336991869175913343223707624341809788819747170719418243726541572671489998597351987508976625368893462573086200669435510744375238481368748437719667224786417474168447968198614449000086767323086957408111618995624469844986568942546991365197088108827305235023986296495619632468532692063601908885188249081883737261016197142979598787138183074978705458798928099743546095058341848030082072896759903638129980302376970829820587252194503384277692313350647305289724810391273090418128847389972545820023542183503156467442429960442143323368777686518878397792294994051973014842697883708722526682391259176105339820357099608872104947400066248897278140790118324588004958611141725193336490885005461601629347214431423726839270406148503674981316938543870192889583494761037406335239711893376281982796588257322378166012319921564825576779514901717454275325234794623025552076395776385425941588020389544450584843810624634515176448185244119662584446055951596373120132167494078641437960449004478701765983855581368719835065041571414247830478427724598431393129158121548303732115426655446511416604182744087788410248556645415790321080307896173197834964142811814843687338408807042193024453632194098894280987274971544899659600377283287663752193490285710612422275778165061196508082966306474115739898540519745698978175474833063429829099152967246052725682353502525352539550515997202741417320027803465093198776636695778441023279361666656376513882316818541584031145244998814509389310011603145258958059618260790423027679765533985915999182022938324055984169812136555902670781051344402810442001204712498887855102224509853574809887422082072554693436580049596193016098254990937269999646616220049239036453624596090946296944153743606096059436304462546317302557276752101314610097048419031781188131775128760168781399215551663317511335824321891500516498496833231880250241735386914405020889424757763198137462024710958433100317161901282028932833839264708007500319981931848997635979434075072262729829435336036612582634916614025432182643228111465455057684195772880105584548853773756400076565968067350370887640738434756032392861930321111675515493964276142175116370879724436284747649064354454162684149624829564062140255337964797139398630610015488624812008961341158988942345812462346866474809558466158889195204460573029070280704717327461759840643254487104334431572247639278365458140340689693465139067537659878451827758804142866975568169324373202400546123993311601304035540677940384814208474716260610112623578372895790627388211137921934076790824698884738911091601282918586258720492096579439845480121137991676897722553110340493947865821592696285849869770459764544243656120732325764210887988304680913650406057058472495624067225389560479318191752715559667598490845598027080285814087699132165760443438153296332384067158540359091784418368569673546223251772566638456869065552885453229507587015007805541248706703796927114886179508428944871175689254703892023416898196856025552081780444117995403904287757423901245166989242555784858519630089262109553059513119926903777765788300378879837580667966518082294479467480729009905589509299549514497348868918391230824135134858718884268261575893204124765045209361099939912631010671261771375618420429925692023976704927895465494566090014401661954689624835611880454290652245002597897838434220080441152885663264591002994268740111669054086853365636582451688689995399720519605329628090343980477260912361890747571248281129461389259819859370314984182990460608495911016313765115006762678323357949178067388836899968248705878271100756325417353565649230655357171451382391442672759189445494704257280198127374097475546048312182365322032384690938271616570942826131934952057535584390878843288447837869176510722794309187101969325136765306343536949712565601900990905812298484210274953044023278805290690423814566179676089795434316208799279383242860482407291250013342221369695311761416716302591448660845427837148441829480954428269347712142080782154038150621289671064638370532118807731350118017891300484818724423177341153978167100305338452457734310932134097727616227571742205046959590250005101340212471794932434506835036559681552697630452577497881496621563023903220153387794217466706474047163513529301439765396760367608405255443516994831043997933134436620011009596757847793345748290053475934040709130295791108262535112092209004433847744279044563262360652697863294629907442111541378686141050822807247523060066722965775282232856647752748681826404512604387593159621586600018210641222820286755687751039717963445884765187240951283712, - -208037549746089233943144571253324122160681345239402043291472551574569209204282516971641378349943546842754237262108541421649032363976075078579065742465156169459075484178614794043856482680161198831651617626291541925677557929672822167547967676141883295216438349183449802109869113365362255267108509914333016815351157667748499499146257552835731662623545726861930064105425505729554870046298278758385679216077447206087379347221214445965540032790934589605532720588897240000064629493552503183434432589296829174343200004765936490433797559038140183612986617257242725886549120938099474267163477911391265819771167912724240808133601647752308464615417609237085754122585923617375972038668729937476301342978711756706777374146932330635569440653710452517938817240110425044894089234479766152435383892747396488853731433093584553377843897879627916230230037140655057080854383879450276672882083269286185924974801584454031754292110647307661348156267349784011506306483919223704468302514386277751642967489551400725839243599739093111098716114792325962823086702024208110146413860165286758186020344096708738685243117049036490094734280579715716883872437251257208082361066703208200616118405411986580765982637900167339257330812527074828068922343783484002853300134895181998472678638180663446872044562820894344494410707237800207521018519226766324356100452863478211517998463424713594174975150499759616579629794845869196473375127052188251861815756764017357857432384482027962779215771433292836158895076997211928720091014196566616000050284161010643858848927080287052371002898596725600514441251586745137428358733023505952589006591492443445215097810719348903725779721753242228340151379913303866830113032511533502684517619743502866533387989036799048171489916169096271214777929407737893265141907131691940218983946594342892946113465078652359204946651851145341236850617429303682524011168550541304591828325166772078049585854249773432454537679654693404137688893389075568542383508056338483034358069236858309786236896067569193618149607708963233092828307849653434935276835627189737167417521002135135355067488442378224574202178696211381001382544346551837912852487906236225975661296557230229432208725594055352602741089756740406976048940068793294304533853780343681589538816018021324662484930956051210602270380677486300630229318166899348453343620134897379112227603447160929682502104375891067589887291081035181431699449822159848861726633393676445359053230936022827500936317752836844828069756201231261244900901764877087576116369235544807161738556766722966212163106233146189042656908784073160749953406757514593359681534833139798788753882412451877419409908875168332093825861673616565802317388147855250775300219250394464344030779810149592385771409662179408178471299937625492772542466186149906199594424905380705147555035526571479981555772244680323794550350083256228845471635865371431653711502228656348632263460599938473391014741939159226075883305540728056709850189161360054440590228487163279695349650452110220785392978713685868644460367531815442547699280938242895553706863206582632383626620501608228611662929575075735007765905815905889721542888925307234927602654842718371127802688059976774527159901137445430359161752651373505322717410725937386066769821282126370762221957064567545006834107210565217905080512915962746433900977292544793913021722350852636947042857995543266437524877840503559303256799071907669347727656202487746585755640088467619381249069859086285225607816475740186552389954118615834277470613307912318925049414963284330785829120435977571717088667066067471630068494301753440237543696077502286453024962935128436664165842751186581914178268734117160812404448890348797162575653149159214021411815489284604753778606929803462202395379036012308278776213995143793005167170647611739746639309035475365179439602916391637836957575482392589502624440931878716253751599198161383978167907282987928378130902091238176274610455109804605051358401399761740277521388768921867690055265691833096859430569265279796146256982198671585644773978175103409817670513550652102889737787506232771321258510174067805525986864209995255450515084756605272023613621487668934044959711527817293281771010515949571605977613690656038041990565745061037781490225951880379516863283284088394602825523059770653585793933879454028898845521593085681229432098520955104492777359230025673362523521386531422478296874091157477596264754574373791612193376473101651651774034745261806572495411398607027794557354426261743529163441909069495066709360062489324089383612518551057780584517069102797881182464805492263480010723482658513760730623071475829507170615302575507873881805776286580428062814603221008589807506113603085043182826837932447295598191981564650318164024884734182652350540026429010052695016732412181234934254356459557691610466373691048253051489020441436238749727548849920098157289598030805321783455573865524167563263012050420764680943243815464615636934180104214825567063325460723787053783436292011372345275182564950159545963496419114895152882590624481954942931015250314673320582592540057172989729971960103757199107622568034586026398451672811502967588027055987546503740201952755737065577108785106571343969684056847141033258440461750750112481273902721727491192401012069979468180135772023962832659681732324147400165411555102363563225334357011969070107718521525197321813475192044350741266448415710738733119560788500100252161525865474624974654898164527564981035403685556374927006266001583677453143567990763822714713651940547477443517808281002375752092249521984312691548615780100674539812723858524647831232767632481842365143556619608207795724462367305103440401491161246894646186808306483221937981699643684782160268396020701576223235199881157706301846189706414175069708703608682355199277816770007163660703079754274182897024476408816271704899824550235775349629281173729272413304301613386744535983263601121548233131780863866442395194093132241078671037891822974590461525909161415188809601691277014095739529669738593425043391986108627845306539206170135710811706833744165028575071685778219808719866497158898651785074003466000080376639708510486470360951510874716632994119857521279764389880360323638606095310480764885601047840559305007528957965336666212269459696574549517458108153534891884547873479900109701383883488536424702961050247377460813107073476355545371632772499996486343753051124433170827819096893295497091288810059012915493499442238305969662670182342781289626959183941664194899782542037184815209483357050653910979885276857958884705252889294029069214586136441390417807506825955835813410922403256466960636610297925660566538191123116577542082848046879445045795985980874048755464316598927606374557710142878723091459132750320342008099782770407617085791925514325071259666049589663110794488441211391612746643264903378701772986638930121491489883475543950542555480093506789076864359505276091828596283482891160928923232553304965741630065051354657289881459701976397269650807666828335411488341918370914240418951954488471461383555603706224594795538411860366653492614649925150434655294195761152, - -569214683806857364130469168859174130144621793808039894935636676300254819837787349707894971455523888278229131682174345495693539506650319824316407898911954995037918680819096058450884933152874242595837255337538857257228010517150244207304312524973747119227868655786327475092628243877959614910036139380160279061062695922046494479293121919815287320373468558630224557227081726755068986125752070377893424346641030876059275431815287099682751901470504008339123555750494709731247548555241681420310639926057426694380736212812136673465918383714444112051554388366830155679112168117627082403641075548495521304991097999787278294493368358280087381794795825866876134690140635959609295451289362674343638121231504689658519561419934478392809715661906409199838176487138245156222476549428329857653865661670608959573463485929143994267949423370342278991106529630200086444454518255300374470072635452153662504893481184029561828943156260805477758893936614171039172337527484722444652562292560303196001415072096638091644861915027685967581412185353197861114703604744913415388055175717633632689868793451503327856219564333649870672995677873750375719736003391980365979004005570901116309995749112557176864938812465268058905593380307567694771384913628138034973561562646684562553757707450747204418010823217943777137892522005266209821196319582909458216691752758582609956179974226652312808463008822258511013986790514827262125822424699957824402251539890505783242448191814618197906032473690844028320390731949456644159380346949031565962263886589098501322982353450119383519297559602016503979157355368232496738383260674028472672869793810083361820899752672173919402561930273871067849015970675967687655592214528117648431680245016612956343911399214288373451629060899514627757952014219850480232295816233258634928061152028313196136526275731495109192900169113906019692459144939723370657473697493474387257817624268254382135318051779636897448362034116753174785616741746939443516282210308894382960460504145549147529380438071300947491407389621981013080862699814542259119854371029363608055476727751555825920995101151284628652679270809631669524469244550788752460988633684988489452376647763324779560911885373523194572047698211813366174250760194098173568989358954053330753247720792863721880314339154981580407591898657814804284463098455223762125680487425174508813057943610293142494058837140243469117200921940301610732698496452863035338939952415539438417090755459462549241734842728312435772139660336127992872263720139326740067614049665296922770792754748765020890983236688213781934645710414827289185540741383096810403666895555403790308208152101603048554497890424222816565554054750537680877153261990306632803943166197413521597869959836923236469065524400975544037556565365952579943641825121902266266223780581348544508147134646759586534683900310388344148792754609658257776601063116637986517204253731477979063608322784416204997743494287808842284420731586509777995037253116836013720798163293762523750821693788154777312641227430015744538944749677415543106548662480050686273125864322740749835040983241191826585754865376972172879009270466740934990982948398159429187048725472930278784998368071653537562303904761092575179148455272596290125457417333274758989035624896367780103961063166228606802718479847170843158776150939897447298107170544579016395134838243436432472349897102526044812847892072090283073441055366251489655032339904895272768280317373447669201019753026315525647023024208642431648986104152976592324092443900560021283687874570311472167819996222108130888904889158654885825557283023348415996830285110941213365475675417933277347782136656797328113247016475457512921567540998002100558128470842298151417780868150247821362788802993132941063286601772547374420295145938965293185588245310042755760415847492383203412640845270977097839992665537939251404494724897510301217168466367882726521308129557029588123276130332510010183251208665491960958705788994393045463589169716932532064436590550697304587961550880205103598144074358576814469167888520436308293272227755529844626341129879683542153800770678454755257262767345979796381864234238322212680928359959942314070718270050238690634368093939423569065186028172774981930790779174335949149351172694300024485765830269452309800611149784837490608216467105511025746679449990829128619044435836167004648914174390508136303898692630153885918054195190090244585193030430985299342571570906630161775395529564930317672097939456259857698358408400532592424120518203870022864024230878923372338840768529830168611173833109533665060489050607395555689572107751058362601597039189960089314587097936987243049537756760509363555104398063040456099473730786276788988104879624038163409047501320826711262786199926285124469071810549840052125291910494361956549163447167283065588605545840664988191632671828407983628830295895905143102071546622541724446657971457019135017754538800815911685496976292689447679281396218114860398855931396947430663274313752395649800496556118207669013016166211148648393589816689556568365816497119349240858040921066505205322434815316036005201926036323654105975552878790809202685401837408053194566305923738179747310940786996798771444687120268517333661819872179262476316026992221732819728083094709136464409220942504426038546387297621977320338252204259570653494243706297843836340295304741110223613536293760983964518956248269489424993168965925508868062099066981891678297209568155057841698441108032025526934399255213104187550295014900326678541925917144144816875458776766762704532691774210001609159036004534693919665255238011255136581792004165519373389408809546637857119999497012849826441815622746473380206185965858365184436326950620849501289103152792793985975068034757861947263125347715150775217205663222844831582546465861814003071921593279843320220774937912312670120175012807178202889961076634662963808293472605588932297647815323411559015468968137491268201755040783780342335934146524693239117125079352290498775915960238349544491587271426277691980364534035284279158203879922850239635493209442786101585439530776182475718311344551082055501035620746079130117676093081530133046069806435485894224365672158492793028759739932307448612885700822836178378312775794845817479711933777018914210197312995965882375552118113123328282188568893517519385946936586341746052462423955046671036262365455634109297288501645929154047269054232622153532839364838236954518071499463252028478076645698714327676752783566272940804459228089269318737580410598868257648168327005418406810027420144859933688600789374157803146219414413222360911558173679601707516974596986664306989034908852753464654561480867898838104920683537117485436682079441036465552310580258037221124275777084387871306599984724502554212988656361890382622787077231432414125467250087934859028077707409521760932800089606011322510417823374029685147044380688454020403493714207202436420319910230329372115516496674747153338143923079726827818886159250411102358845472239758750091748088666867158773940797700461718115465712498138611641005204298478546344730343505920, - 61643596619448932901596771864356652485315657844242358148298671257027600010145808107887530547969126667851258807392872638104117748717056422522106060726854459221853009853043253686961777580901493958811204253312323323248185508195108834587728992738087223895046627416617639738725995797631368371953804581143769354125946508538075739653847238576546946183631770817248264587933911131623549666816007473055806933152099580711926187258905944303822318232328188864525261292182802333113182282162473340278020744958870816027061320294891926197770418773005440378331908662648683803764576436780883253249999987512677557821603439900445323618406805193392736677688187553531316244610932978111745121495556404986281378765309351891512198756316933076346894032084768809170811654905421671050168177696592421181160910495039044165118205364274595325696127475399467002098702016701836835280697247952318686954016411888219639923036731415842332761658648791286185359791391310103412238496372025135811386918806621008513390697720518487328398332313292767280018536809268853441215732616285542515367989683040073143326486267323668512316446988609599697620041494711000435676372793723581283417280162009825014742721328745329629046957727178575910769187928339253760561224822502985082875884441794382782998525019004550088506070652580407102498076840710877636156110826598286344611429202908877793771688962230914916371827320238423752267775329498185315412850886094977682605501056064903893110216248537512024399040496028421110664451727917064810342408325596131009277563825071800429689387553823042780574650206267248350417915522495883144708408538709754995671323815670532118619197400750049332673347864432115393610416569344888765718466011876063241322672256470806951527637953037927626078052509178759825971230281669288246137005780599496858127254103377300511385016058708603071801310059615002113654644491332478207905898426619356680294097759560150276476860396772523676449923532704768005911819593030116814949067589566276395290728427509149313761592027594015712764744185190707203117755418063379797772931153679368923381857493166990645204858864833325489994094648271812804635328498443199860247523814713493282472359777437724363731971489312377175286773563932762141505095852982536403380125818077126034461059808881436482395802563059012420304242397998855524236177734503789661192249689016942620027559049802320373157552059069569571336444629465301231118671085205110630664934456890255393152389621649419636458887221222349605256323068388288478072014135649544907921501134849769569229570394454379900275870571103806542374828117819408412758642313588158051111338563772134688673130581216360988990200687524280835744455991568000140458811848503478447144498661457375939947039796984876835428270358925439749999544049273441539722367352968887241412360783301427827467042828924681535863849767161432559600615692778276406079873204911119966829273605956791577436912601838754029167112331374737976191244109512323924734840657141247423871444881729764052480983022725422306368740889453627138156226125228315867627319902473735791697928179410462310687972261674028502339968167896793769546139029599021517382299012144194920286870277638510521951473614071460872001472407724976596701837906582928227048857300832319457976196274554325551545784865253894769294505351897610457747478038557918029596269215036790591622824763653285192401659521515246858527820604122570416061306689570542993809016831442645402425844716394186877275376822327608041499129267119867855750846616936237398646690754251471639225756035431839968346708353713098218446002537096578847358762737039670493755502216351244782012592816145662275564553227958044876364543970448870700049759164921157870152218999576882636422242782524659233577417170474705613131603109024761621868756517566460725988328858395777127859793625447195297486668283386783595896161684766035369286142455439565150761026273266138114564164350520531775847431046540378877055666292759204605365117729719293310385507428920698069710631315338481756123586646664653931931509490617766032900108126702226508546546817842034552023535342458402569142960331907583253940861679304796055410088269407962161141826954928066315552320320018972578323008128262713011531782648417701018293357849121099807819009479318570438918886216187130540547269387695105127572002559712165160977096903788181244031663535643533729451303146943455381252443131969420628418553894363385737296582167415125567778208721338092224667989125046129503722464218734633535926380103751055960459892425500167805515032171432761114414304540807828575490499898992978847950988500576802435191133832380697604607478242076108889098092435356345346031247291500522847037327714024271039419291388443150997664826035707326205432525458974744206614911918685157107964290749593288625674725734883914124583876467377709728608033822009052960229114279776085538821938758155101171215978449437256925899713407272543919949182860387988910078678583397580180883651318451069754949010286322070130328308468133255721669041944754047249233638397469986114373277307064368521199187282512747733338188532265529601922953848333033349718524139072930302195023832556390078884642964623138207280735535063960651883375795523756397138185658497880914044662879949928939970008724592071726889053075922741815005677502816509930446706261835541492780233628818968935131892082291225957542553457009362004391053637582256300965028379698362173974984071204948324061678428614960805283264857797382909464330565444305368350711802707060364520178571393258809343559570630327386572854354488124798699064686463124659232090299851344862872327264416124664407072676003583551026376131595374367950032298525263548928844477222144761095397433295129218217594665467761303481582915355463929688151059439389976762066288158925662642806870966574802678262969745088300009127463433574542978019496439977539066284879054133344395095026856439537183605204122866224561074605706471249502565465422104802203840586668167812082571367306769421823117155384660744478164519258578320479298170947868605421319275523818157082748352805041299208611609352266448286593009372364044563151088702461974878542659123827591086825465604355916558780110074382351160209240473576421063621545833794520251056941613898163467866132875255435554244143954403704023963883599248588319708228727866833288232534280617139415289724252483389278125793365298188202129574495930216871872388872128202419490361923341899129609416511470859174870354591929295864602256109220900874413943701843914427003734859880860741825407041376500911092696358088518423291214832342812740384286763160321652502348742338074311155059126702692912120884421127842067614014692612041232458120009886345117525238287922317711216614893177577027338940053701951314118499291524076035277415473629517810127561932819640753339091351584917692264195029959180178329340004328109497024368887565494694201686659970392479394945979758437800784940866612377648492792280918425580842423262239170541876847319284825373985668487012274754604714731847643567878847654831751053818867392786297532202089286027182080, - 1783806041061590200806454610520100824098601973804719435680639380036914778234916101931237594008892043994640052737896697856704856177252381125522249123604257016313812888299607796105273998076237763154192006935616208846394267509716300802258632420893552172090906675088882070583390595156022204009310929401373676501077987861844669467256296027282837669357294733516116154185790691423962082916521049081164666991697646952818962771109296653590744609459070806459241452674086721610449220129506519981903910254099445675447361752708493381175502279377452089930497637738308668924000079728381046730608845597487379935102699218547695330171319325655877969220319069259136158559462076615889288594447440945994630663727131452988994134917278375816365117995416229347454777506121276971419852495491188484062156170826544609616183236627757067301354009552367949009332873970864827206824044982512236661007644284337202023957691932932320228772807483121705125906531338985427632999525739570698159734011343974985735930357275239125919097658642217448424844173120086002637065484487640360898983411730784895078713652103155600170658529813760851391920886511054826746819241206223256366456705536578240742862030021002350606456142662168045087257888748704939944548804931614915664118540243865173327001186605874394057261681853255685593130525527702023095527039580065147398820151711588181374934576604338850925573437150703075078936320075865500854117088666369842907381783828394099355518411478612472308109294701967897000427863057964448345027766448810719326005721492659665280235446922013699981847772275236768328994195484997990895403786393488107394852335009344644352220332782301843109451445342329442005215352539408353342923409959202189035755446084957448399568512564684603356889500944221871228352516734923551311708950922761132342080186420094793077722631816445818815350466034289377772839805759365060425092980030802056678539224251398547510270662519498676973073133518453544094273279079969875219387454700025913912809789743530464887168987612053203028981462475234056608850618368517361409405232854872768092957384465638042776055533982826130087872481625054883303143944619467451826800994267419702533643401374497999833036950420317773034123118221138477789501252861209353781555169096182523760004520845608065189242136147658245941440915277963137181387992209267359746724711847275516352821124047140548633499890280243729585589568597353058055103428881880548716403726501289117587333065846211715650643595120711286761385226480479489312074305923050568990515370842422729019289522458554852345487266891396680505490282066301142638516035762363118798296286830752469263232915887924744588123565489501378739960280490328033059631660538045279440612737986832690664397673218568663639969098044677776303505903742270842818401018868036458487630529764796451911390841932379973917755158096462605803455611526197714845413248501845211336336692385572669061200689284202903685097293111163000329304384091651121840529092473253505024085613710661896078238665295240955682398072393724125287128052082319631649230573379937399410634623612306891940919098264933046487837317810235834615597481192446530211356499411756820384988682637807137724021631625169729377499115612328358189997740651701560822625067606055856492689964506371457301616174556956772844671068117659485909979542625125129603854526055562485666856786849147508686951355942513374445256671257540498968285595040666938298849087138976002009103833939864697792930778119566158678459502494206805116966255050045393374865051026082533781043377188567404043524795634751090788419453138915609169660193791189959157658887621924443833233902140108281494872820587076444573505858393189492456195795401596331504908092117808439329636443326283959119395944410187992565931745401678886945069497617221043637858067125758438176288151921561061050167753002812793095042426539705192575675042089940283734621104082706960074944244903369153318263359263101734143442248823771377861700378198312743095199234303783052724873121045558116109815425723452887407250461375053208864181670986478742065666671449823729363760412970380574759733328511361268525793594984180850858476718470756568244840934637853039853692878636232138655601888070015280736053667177958630027293542141241989812849323234122750869606784806316421466388064092694269877466490903095216393473507940026624049156030460777390064573188930379188436501406055627746050502398143927744887586438018721621952055274456404207697384146835851634760472418020298960100571753199576315807304182569502396413862270881326314450311143127944901492998379295238357932058750005468160008327317741089064610277604614561580835757769754095936110794881634165753962791554535678623761166972940695509300135740226914871746003992965991480316344006643341858728676784698864710698737728337333700736546293775818130543046581778734018012439519946926683891756309924811196287906901596194833336111636431397528765694737785505357605059311357037300542489344862450906989021647952644339125381397358652352678653363453673841763021134400733300714268271136385035856724666850102265356469797672204431580167029907721508159573518182031591025255036169283036495208051724152405338465424882046754407499289872943060091519492513365823161602969027265062441825480557864954481909770579685522199409308747198426626832967861051515246269372511783517697013282485202164413286613455191178054605536137116109357511340518947565428731794683403893047554314118157697473058876890733837591307651954676621584163971703950244479130448397518071457564051333830972378529422642191720400133168184788601444670755454308863014766790391184912356776559054052013489784961862173961180758874919788348854084627980512582010903827352656773552477940341004225645750358355726613720081014361196179624155853492407179695092589993186603197066709582550799224949364398338502968441716358812883517701856062173567093197698632478448129678249725438673580828893442623740143194692222714912567648834809079773033177886060937773253290212071068837797732710066413553779281288226004872718237633326030392297521183034884981080627836569371391272761552508654415317641811628754647215559676082269074942978368331859566518704916723692481479022063374077038746091677607107254428510936198801198541130409757363897850847464592958990949957843473632924753555121240631966486029868098457547154745793011180717570762573989160873256534276428748350922838435969344172073620193422527129392244373033634467719766549659872784503678408964533181834338092267228191502210816416533687521496440559109143214728494447951693936770125149307593330207575831359356530688481944832247488607183084812274188730475498040317014892815990518742579258553543392686195830315969205128904877576285802178037998315564220669219657566080561133326815655068895766184501842513920177799273615559161609451769415333906584038605963176062050762464244098134056824375633762120000270864320296106277205945422857319357713116764054053101335772188269713495487166328748248105474123246504456803753392311546848433064394405426670625231122464768, - 23824439206541259929452436227812800176242259503908920110531133495444160293131664607359627016526531948605114938292439014808850473066966472349443940850748852334245930749947535647852303420274917416228771111285602300283715382118311809928162711883771969091832606872460318217941265936252224730805361945887868623079184693011537697061432576065620545989829832743940876702996238790533074721855882542332862672857421251778735478866689166163242603137620043560813272896262139075374406450618636987412527607810911915631065353028553965858218299463213569599045592881629433728069048343355855644129426926897234358928615510915394177251268310732224312745642002334023136958860988566922237134980483625277223773523556351174630632070769805589528194292327739200672554007580103049035780959602160658942230893603534021459599182767737866811747036151854393567954328945329285939971475963273614906412793639669784946581103865969411520676825224012432936471565232930946696382278092136467429304417050354396795355670769650388734398444036117682336226038694274819487629920992712984658841504389981769947378322876832469512809322955833179230874598996876111519040542729469958956061264227455236090740819217248779537014318751106688822659974493602742976090508176396548662724111386125692564813689291367965624943166107022463545827461987874141703584037275584927845029277462282069342316274544827607359561747211864601159950137247503370656407669312819927274989996189502949966450872410309288975973573067244701010589510716337716261296130424512896927125192684934304920378369664770171947719705814762247918509312347308120010148652516098230540084579232263897782702696935949956601003991144847958854628201449861049759434369506189368001178467900974908029440195395552082672103408462129732472160613228480899927069271809579439328533546167029056083212019186716371823544415676068949546022916063380948477251567122254273127977584681278106064656604971326355502767245192437750716780916211404113463266011927798020595013973878939049274174790299124667706157263045711345522232920531437185903195011537254109127267298427582946521058204913853917274005915542535451549883937839587967045425329162609210312825735225735912860328925602160396066085158862082140179849065020817727571163520885691526017099142638450460483326258384760388354768434064396066207497334006033689351814865146605512676023210251624260368468377481760165295816299911143747945076109091779443903538327618789840523220768548284508309203160170376561351547838769760667118221311706550963647405967580655720763773964558807258682015601194461062708484208510014797472125876195826867431762648860211145873909104386086436344715804162707179565052844920970190522908800151120591947966709395021941346055520769016794204106662536844780160384823164298942444201468641247421254094125513887897271988515667476962769512850841474678182911831367177165644153506451105807796158319085876836073284285864803507009563383393884566140418782690942342591026316553569885542085520954347906346459992696161246444407999043803848239895042728306659090621453369419924450092988299688241742805421256159886232898744080949506884312808819152958375120082803352164756120922301100741660818275254477546818751883234964919098478394225111474744619816760016699132210876906325583204641475339198871813838339866599140660898020568647148251882771633260035519654235286013933629993520038995186421696637971246821987594398489619170531951117485733938693308476339061697686147077676078399297904819633045012843783481876576283421690418361428914916043700685957775061533632930359097559808084099328666608636723352150519307186139067478112145150697524177942477780057722445387834898318291237589740667565980578467990407426152010057697764129567337861845357046204369199528339154915696086351592887520299033997926245499038390311768811399509002376593355895561016879746090709496395386188651128102482037448109036298478179228831329900634223236719466654418847924425158696711093200524928008079958216687104497619722727212945149975858629406579183049541274152473707915248601574130707507765495517178809029547990179275040833015774049823634624485821512797890085724962110855189935953582356622614743201529926187078799229333993581611117455193709977462000704974613104890547061909197278731547748266747840536524265362879286894877695704065911939894906571887734743959815509493683873949891719096403859192324037565213316975010379947838122209616920403827880394842777562037486812443086828789226523699742708227630894121413473483132731276405959084443940371918903349690562220426797131994444229321538111794901574335085201589906243496429704021547506431328553094796603385595256586278322341822193210416857595331787758126359595393982105173062776000164478227949892974573090310759263348896925621843028852831710324676038358758299031556499047599168840010011822131676061833599190485131781405037677473867535883072503151314314225139154164251020668182248670688074207620282285093932621696944097133787280626337335772044877631645623752447280543631785021395070038327149031295971034948602238244359422094722780531729104039555812483252943741668235997647135756473093165573211199879814315416881463533401794498506052145269398362229893065816036583095059402857385770562634483944953540522958411632589884400662211017621145330619651528625391381564314375463304192108743256201025881526215536290011511677846320327916976036513608272867339879346186049586930444682980060104420402433430165075402315458561730346230781839127548252138763795655779609932448367333485338683311574564814061791886782673215095153250278808367737106028155696938644183770858787129267346255392395455047928079572157048318534688675859737075492153597417751660798312221862671924275650512006074821350029779435510251652595638084624189760957561532729808170226398828929066823707807333913855836698550402126505119673977111917880453461161832741389836403815962897219151177305893887526991731643282852849510482322595761003889827751373928398515690586012760374664014938696931852673906284772678591539537986950137271294729121290714031703664216434395450415961891914009235167551305115012325365249008535268738850659382810691247255503411530030646676405577196169835461815048559004611154433803874429568179222806467704405890620608640689633044727139038900184964949842692260255012321467526651771838980728215663522673619299305504237391420383159190630733507517493905565827781067559398324126490894543858926977522717502745126282704817269964835232225600122232296186120585448896215782872697830621613968636510549389158234457205233302124246579278262991443904448151866186990468488109161300417832773669796577037157010416224761669976733463195738607712587726985889392428602310606951069873424587606023783812050750566788083865333241664294715177044242511054800572293537315717040105566794139697732543318012046303576924113798107236185359589559543195177019548115967560939645657581276161337796566196739544946667683605138673081378941653624777265621671623004768894490204504636883918998706559763087360, - 55559804981872303999908333502266242190656903608048125995064894615382800868914766784638191843011006504303583983136484219357946438152056659266923708589769985501784485624080450307837683359476850134441734755544915764005868498808799338823781821378688415376605907835294821508117060406518090754143589512395534354537507294645972995008852602849049301678402920424209952533753568207264252613542197802702695189681262075821719400582216367716673746111243449487989388563404054491077444488928408309491022297876723939155058020234968226282935065787947944481552098446771967248832377766574130179771296769883129236004843360689428118147519514036117503723971455335209678773302929984970997559301263892292490892308368664932331757186296313840592537809876492506629318799216388643560013228713496929844702174508767079040517098019009031178037777209855252060668916617167405136347395350648413335959075034455825051235816387954434689671228877060182996305227378393348218213117604745939929981188756736011704144228007399968389422118868616227397653449816062186018280827561498016726554489535818907293869406819822806390778125744806839284751588124258517475950395897895129637478231719937739323867595392582452643917034209796050540339148581653805313516103189628044055977870375003319938210253373280012362457626927716637442782026512968160992711823917797328620288770334339693749314569555399981298562591182747953676357823340413316719792010234636319036257300672462047471530976531512149427472170524534466097888713918873405329183206208555117485659738879961389958778899805704848626514829722633533014293440563820245534941336034221376180900968104709221996753243994002394372082708803646720098502419444241835764412715127694250097761504681623260328114961439373939244717017061518186450613833552386224978436977463562867224099073250755587169778412235918330532117495871660255190655458522462673437122623382985625542305552196886503369874434451195683172780054703550085370129167397095539474834018366159971202639699891583581948593191272267147535278309784990111346657604771670411999636987094813351338997470628960768540270483695140299517029971247217786692466151282671387670391455296503751944984988628578396165441808997881487756885251387468193006207567549940276310301858556659105594741511409004684981116173845182136849177525078465617595689117598202845944912650256401270210527918145579229280036595016918018057958375260685130285435902080431838193093485003564528866926234528537461061335268635919001073840905003429364670955608876532810135965311418891432960640334502885575311962537842163843925108952853324321239362130256162888082498778610543857276280336238107706930950749112965484978183714315463817423083333263935844814248735819462490971912805377881515103155658275353353493059407792052231467768391314140902123772992599255074570946159409669830519914870766017855550209885852534086491214008250778130853532919723262570893041329719904651615374420286521936115564505487295621291092922821513803846271673118550545364875929133792733933415677025480768635496364058991829207659858163837793083555049602754517453554825229775654143464333520882579455781721583361994972201064349667652164455211535171900896152667204377303227719957596474866095792956054559344349489138360278413265895940797632540432879131904501536155035600328654222397486370338140730591886961658373086551397390512895172318353233808626436190100247287681645230099522858914242471036042636786806857883464231953899496238199636865693797880178858567723027501436536996219430305706850038357299051147138753254432933397821678232150230366774846795491076112793830662795608347916160887930757978659942179411990189002752466976068298334725909802386415954188666551740895490216025839264214195860542800264449645437698726254810497231199023423809511736676646636550198361885901687336180829041834365103912305103598437611467023170676192611465117155728292745088864889075604783060933796230632084282637569441900790071179708580656542378535566567598318527499558721445574681244794431143627193904729214292596761137596247217636745746319192666458998992283187233043546557037791887369001267239208651714474912751556151914556462846258890309098399900278077088385013448191852355010189814059266424900227784364161321764795698247101526670233805292188088091561990051401122266444424873770870067219860239555054143737924104743505491484851374790241901434727481010739395495045174012804849405612059726530791097954424585895886223317274009852924135830624053895174317225370045729229028067662613247295075111431027309380217813526267310855556000276813033661105566963189732013806204499674831468915003958036912628745875522866086100937138564163621662359674726987293627868775975582995575118999302045008135043655012471162475335542485520122260486511353555906688608484281827687263583480000194504494487129173485595620643825264130224585773002785405080098076263040754508025389787299627608636711289279865458537551355162126425449283003363181533878508177498848659856058998247453793618311074991982226882371253932282784904310173895842582963552092735220266161547089000376735403591665364435435739568378594054478034507696662667070889890631277352534050954820846891682502012650217793504480677763403670518439138299162835568618501336268343866327859357830068379884851541968385362140311982509715224125903186890401650803991374946052695404323627671841004952465828928296416648934003810895744631238890743098003438281239888574356261360065837306647947062972003890031412891615322086133644864797358573738961733758333658304055791120314627682839874897231437553739816006306880475041501796513241798633562123999649965301350718600024679203832578000796381244575890076248369187139927690773413147542284828323931168808825106422244158482496373949962904816764646925281078378431631625709340145720267053295927454537193044059956516352816010330323595710397597072634839648890796844206661976682702983958513918443470150924115343215295840111399562115013504512984811512770848645601348180597759372534674094075834118297191119914102704145560579279518400279113633804807170453625216439604085796763595063254961411825471285975636813948058257505154443783704821954237290328431249691476492466204304367004047007131163383204926033896336793654996452491091801413783329430178912571875119119810261753077361265588146575736032247923438805738877838967666228018850795057582317885117854039431159625524967262757459065730332102273692582581610382348282101262271963397070605127316035298304799444480373354520346878275364254662795537244494577494199014490272574258109308759449623656954904990282003328856929447856537421384903031142426741250477684736893132114680164842317525767681286571945658303248322536672114069382365115656471712403482837162869841253181358733177375948364195174339924775392575279000961197210508351470781872009736915435205539066125929579423755487978509973953900330796350239533280489951015485555349710396110332430345240720835415522385348319126024874525214601823228264448, - -7590904275548732203317794559477127807804324143242093016290260637604151656918400182457213550904695583805604043460018098635416032295423956898181479063909651662187880764409653572520970333808788481508435938654471384154228038218905107796363010357119603818760757042492778253700615427336997062636213193493170786529816019564667062964851468739689799754638297742031013136432856811352408358019538983108622844505243999792617836299438911227176050953804716364125006352914675815960892300313090331598968236043517519573613111175412939773911856236565259359891784583991357637507192563299400523427273577026270792292940917660577523732981846487388296225706751096971147849776153145493129123378311632186194825509742957470050322877790461266663486199319697903500190040630740075306690770512872767762435950427442858546532813282281505649756447750001159726305222775483022497026623812022194680629492205747483525829619251469021152302147100462437753335388025425982683132948000258408285519413378433414253374642215101707055998018516994449297127464344906076095512317588166484645110552341444276018345087800919841107371906099621264106295538366973061672113446829406981803195026997183910070861302684790121673916038614412850521046720991330480497449713247579784571080386639299145778016268914088023254400125288786284023474644508408938613584654821589660391915655727494218383691249492942798641735817648640033870995361500393092157181455759939156770643281949810707236084217945819944221142823750669983882711722330918403454461404597797336189275825146248505273761408378840914563250119297703013093742375782884492187948058488294549222192664148632464815643713951305465721401283035983108435467813243959498123191884514183235951258557291847748856948569571071350138675125057776450079048527820749052831996742238044432585083888790719994852453151459760033846047836024648832028784608394572892537141189028092235410798020226346645377444758926470952649709157783759067337807226622514407866338074141005438799796128874250558241518745042431551638340469479447866934310532117602197628807792711341680567517374170955648701756843606853047990027015623518490191542786687745519565340627820069762501722036648111424514049137290756945372078758029254975625170982510928513925867945011073557425795798480151546150910295542790119306844808925810854104985266249976793795892387783678984218153322555250011714969598232377580762352015466014179255436970673910607941031056043119945793354535251732835983472037683609254444507173721667552130333367369715584644581952122553317722145085020583884988404321655259298204435666460493745709613760307154886946505499206670063273099130510013409076762776984276666384616245600352173552400616155978669447229542175802177350440642431376425324028963776604867262691627204879079595391700808969258379893480606311147926030325758490635085018040249875238775118676083970225797298369024748464152915260307304816270018757110404837694191962253809551459743592394278592678324774407031729845059876691478760519679307392821150555670722342276512738254035408794264846046624218080630557479553545042012243633154632877979623071297512158775170662091890979571473704946516996802497385556639580857644990576431880405568440655592123565502388726322614084571803977512480083003644489392003765563836775113940493491268730721476788705922102831506638494443845847970035692582982906809089641907605997316845648821649593056619337928809055153755437594462418868353436656778710408768866655935639303226323431155023858417513332147079913671027789943008478820682823260009837049990329517241768264983515075372699607296340251891488917436346807778688782817611540485689034481515750694872131903019095219527391694632435934542402859215500768321598243440215748402740230441894417480294865813632262753769042286553952543487132066405453274281750505971012929602034727567913722333962256903489371897227868747478160897950160549467626276596353346749274904640156829429687008921797083799406817197545604116482106204511970978986416713294333357542150816196273292109255199541245819156386086250684819679093189081217612256418277176360972658480148958697987187156953266158700624528566453833904039175145744670685770668779670070099532949817573405278245272782746886259684254394643695464903892979405383842269685155648901262297638077816837224700062419238547744240154103562889872408838737661535593813280340224841109828053471646905378344660992239114985512835575760788970306377991780050899676400201309823302969171506129488064616932879740458859437880255630454520272405978713332154899549739968513935345677938888787187033854664575719079896901667072944806113768321008136736493934262386279634416967561895820624642967664241166031450041598696727773192261050337798968787304475350615458317882121687053796883440585677737300552504996530228403658648727343010661238093264223119778378517681307327755735705165026342662247946491172436233241475822481462737293481432357767884276759689239548355897474562598951938130700205352069045562575557028306760834622671231066799624742556402649959205038020674154565121864515866814258276797230168313558939974383259498692839169778674809295588847085057570945605780243172570167088190458633658528499614563022844581435168593382522487795501687290466761623701382106447255864918306367205930497454060695438954184728876282339112045694185034114197555780560663174506461617709600950473880277183902516793061360927589027806555286439518928745306880024822040827775087787299305209650533937690169893224931341769045022171942539563640963184589801752622411502404798389587827597931554368460807887997233260140653727338578910337659488507322887813511977363718804902763366789956394382828084708701184904343754577945162995227145212217144478447340811927764532429307728264277480195966678621119603164044547807677414482613825766955441869625384768658956576779139055937367817649116583218713694010444694020754968543283183803998519627805685053394190713855860821108953318425901484437508079057717409290285595361496980114554860400133894627718895941831518502671138509566869320265147245563747693295558654027956867195280989865204732918041670335589482780330432976055030187407397187693426447532123359069782152314414945603007341871719374897689409781923616083910588878074062380211525366939193637754322891163085329906309731412977266418724487905035046049376065134750726602199692747655716376370025697411341417742110015036903173525739700939825107393521465660821686346422067699482156048471033066417318388966108591090323712972285368008170938705793827044653554092821568233719641923110679019743134511192105035715985572703160205529524557708482981851340266538873125132336301095609739067653055676577127861131011873231625538268680803619945740533614729154999061155668726173312730486937397811347985288212178763312796869560816113901537719910043618725424488844281261162722114800217725454708957355036814102651522155569149362763016620670068821466939556495236978965609395283893173034067951616, - -181087839220616406161600499103312176020065495918539935242087948667424505178729234821060097287477873779279208568245052923594550439915154920742117973042593791248845618997937010921890730737697554543130894973372940686606928470619301625216053890002571949891056769862942348088678798828289457702448038435338091119466012344291915357780747202732840500371166081909745675521098820311601235248051950158860687566217038871771972725414803648932556689733983833838631005740537565997623911809392793260547843750043042397407799012356065211772805470168553453727016690867858971384184421593774277950453226655222423293602143086971596377853897725054611445655933868556359565837787060307780885431586968706910811619715380301042749901213989583650256882744361307714387777624909036406494917027592912997096753854009631436202659867993922906998520319262965582816642587855214176552703787849737657272269226899537042234030678737206870815282118219314821773049368661718666185472756315500718916013308782197040512544870435833053793930239705537548025267824911961528475854081608037123743493801189071954849131608310160698486499417987633603415377640911623000491580369859947422916190710234094714525091686329729197991608716306457609569473571885081788053418491147708900166119812851974998703840631942218184891691755692937741566480572783223828917258478440618155880327651532334445933265184264234331936913136466356327756695563954828986366622957925919921454505356329536145939749587395901731721267165286488783670206186204295160027988595895783742763834680764256415290925669144019104364137088861713900626376829241473741585799604162813235149695836537560443011907475324861378211071915894718594856430031328651029400422635785909059636114054717220915223545175928508016367065228466849273966824799678258767347102105394394750598464877724362225267869352381375622239113641102069667379272430934507818195395051089576757569226252113106330731410287043800403982443532101131026127533376673611737123508421297752803618111783055714855078245494480608410306512079982003988535057193005264830782957256818405906268236893275921961022916691526708894764983189699039824041687283053097704019094035544032796531144187618097758073451789552710721420358072761991507776105088608820421160585841420722372561207514410465554835463495827884600014692361820392637575106747068019058571628654214081782319772318611306414973938898318014578593434262174366706286963495517490971634145980408912527614314317429169282828143598008647305647096057442183856924989379246010691214199632822651287157739016642075323526414099092369470935022196507910310415423557405857684367690198622133794584936493536180506196239802676934216118957661301937119777070603595216220525839110301180323453517288708854322100889673833748960855253159104761997164045505450025734234075380118276053546235709932573322542246158936986904183859014513118417598982264186027166127365413313430913222820488313103692598083980773833579093845122731654320922635995094701522994661821436668480611125432485043605410833522526131402831495193478052103578439207385801269544481188209373883899469779938678762902877692866183281966873664542568086957810436245399452320626210683629413417570444031985001967362316997109319414756219136013197418437427552702658296681938911924488511999765925852108041697852856091812854389935695989744861791638260047926591652899277509368420529812461810670112343038776843833772663124557503464810979043501999389725618375321717096295411879066702807941717059959645024436332599783808018175697066257416752792761871223250042942306708777314118033036641366247368653269073626109199860180038490747531228758334649603722088656749498923208796107973654252017597968394874806771091231886368378519473746889345040456672363416794073868614853418247718374310754773596363491528012888445189427383581910707046262995884750256731446543659711506386522203524195823126520908058042588188916065477329861729353039370719693770819812532218062561468339500262702887778504221698870388627403953797856050836668525061402434746829675766027575779065460077453668965266753252171946544448666837176209953682104555017381436412691125618263514616154385387425239991671252596249809951073798860262144379285014750170188466057321025570289405569609388443286338636403934358242067474916271192540958850314318002636368578252241495906749806826404775687299875045596999214247117598832833453764635629752805248369064714929690145809038821134534963043061992420615752345045857478206565767376176577627493770875174921939107129027867491838345711835475512983372417909438385766170859215270707176524976842522043406513189437183721556614828965362363335913687296413461892420787033472738951566465032912049613729630315014161857281876171187945506690510189657838997725760901007939218546376459174277640464457576598322086338051608131034921017290848899380072515512269036487742423201012853593117884453004334057981094105648690045704960410149266332289935923130307890125403119372369370200994585928203183901734709104782946459233456426697171943582787559868832342572915306655567105183743507557468373388806862465149459499184953071329677516448384358547177766015259427758850745951359421672132293883820649901243194986900025985045541960356699305492855256485249065521893840877177029488856138486602150780773650979265444140660330276344279935801371762032870493056706606759952644197678018312046521563530660692957488931772682273035301008459470752971158648861632090564078217076196342482914912472971834787851672914119971035720301497235700397692967806460328906114251206710206369109969832194809540035737573143763353500440924130347886589935070096036232907227892733898951076397732791859941625920152937557690456299211574313745283493729268728209186961703472486767670584660938215487558146009552845663134963907066405585245631792008083979350600221676430989140310064617670947914087147313152453778409638419853868800374874898288502524069853347022921817682709338922883297555802594507222404261194798476482652766841747650197916460663674576525760167133630449596305633694369436550220396851334026555806815228983893066255823212901242333568227712606346271301216792754377999824183022493434733721029087396818877855802790028106499268532155892580629731917385937838690394662764229182055784538136531051417526820411664200115846485525150901707730945914444179505516922488481593931882116716296624032723939290409028230283787303272296547156832851535442938033212393019352380318942529877246699203491584555748227789702906505489377286976840689771851203080784791677508383972782655408813578029651295412128146152521442772309443474172164994323048854372942375641898424214992087507061334783449346995167066528555465372760416028586728465513370423041368620131132594172619244837468565863721972320112939797642664316786275982678235623967417265529320983055395604602064497022170547697020712370709523786864832035905187532100411572246466548042979652837889531750310534447104, - -1993886598258793124571685182502722575351901804033769639307397801342974354061512796921807896892922267380297968562375377088214990552372994688038498140128496394099143236465273392028447402245565885275839136952253916959105172070518765967663080426572171904692538311784627713383800443713358848071644512612192547287802080677840882732927900268233748757302631888132463588730849945291975560248542038218240804410860978572258988983127515466492121812914062416372220181913606978733516527375901044182863784682165177513060880344545672750473595354359376061226718359422244458949683484362809964549877094290756239927182046451692139690361857883234333407894759336774288276379048342744507978862367144720704607391162896722864074488458069784885586889624219348295577042995879279146236584111635558176402886910806463623049366641253216056527554752340579203642664428411451453561317913137311448052220734486518719164898178746684620401386389736728196568855358349626013684527537752286101140244631714219755608449627310219375034421907433219461098793491585545667461117735073677197189174260832400237686363667634187937365563168753282921430521756884519409765017703097346353326341198535467505474262698360403842353445263082040919964573713993457773184864401391548576258176004801625091671712212329025180145008055055952046450956058858948002828974462546962364243195702638030516632937539839518406584693734262713502566666131916190328856506907016858135696074650995700103450377602841239911808951371527868192431130853876212972469849527420481469786387320378987539411762754164269281257698816804173755376746183887469817928281819186910185569178894015476228075597861446053281745184682910576556848749611984025064198326702362738564378148481016786321521233216522241165114313366682508803290219934890155069421025034195552984676650730821476394574610952846231644074253966596211922669980101860987482226579544886027929056347822368820684740663155694801842187531410956453891061762565623634359421900365575961187549148015441845029598832325343263204380993336421532941247016613498324211333710172521957301037805830973792457719236964641107003379870840021827193140460350846645793874983558980672054996109992621011789137264817198241139866668075380242325682799401613994119164952210685819739637029828626391422224571330353786368251430543146989497759123774962398208858679447724096291575237182780363151154286302263161687963294290707676680829098820911997261357039068444464859628262389837811000404163501304011605570183202847205601090224504950238837605875014226258331383945971372788988266691782607472789028681362047868112426514055409708293401998159070234126305634085718745543246243478722394204261449700098242040844727046946639101867261258365436010924036649503643522195658461961616985591193849054223754698490558266622167712995762494219175511814934899952823095288900103257277618816663531669893306021178925673701207631110922641480488208640634303112131513607080983553008806615962422199427980462649117684997556306615023875986848573718409433717771997454835918391906220246936409653284785472051834187833452170921322806367280041125146856248203704368778372647921734638168561663101706455894069244790586165878873216330001041286657165877129147892443573768266889073667915932756044603031713311688219755531596322317193730935180471849721944617309082168712523094431073169621107048069998520504964049888768474490822582325836706088447280534241548888446849394896516190394475421302871721506359118929846893815105864320249116453819098815206726173702741296772319159883978845090649851119697922593096517394567572057456327981262849069810396949566133223074755490434890594258141459924869256109202929484077048761239796907820933261772311281683113371353494456041887080749042220922350534338048182445368714412879239798685031983592759025471067101547849125350871496129247130149477135858800405467161720009976350910704019045568921750265254461092692319692651863049355877024137731631773459302948740123588365765614441746305067698524319752450437931066439758140299250225828465717101147171871225886208571936898623404372034485778113507684891111732595041526633084133749823479665174860915861990700425182300572840263782811369608733949387387097546509355011564791181134018131965979719753193967322183817658532031307794316680206900124428383333121629685495367356695979458452485142772327713580998434757180704477108627921759548735175849432155032779136661648916966666493068008359701040768301917207633276637022412210071057905276618019579667534510385469516510743381263374770347896569006528609307365951101357710313987944008522332207684998063835343030819180473152002701325901611724858639243531370130268520410650374541129012889332867339224349014767347222220622741128387215224426956264964432295248271256318297988297872499128148625562675489422799366069036915341857470222641773608796291354745780795500863858240251609766222027621896252089786574171836690527474902464823711716658983385641302053750847525382114110319646078727188052429688140069970384754708668251711242104543258066624641106173562122838957719267316424691487263985869461946093890017264316930875212069168955786797122060598866000349320149997203777856082436042253633647542577770358663875290753934283948852925712734677239957209738762869201911163036972626571565296642520392409700470054850835257215143434175584620579221521413099685912992858441542014291561649933781495443327631008643428395778736152726184412629849246207108396148341503376686120042247236795176005077113689219396195310187317224496198360834923436263683182033546522662393894062302087456800715517417848495423236205116861348299623757986981030828319506797413623898867779318086116766730719811401164083648775943307303119281248510471533465531825728980931946803836682601019249367509153507581804454149343436080111284271561223056180774345996579597749466834924310592314228225958497540387602469586226096550327566268095115257929046553867818407281846313248466014230806484777200809454683654143253286671153666012749468289752496760108634342974073175158946807948511714687575749412206113702895988753595675016157919660427979095633369113789385953930141203807722122150481928948406954318370568818024875146711591167752214286939622823442079283353883171804619798395965994706088810974504800423897697394528725706167980666290337573311827500727361874524514591399248652336467938751613253878872970694503839116576935758217688867625198771627052932425333366869168170906225554665818774998046439813981622985923886445868105344101933489443248158415525925156676290049031047712245880538824007569687659797558600344924398880067673512427131245439498842997643203278473429666009169806916488864102731562436849220199431194222437009425361926012600579918664278593243519516274381116712432267563566352269316528883186975044334972363154025611388234393889548198562773466849199788769379337808695733287931471826126512386211261387374592, - 5866234343984016012387693962678574547816595102341037198001599182269503791374597825393924871563007865228905367381320857686001858420924283298830691454136019179315142454201442647115531642263704791061265085238678567365652118880035686126921856466634349983807992800989985330771154012441530174497265216587654181544534130028756948178225803184147526655407065028981649349655463667355031504087752657751991387896921446109081007746091046003900058539927961049935309990959660867999565082333296290731734044228132618778313178352760830441102904593829871288539964976093915162023427560985672176391597536727946464296731729161951379386635626754656266537706617945778301619962702371616542682388619904196548926567378808502121948091702017507601985717209385160527916088725882662185731969853739153516598043267460369035767336798347340822840608888931445963315754296678430969501395502601138295413850782372250627459698932491202714265639137553033093288571854013322022185507864588653398381298843168686791012152554889394635826085615323399805018197468209183694533874509684853297584561113524588704020597593887997272592602990465344727518811649952132692587925799463573779902826313472814379818098346069717003353134010281128272637086245942710026038593495055421586018311589554030296748805061954408412380991667901994199213690379173829294179214032568157114509922658816366343623663668919597121555100141190435187119357717920046880206733686979230912896630045058633243446320087049880044993288246261584284269653176188821047286673269492051188807861385202667070432123986447545627911612701709842454466671341232862771158003914057005019948025912326748150463577408074936795651546980489342329466386752290520694150838762506143915736776448964546621779069301836284332027659200340400295738752061371664455820794100657762763554107351017842428859200131117456230975719216356946559318466756997584862285947313633805578635491424759265713288995687208631936069316550667479318834640877497820580845374710929618581285622176792285456135389761509897346452364441441744593945610984256437155783148721916936179305488671205519334182660432220452964117188027119743671356190504097801496119394927952093578034574801786328094423329080164644024438261144292308998363416354323122882340897368702793546858717969366233613426121021402912412990664560317972088233168538261561491675011435461719611268111501635029511121201242001538856492420809211794448708872580310135986016825006546426909441076919541647442278049288449271647933497016956080550356478422331000905991716413295716685370091203194111166784488761597639474386693704710400813734626322475656827439861609550939744577441875585155434381985344245881703634783658813659702712081481025491935799130305807857573111670583315537969088624217777374382190103627907504332692520539333111513464184325751337312696768431413840153947260036083365344677149728087711218632402324444062587273284652109342368597173244231458577446480051038171948188478173993278717281414060688690899179688056594068300155382195481944191931661047499382167873527922505985530264029153956947565726246761783119206279107737140405648691777163230727230754968613831245695861457678667630396940593787791389379010978525472037804675740865881343512379485655010696931971425931534301044018685806796406566510495323550881733213295918305321009578134479323094445077862042747749371891522010802759972175654948090459276437439985823630243663464273909058507679233857603279223122267304771285083393108747225011751190129956842352507434645168005476289659767943400995592473433796783877068073053529297280324362689896684073488024515036621247077203055796242706988656134529951489073566151771542524654949536866011829406830257010014790510053502783659924142719535846123601608610282311228653717802477720100851543357245234179575812157754844270540440502340810497694909049571709007750668384308960031867187709077030437330486201875922621276825561893589695324679203790019740861488197735089035960218651004059728475723188434459868695246659100733074272009630904636064973151229410711067861358324905731009274460921508201329330056837783269624195588907782516621955903961374881103900992842005762877337291615455963553312830990168921836091968133284116211901800474814446802477853620344639453976976041008509725164195409208517734436817266906017509223260602222043624458749598738049394269427106698536449924698890889188949113516998340114341791834855065022658815143103172589358376043693770450429496992385464006304049143006017044511915090915051295454191777492877212706491932041099721096504990862176145452769307599302973627433455088978883154997095648798413024076994017694759457675335211113743725440431015735722257423028604272811009645383046334634703112722579136895729211943699100424271792328851623991261628056197788471841330477103532122334575404691590867891100662869884935070091566587167789431815171402669207094869007331573699278430163835714487081554152212062802238767961280728139610601743964719183719674670252139957877729915451948200104107114973964484705574545028803838324620022300538412692268937682901083112358238969380213687910207109506255470528484798920817994951555203998732231628375110041945062388662505350749356367178562568103882211453801085642200779278687301951208219609890546977192687846364255279903580524782090508494731556797173236414231649251247069028898248182695309483962230538044917706785681143027584255970363735137108168319267446115601241315828890865575394584235784896218670593075619265162920383152212761880333343335358615981522932914924137793998377715873625691842071069811899968406471808652340913244901344531990737743158953275453580450002571877635467727011024856927219846524833251611039397461313490853678463911523058752302757814354115650488364515669352860378481199198840885420142929670661023667084208484618647543956997244689016992434003297591931067728652703854536971244349927811452101135384322927768279225482472591331035394922368772296065525338983081227885999922618364598299858326133121298145323722234113483756152107178697574891741074871807177723811358611281421144770974461476005227913054899670300494047610902524744919198209321427903690419394308397763935742734682082627910531206583339492801343948353733729473469903670847999190403764026627404898077677864182912964828805609953154004664020808976474805679607433245920165991727101561785823193953845815721473854592250380719941958150038050833758666568139692966418506008699842411265206731998872809595434006845453360053211736908189616528451918864237277500812019330784784079277070540189593708019306996171074384114523677327391706180783832517326359580204628656503689471182166935577181230596491490239514852010454109445965580073407075579622379987723454516698588269264787584921557439279314276103353436294536728055373214870671059291922775674086981406867504105342794216553568945865544138454957227013523025583669248, - 683118223312278441861634596835535169259201660038618217624706800981064268070913979868201250494454650065914071443487836682987400116999992323992710064006824071003595657785135869182730900798201800943983976732913279762090035923193799428997163659449691369941973293285019252393588605834587270698834666350796773740336850964393632096993851545755086354297883160807305694867310948674927134723097260266876427505272343438210809619986866334913013583598073535882167278671059688620506108362340537188861180033264923809814277760994244034197397469869018552734948956792637033845767371840226754950657689117806461671051486739000007440534047626056866109211949998706797318306906399702472185547298009761864046652852546576214833593429800887059918166602549891248719760740311026962978727577870712674340601726696801637395243445607439212344814506558553328432545379083412811028243649440319725731658385635674548673287250522522435862727812901193761397667015258716466816838488134547615438504856015873801187762002415777819572143553249441500901897058908391572298442005990595256400031613583281034908308795941284201395340195276722889935060640015547034871482488281002663826719330063855584894132534473398893961094700673331838620503125032744916071896051854057288883082383497011988866638607708988125516637182367553780186893646780683392858507077627393498078215662252668291561020909749742972352978589779753467914934271456900939876462231151686667785531493847116264829654172676104523023585648882849060428359094876635270077693937382338448262129453778495058101659398320470809549009044421076992012419965338783486605147645539402797570524286766742989304300984292154566290309504589500964248246596244733843023684508319375584260466743345886722542820504210540946246092728554966178907112630317819275041870372028241419529509734652927939853008833363176323770299523673703083328049658470093931273742881293232103962228612984004059597716770248743690293030281602645782852287157776644581906153205943828112308277003405143876894116506424629380194411969493050346576363395135247352677303075893265411892327318504647320307774375336663213942624705558879571892306497240421031027831912428833396569249161671873714373182629442692298655387508929855831741147195367934462300904135640535232327982615075445927476786092561660215915426165925681972906579930967840154498630344112745801283312267359788914459758078789714482755261570104766783059478656311957471795273069922400557440265330703285406029922466252567528565345819243131281572582837750667045161877214760098177294718174846972917621357286615875589132964355929426948724353989290569699436601108702825026578784109494840351827476181632955138550748865955823272829921767839903682716307519785907910791303836407592524402234510487045024345345930324119393970349520040056197512985571756163862493620498585097191692002805983706302612768353695175080857731005463479574078199779665346174564429690190713916912316564581474164620426922997163328953994073878158706047580086447779271805119595687465574261470402988715542116328956783744711740212581581914912122828250565859481170728675066929622179929213705400046489031152535332712110028111681884839213206867772756718285880678804054553865955878642621046429947945266357195742027909669031555005578717938523286003550029263523749289311549347010949748619573556893027735935888164480767207834601810162251291834966942629879149414961542937427095150252076552426114177881669910823065163294636633102253624801360384351334073885530746197278039984692348248831510627152112576952966985667292957718858207210906279903090274670559785647232070640786067317750139863965277582276590773118669435657482074024712737422881070030459677460857947583325230702037446211290681507578759030410272637845279690724237571301785380549068762689045305658023874798549545441238234491246160194280159868826407213183615700239047846820406471450190002016968216035082998255553698417401157531101472997371622974110034085751392869194284371675977284287745834395232245147403915222980184007258108612673184380385397712284361575185596877289407325479225576661807015316013336538123463833426996841732921113624519697845809560728973214745249109074249547002164600584078413408686836688126709064811472770762925699851881207710659669348612131772954277630798629102409997752278144936906885467556135287682095340656544107197715606808400979916033226083216746828110434113899282681389663279413542822221193732257093608196034994540605769940650640742591207964112867233972083986246238450310565291672285562960267112711388002774247950873150971189223134494693262910203267404234136193115289890421781977253665407612546260109378189102025880493838089493567916965767492733573209405842383185847009166179765467337380861575595478904635078405219257911309257838161806388072959983207092790099838875812371799792648211460359869063019278338427344134020573111422569589393867319419365664258562624625613826464210069991541554934820712463381661819543157003237935251660614955548056817921665940532108740624948640350493503696525927404720352054117915201502764880763204752155460220242890799168882337141192421319464969575405805909506565555487329347830634297419410169715955042968453275588361693325252363677577126297794877269316108964562304757105316807829351563775555149104528847585308706871598388352747652924110236257682354208578732974750824928712755022566738692590627691147575070530088635698307665456319983376463979087337852829153934923561390612594233728985673372904411528446046737867247842565711405684134389804489587341501747309188753842795711374302799320966863870666628653737009314425672662045338375289479548071644774184033651170731185517786280345734069740591440438497783718886231470670720125318124400389595952341465206980570350035502994323271843519050147162671685339190068115870124806881255229494408404285977428145091050181276883921603419279952984786599977260199528288574983985530238891304036249221838298577619845556122518505491545730502170212220237525373885611095007220742139727108116834987541094119709701915120049850052917671912719243075709475596827429860374337418003016404597406853479004668130722427063227956838403322537432808710985282482219292535738639504988693157737762352583049928824997839167579689185170174670134561788404999431670728575202611474828814794789289625512846615801174724470999021232876450986096095861388652556173317769873195324765453896004615541780919960232134986681969024309351744094039197942211707278834325575092268285954406744914366098005607027497600180442163970708534468492456214398656006072512167312185238701534126561073544903604685230866639033516758616413418342524203221992188331244180253016031088243266772759102891230026183803136137189819441549949350126509629501565041226273959061363855970207083872707338781268853331946241815121878376132539252623087056129967053808336896, - 13653612294220839393970639246049111125159084062274911913732044594464122959811542312611735925085212752235139829427286757921356620856879989016103416695761869615000102262817238654413688859999071514738436112426094978721140874915203664098322966689691772339670381922169031881927937094646717454438123176927585108247221644787385784570592434474177943553674249247213266881288591440993244829662366071434718816045248887975956453193175235066597551054296592411979675841995988007470337119701389243176455232483423180834873155724108334219066677692883730482309212593950109102786608527114009122782344184256446290731822431198487461873256631717355363035865720685108822958218278970455462631937901970982601577361018263294518856502516883616353605883396073822461809032605812633293385078059603506558764817189117512407363146365409365329034258497484027457064536120805425538493153943227792397307383308450750450761553413503496112865670229461649855824375133518630498290840174465577814040016865302842456388096159387820235516285526627326312849100696822273327630161870763273039542443090021206058311287861998071568614094877799279160430320629800538747175082779009963660446834293206993565891720037860282501586672896606932621694787351044104922466797645789643505821677930329027162213955508948220060186984775359207089465841863273179745881954402139984539137182441537657057631894402865058059901136624029898775320485627034424064044793059017887331432680271478564511693186653422597520622620576390091821963686807361308940251751681425867225943375651739606548552650198716187306975045869953532002340834006638520562767231989740942861667302959186888544791435513509372348502854365583759486309300290671426803311938629218005203157934106435033158496466823957518021514901442101377933658368257421100088538977192991521609371559862953426769888813665011333221324553795150360460384705346952072444632801174133473178390183711822827742248827814000035121129542979791734538242625817728670111498290682849880812233498156082336844873820251829015849726803329604532037721175882337677183073836860025871818711444379111862202951095557906302984818053365601791211573557021549917401018612837336942516070878280005561304640420348163833664941038158626849837831438745915758406555995008264708895980047156834440717534900206533908276164173130837721887037964652675379717125590979757520875652188292395251924052357873816420491091208549004658090410589935669865088971421893659221062937483227270576898313519136687362643181790774099261857445115248558222763838211820904638424194223797430993093022557674075664512543750188602586219861319593283510734275471501016553325780114064230150798706271874886684749511057593485862145638290751805138003113783958565699724772417892780885632387211792070610309845083606824798519085360261924655625741913599574768139422830855875020568005306365346660922030109759765838706080478822254128872451998692973985397274963049885005995593609727440325221428891000820510761766692804609251575188212336660646549911788066724579928428418435234326474917799111886179765475829166964965546739027426022827160583000048270365502614660748019205410038850957902022323503634359780261714833276720558160859066752901748012443114019243692973508262213378028652888960760633618192721138740790018359807733407861411066768443411195141223168647391609607844450048019466393974416449591897695900846016978753945790903607091278188141885787696809198716033613055918384119490526579840860667491099310363880765035422740554495954206329895691363103045100673028383757506016188867111924214124403048524160924951040131732071938823121317079285216934742837140028689232354965866700092604730063392574013492975104184414919419691268508214406392171011252006636368151762128947638954447903608899024629821294177768314605651648953824108231149920035658089420416292118042657109613577564012795279260850198758895454159661445763439631010170912697125904274282794687993686987631712051743659108768472022992810900487499623052894718041953501006003387483693158401543811049823906854439083964003983819575718597586124492349232215797427451333060875475509701337301731359832838285338968992247961069505141924459069713368682770471911752908096387376547917169537557524403496171222542537004711579805797449830490750448059149077339080242063337708814051125526304859268360114050185475472941065563406935804946854591482868388339965010600258750008218728454882072230453013304896656126051692269667101087502782712397128643759353303593918852560753206403981904346571464430653307643781977479170854364276734030105133877925098863764831337507324716592086710814837174827817425846412181698451508355408373003444933785192660534668585296051529033001156755667229322668045973712644498749273400599049856848176984221474728395538265724503531035662560395149277538175515782942949671941928032963103701433105318811591882356037019694899863793405632731206921313282811920080600563508454723756872917339031588394840861978201104596384044864249886289309511495186815786112223721760356812267361780821939248790420718404767250169891874814540156679674353001588913237853191923152384974453848950193004415899913331615939836950870107944788649162449323405164882732868921015239287454491137806188068540510593730345887729902578576868088521944300522087076478282157712123247590934428137550709929449280993106371981249139867104172218269340733756860062464523151408413421785574893710978293727543472278079111031972758074858372804003539534817506869075940602575613404603078207530008523205297836275215337143395588246256888475430927566970457618861016630939157583053315878078139114833994261911370178470179842308378265581936381156064263587011259840229981597054420451704325672823492384192788479808601804782572541602856308817488512422195208677436198953863233829868899854619050190637145447571543869552685936108893384688174680339917861947911905992823257078173510500340333277330948050107918234455789372476959322306828107182617125240841906770478518993589712267311717450099811480456811963895235778030918842344787164554113183997607654739602205457943059152229113923170362239817122699702362563034368254525709431113913510722392477765234406809668143822451671743815152710075972665267058346554378006874389596284743290875716871515213544521546035527853557234900245358348666657288740471228758724218980340281750330077544378482452639018872276250638680454606898841739597381922641134212062030791656693046884634655112460369772688166442844492501206924648005199756451289774962033445910121095408971340616854594680507156741277128617808778899601929563027298099148239017691242930383167541985086355618990830532336066470274628891608914234943988886155066048189345024261757316062738385629149185017588617012065263039368190830113382451203984615854820351874061825162652129649180468973962888728592070475776, - 123697901491664964492775450347742037455910132377833512108259865174778968966223431543617347560150473650409966549287784009764911705517101165054022914885524272294360288952545403031817234164765380146918639223336445809855971974938984666599856134838575163002555921159729414715160766958217219726149070463730326930737854063630609490965147405367445565012432768221129060248020562366992973363598873120644755020722729650379732543860664366982616211904061699920989034843998660344363013546787059280977764970971950556842208016620314382855606267429535478522781659184173301440739404209435741826669793661198727275249966801951613032814372657408365683875082501660953804601326882899533537180875404469289094463480892707744326921971507990182936588147928465691609256584525562628937731846326395495279444868056635349043508089236116979070631741508093205395167573040883539685180162570542606021407280321292305463455885790780056932449751240016068014071813804225145683602017731353718448586288000369015024827667856518679012507372525404720207365854481345708354098150779654490637090813399050189559286249499310093805204221394804407438091213057925635634490473465798467330844421394656090638147157561239272771724025408973434469181855661703374908591008247542135935326841594939437902046220024688499816378477991689714007261629299072901898439083625810602347407701739535421317468604013286048544618441012805888904998509870678815472119870144845438326195134196191460819604742128328399742575380501129033388039148736693058392628698746067137711248954999581959825737772042420887827653585321206831724250265530437388947226099208875679195055818296617268507693076835324513637972359904686459245051091072880051957936886779374982925049631323799226326971926224327514116202992509689466501054367166458935947559222436971281216653219849922726317321894578265439073490756578333534065244587834639061048321436669269449936657774480035555173320525161970291423855631197746155675600454957516203276316355299036056019378361597678357598449910440019032720842448751025463359971083763384528469086849408306083731185267538210850608332208360363553735075512911924893994659144131072547377519729525270251817448350943125176372132282103776655370054752093729394491468376759118231516145487531804333039927816716319758785093978571423591704086563595209427132771822052020726216310531650787794992660671772340817181838514465562352771714889572718104334170382236994822574163973944652645894749518519919823526608517073216814637589474647941822635877258886084396491492676395407364008868526262613481674964354341389754390085382854734074275533131407540669200662447329245585044229760313635162601210791325610296930013830070650330453652583500843968041461966577133181043964551155464128721339231805962237022492185107772862158825016981528223156637083543034485938860785131695859630434403187981645491751605522959544740538543072829115180805261236727997753285117031508747612958824216020998488436593744570514953496901261917400885235946405619245166147099501496548542379458269666133550818245230731790430559371703986285871497624019829566300333827785125933951973146514164835701479288843395829890347706828006863237961611006356554988461929668471652755239589733197736847324648738364704222766228978809145108823803594755892143960796492213415233472479347617648800318929092734054527864405603782946149528359813771122321361170295836571886703927373442332782478639095448836856606066611363921180373901015726902280228320442726280056419623536623683220743699498371526737532681031628467430322155416984754553189927666983966218592989162141446580982345921122874324136787933093541890921210682140319159532244201745674803043456601738596395000837245260707142119739224444768988076830014470766635385273975786949114687170899106476323033931357326299523936065035307129093749279330599528873272748028355347495421170338048923941013169910077808958521359639631447880117583933699583296450305504831152637231096651021339591841579845722978344601854180204491746630043107761903724525426036145017344497567711376680421935320005014193841804525604158450938901725951434058376839803003343833558628722570303174468952112799659143343993202929284208113294274364908347733481903159940638780580208553927460572540030171439368808398580479301067401836068165494916584901970235775829214048145075307489118273917371846943855001758702528214821134085704205660187140419081944135417628142027480120024735060975172272676826433765596472966745775454995017376775556059877447661751296164361231479720543738402621417637020775305466911878942925028138735651832828756059092427665328740512979927356407423848582922881190695538712391190100045031428793938757522689070770107122921696671880838303686779891821334499991259393252407673094778901073574886025744840269805258022499914188968831562952634394641236386512238279446937717985886824588652920333523544672847178783112695574889150855259415699876698678511622667526540971081999372831755400753671597169022396499431683224719429076385584605250108532780364372929553611407913669482302243764224570319432185899206308533828233949334092046632436658955781430048000235431389726090450668569909220993458713824978394053672375109930653580940096705053300117529023766679556801657845571996757893997422661389161745855576390568188522519177188885782256068893344836082203350279909078687821633396541742609033557328600889388496258017839626786692206200100322394405336034456498274413992732954363156996531877510936074407371578270843939207160855232686917317470834466260791988518282003726745990163439919573167070250857365724575812541135282775396001106225840257550789836557125614899087130225254500365489930906265037218877113373052382087997564701842088730357306905950290021823827285629719069710271619790741333740646623166940907193268531546312380479029448903854934375635743429608342726470977013098004320097442944301328576485010201972550361338248392968007389095241133683864871581932125766761136699649027717910010612437679002934381821452093472157374728789632055064509093319075395280159576239445831381800966759602341346192880947953403020672325557008809216269803399119423936167695699699475663448907954836103846628875775266304534054952834741375484044670868997303202008415898831626298726585107837902636515417156659030715977948686585391179444723057506048780282558635657393104152782685671711199118676676986554749096643274757340185080152448781596909885384813028431376532173817876426492926209690055111060496161475696139776944484885555529443443658585945679857912817403092015340458256699227475312522874606196898258523646929134205438316879354518950690910765002909079347204068404906734644503441650246057394522257814606700728605667545064086395070852570053935202786443311635060034136395959226876473627583766095008190565449728, - -716123013437087146248739077438716279104302709122941999237276595166441984495266260497186704640038801756974974571112690766606864270100850694129455589540426680491409979967395074271137772336207162666676112891467093449137778742231701166463348569798173761964378708243757888121588859742514310355858398494008226131865592304835591439313151948106355284455199344659189575906255627326186589875477717558276640228943250871815514519518813014149631578547102985145776937192427727158868767783295632130391052203709852759125940352965701566025471853565672415505601839999742875198769134831645791891686639653581182537281123408737415703418063740100097328083525473364111379233101135877010024183708928482112681629103493625702561348392294909162363964520467324088523378723570381013461726775808517620440684695711751106164529992406983678986254954136381108750194743931965657597329034392109668937762928850933009661226371137011755427676422963829010087216827159660756286277296837132593232206909768652026397012287965438641130868837278736109755658549480778393552556904934595242592729880673545385719275092004223261902176548624315226874833515504680000757903579246360177256931614589806905332464292814773903805579681645788833338307125683346200029375432327739685031115242652999998229908138340248519856462631082180657952432186657891859580939498532025507358776054197373739921620789872294765123084638130896668456329043731256427516482036159646998612474306461316572559916028061553076285405905000629123441099639715445763116878679811842766932971092928500581698956905313683417625297286731012690946957298363362307169413277011485487064359292925894645429753200903086039856596002339934569361919925921417100412412693222526136382116287345495176796278320434415215846155725776671392331808274928016862342123278031163620570271374976591500973706345316383249685117017419829153664137766647426086918214534545584518553947207474633468576971503927219410578451657706852053387629740625526962519144030305755263263923819734507459403358057171419439888399752783952397833983629096382793090139518519871225602038662812542520007872721260834378663672769511707126055918051562781778014842419471880413864688218411485884395402161052294466668443790893315314829372112646846310702515763866973694027146065928846003693440481867886222519814520627803977389706698020503796312253341459945603553218216874895939489922798548896397232395476423601920031823376000825997408225149593410882984026254099900272866265939072623444523984436349139846351895333107367468757798323878154979876546767554432917143396404266832853529844169657375186404120893935786134732137096017405101800853093173199730471428599491720036164016096477825415695637280491955380046515808977286181131695000749110777250712479381777889103868186914335173804842184905333671708298046856764136536442391304231308839887578033882620552972221391201805969953698025466914100095061915724815740333194279883464143828477214101173452952016626298931747701974677798230917052434947912618558446977674532964573484147903391247087093132271159151717870503727401675392407822059605380062614332307722207730159481902054015430522945929725310827220252204256212787604414323786904067304888017219174741185402061717517454315238078696181672193122441836505633883143094843762405430570106809430141143152739152205254636595313323779936258077946954944496742599447787680641644397474466185570916576723223355810850212923374455741004388281810005425961584516214456767486274502097317962504922172627138323464791928745654137171912814878133762324536059077717899586887436433204473994660882255299346597866773113717163638137413932332943379979878630934276863199489421886586691126588281045588791909681463111675469873831030406627368210916881207921130951662384852365329373370013943259247694814202010645803731189939601289691985686261962335838387125207421591043665784141858025937867446323322433591023804419431842419663403573144130470711779053555929473585343611568028371695678555037857679134499819544541398129697970936098146156612408071957293780372662427280006675871963308734420680322047389800929948920344794950182650980991495708714322132594112082620902258303023239858837329377375803310226431079612389620196178901204281915229708430823822080525426660780197159657457909552725458473878760159664168896781316982612673865167348581436032040691104001487638712539531340277327268960449592583037560237598176515871923408121686559671957637785789999901834094575268053594681457106275804730012240363058964935999862508223147601076810883853190475072203342001804824711941765604866002218364645285922576309919697005484404329825805942819775571782859265401211809701405233703298898834382096813603634284495260369325698593515208683096292329750540052200585102667829293617685045040027683164886966031647018825902193786671775006664009287290451161862590622256298290761533835327662251280425124590218907382301528677823335555744435653023707029786672910528553973093548377339883049343671824323967702975152286730134596605340018347703782805124570796671480366025608499309921985478555224943122160810521045082502787538874374199075194724052734565567574519446792227731104290021161720573465431972069068141206395226608432325868707905879519125355675641811326667549263599606308988740025939018167670742700918620252887897367041596665948090674597514868916285038992879170256018878312125050582232628922188989636324561421809163929237253345956564443742859689954599864509919029499591301277117798264812891278701808090031713395682787223562088587137244636445565734643562778671209098146414389919557561547987952294120234439478957586118980678379270879363249426353920381875470437068828648713961288363595525645222819410094726906013132965488151730647363121863834430516512364352619165924573738189235805255137887697592947805749594533743078994524954621082859129087786082879569966266273607390955240855383362765120115863602547336936450411480041694045565225224132371705882498674656080007866574184024048119614783952730205635279591643229136368616589547533821052798156941664889509935030353633882616311939278082335038015160266323126180551886324645243166045766297386921393898025860990267613430016040253110615790500478872965886691080914874611358145838498722526156385521723048928651739778644577382205937192390511490306039113739583890950949532744734265187268415562717102075855000375392971156460084817450518640950822644323176797601538556521565409982574690376721768375823010063947635579110409797813265551152980684502952513359122803570380420271509160161611959828677452775711378024341228530392159057092025582692089961659796978319291792890226642046769148839142729433101214518039966010427092370297286198145630998010049802566684542339893107055653784159637728943636386977585037312, - -44752767458901039454387851404230167992023615932420009085350215618819452923289668961593697943635268583681416395500799376929121393385972197168070928249151662066997265168063869071024757731737324124189187898145226864285549254253721444949900847015751819030546744754468648929587165744563081375689601337195372036387358017295320532533428176230215673080799320242783779985025869283146247050306824462545807438590865297821246732432311414493301326449061849846954841094310369194697561560365601765356455172707229049709619685977529356788457593992702941735125987140263374135323006616449358525151510269003341346949689368667509983909906837056726753260208905524735294981622984777734664483239789288232797224967358744463297561303509494869192215839869011412334573351363776875045156990441622949164305308384201275076136116504801287527629292878157279669718438715968169823401558401970104404302449271646638186763442389154577880592999827732428182024489726861368387898815388633039718111510708744777668229771504471350263528240176677734675272682993397246425614086471136562943215782508767901342529102897866167114102622693010848943394914945699782630091086990610407094630375627815941590885000296115904073929032440381280782158332889217056367562839055139471383051920197448799999194439127588073407099228166958445313111461803579380771360984218401818076306019760682307377951859651630975395245870683094584638358234928510618221341443512113187197254772950985461960392077644654363500645504912439692255011594771637510306380154497893040238067009688756822079326345284346590008200001055550745849271909009067003514709017901703889462463835816745474309776710868499049419772343335579711374244875388370224230653991720792023011610177036755729578580066287779552997627791836263781218519843308631036511160609565339739432505787746782285084496902027953585682027646897093695272423738851733411139698263113128493128014191615832162145851764872539179738323438093282650294574368715710721808530320281159479653612807471873805405572780423317162196403076749622704237209459726061755093441430741070465093727795258917828685594743903857173780566913214851380257670789937959177968723736618451343942004783850527626614575628792687269709267588250343460219260850261223902200451025886031688341640508416174638247946292394151644538798697446555247001658764726177897100522659486908219875172448609950109887018703642462078040670621223657035677233928214308015107845156183787725027716390489946167564012501635036226360252931649964701743122493468940113724743603323963346040490307858655138371042175012564147345521538122327676651595659118402256021363263231497064445611060777068440915617016959456656733106712710578091934013219075450480887268081705508272974081674404648213870957650759413628948165954811002372853259769007993381443943419259876837811686439791498204351788919146049839298619057057984825681137817918082366235418620131805599177831530064002106468603966677679261747026956100553198792330074671868312253888374011257400943555815917703007522413998020307311606147986394657723607227330175312828521709477184995500329463083846960689730125979034147946064748990930234581642504735684586848779474108560008649681627409797360010480009301646081667611823328986729175155687313201766862368328568625178797034798999268336067094317100861997559837473534467261445748728060893355838204502760615555711734616837233827019949546705912746764382144351270135259519810247788676008292052094605068651005568878956964916772681433712731707649507242809786463894608230347935804661965790947414367728129308248372157498701227804091535316998737774927542856487124051217386095201626039036342736727951489705328889043974368327240000149116838622459472190487858139008467045432160092889623636891080342502782130199212828473621925744729322183089209587778994333336549036384183375311812349595335639326644256339356327051152146153303027889482494559858622570504929480605148261398207739033168558579823784812296118611819378372102049462114909731792800966435438949695605865552845541839743029534028703275857989329850810557218821300693570091840383902349757117546292581749170318152271644180445154135300439202793514277894775315332874172574320318857844982094964131114805167505734180731669760682530694997459796912760373111562443388387491533245559845340517681179205397180275977916321429995151399989018324230428211792273874561216850951422617389280841867975289015132395090220147814539932249446416219473980218766582648571782683307364379947883520780617507247038607117225037840587766995934635175638891401672712073959905101352446856180196916769698914475509956156944125808259583322571540685379314028203617969183458799157859386390057203675484109531974465581213123098188308308346623468122247211597135408787340475159605250193781577675705358822576592779218499633906299275460437435055541841526592055727138718990504138564155086043747477478968626073179116694187867668266914725612804075172981896154022192478113237961759709761381936531828441588806634177238099514219089664226861142126693788847859440813402151673712621695893123477230009281133144491102699083773259997442696430872049536568975367775460779123574585427570153869091500408787683808085987959814699006035926996766758378290925818912463389271541342094290041146775366692702011501512196040387188097474688616402725793106843324071683370563136615813608130478487288290727232760031632580363724406615362415665991366416717626283415495096263935895324643858533644460291120990088086536720365089840153428028121265642559976194015605407633982822142448002772973757372078358933622588078832174581911407504344083416228546155221820564793711418513349739503460189327449474618984514100430703062658885690628376218767704626163262094868314806591977036630508413189250031055444310169969519040712211236130765566158869773636645593030614362190471623644399791666989287620730261495953859994144937122101196254257015691128268474710799260593010632510766549562974369877245145872674072647126223073439486007604569122702840223237565829741351876974373886768077540666773054473998811340438251465889727150997692973677665773969926322042769962102164128613908826455669360105836577535674693986764402845837912256445732036944047092012877368273573374928226096342009051536114680846712209163304210796642514048498293858857490684687702059679145974609257207347868036040019021610576741400231347172479045982569858501776741682114298135474310106015608876589287837122281604330764631444491579019646513444352806695848906014322710771064743725300338689815540734742638798968257038989143318263826045329234675746993127394433516443210408727412643531258774934658784210852976164748127071810572891613878097859382065227507976946018410647790979018034532843520, - -769495090041388069441154856526625927707495442460926538128866594795886126250171222904558272860544907289680563254196311925989962915708011135967932124460351637013775117316560982954803028123241569811885000672400952630241480858235601098326670281303381738325594575984495981562859738392685142722358618831305962997114742960403857493281479660191953096715356356824795965017879129389144052920120516963915839039423348942253845026949362114145932311849144080996480416457956894968910116240527398419958560219556521796481386005596022287350675510265878428348364102677909113572658173710907948536529393295492715546028018947685607447138372688784033529018613392690311720219746650767725414966531261484827655175555055595402287974872238643632535484894937234562824066564924186741853877130544622421771083992159311065087344695479817794934449562592207335956444409700643255286400124506073977269241575926698930795375815679854549813534040357592766121437097110914985700260449048651283586869835325953758936659611896341041470225232098951739946988582392480332456447793004143206445255750076953937465561525150388675843683304757773146951764071741834629646717828132264840039979320956789639770990555108214841326501600562407782217318578590582869051562573611228500656694179632233457831861388687943085402072514430758882784861125553418382172376666612844190497783647808321817151234276380220949253985665288645130053553845721008923114569133149848635283880457406779299330439609909910877639856111108017361721595118861238512463879843945389292703582207450416884425675187151404355579929641039738155921637472765514658356003043270522007119838205531346845062416110734784586538587726676033555059057579952180861490583521371127824015379481684500467822383017771557767148742292094328818578878221769577952179921450820946229970491911507011460931326185564155733864465394489416498410713118785809955565540423816247687552726920639902304994030932070870395624799385315405907539276489126495071739926997609034760865935897443344519792323424506106978386726154435224537657760923167965001723037821646214582346151926335882602180774065865671294679988529679905774874922988795793899708279291774751985658347765156384071156209399815408833300493762614511079124500610120706250117170415841470176259330162303558124184339830839540521385098151134706935378692583268714658080271694263282951217290038228335652449742824908598434137356544515357481712599665169183767931635803094006722686760734345101554835359417557971530883619718511719234253429070312806161681674001429697779681193060336432539305556970616548709558635579138818757653241162450353193812964657605647555178939701320086423329567105008939634007383118799953936406484319562623841876346588417304026968415204402798846616488149984369442278463736223548930556393871080814395521476872443062578581217934019267070082805071887828815179537063314087326402531153086384585850646599280749750910271097821377181124316213088391975600304407160351973178707909771462333871247975376383306125449203076803382271521051549042011502618167383863188107668878851549919103782625919132495856154673357030070833329294681565431638693568163163011843609442448857536138705918117399675315775890582236422661098644296786092137688881317365375776610968877675955536434082195606248180305687757113622657781187851507087796209141282362715654929378382453761215522690216983876509924655891136441453885681328350313339042432731513865314337640893761183094929820427541924460175594185556591002251694432938358505981401929449198816809060721320056801506017647267010076179856699033157716953050099258356974463070354608686008852254214216941338801047473120510788952279642999176092909597788379756870140409782134581966543618068118443770021056718564169708579800844147789211625739975356886931216401682461171014004937815071112696741643469548094541044414222103874049936628233150127368111583020448331261343479418974142297264217817348814447691353872647279000520784948185298238919644878807702035172755071341415678808276747811709734777882588161631725463580830801053507672775753699409615487407116044509580672699225051443254413924389630458380280362590634287219988124265403958391703342818489589097186604407513546482731300778002544124692118120161392210356842641252783421638671334439206907887731335978503702314734972600263991339514510585850324948412780374410303856417862386751098447764483162619232326896091411614151520730047147136370481989343385810482638690159179470938780051440265036987696575589625485070829333019193644785856594578792250178927997167917421103020543942866456197988357417260661737876651470145399886834286888559477551914125434228750330899865379181938225218854993825197260769092633315897751777933261573890541181141934058316333017840983081713332611234579632473079345781445200974180442346462970693314959855390569697705287521030922381206606406089040323410137045511813229349556898791543678785720811693184588085127546452640799590967957087153072844372639217657658850253454088715557806771599644799522193167525765835415410274723635478076353261850823159639628944414740497588258498334482114281232702052256464192210496479020926052321882337174737900486438362538659059819026766547951591838604889439208679025202143674953173384308586816613688804081002535703238749399464822316259608735745930559715626037909465786322945593498638841909229600450563566759105613348277330318367159111526048542685176645440167363978125110587116979079609807463054520106509809332125777728993486760459291186661171016845855254425230576452424361438727874190306963357214139509549984418762317162640998938711735455505959111624001567820349925647674046051869932247199906677965118883763285023177586531376544940651366140975587546696381445033432999063305467358863567998488927927923569070268493124695461995152888284804305465284362519771605349358499895546900828260857961852928551972529919347800719165627109164683031773752861988104228169708002773393638405856511052330227294528627994129868141834610269355121978861666620091099825808691818390818988118122915735781383262029901496320052236315464445712176136947186437229711014162953759019364129698698671210621808264743127233413404902976676652321127069124637782055736662471944047726261736124380495839011113461071372604218584881448277904851347856825944998814412270482167583296620635437840422248927991852878278127505502834112215655631654310890203349153733049413719099821422525417275560331673472543323029519130530939648169556067328270727011203578847449073278114877961478572373059674138257281584152337382060678835864825670786581334852985885127112656436185307123547364524050453541204697506482000912809568125670110436480377979303383675349073373957401161498624, - -5871873933074685924952929501304822692129261987223163253491257764510221813814492968550214733647351747679812461024672065502344184011135148010063777779827462795129803603436476399271353345049966674068875186337603630339552090157006017842123238321112591492120893989832580065373469560745635455753908152848723029014601945349344021980424223615058812699810974164641526954386882843990365090130453583204831937634402698000509426708409459618176171514808293141107120566324285821235099024455377302835069068857457232912511778081300417816452575326204898036533007895924285967001752492753622380327194822384871003855673941932622122833101154433636944942026053688412393009409928498229192414418372003646004389139845463591483346160375127051220453216490806637664421112523585540231507386567130460752261825066693663237685386258959174924669358338934696924246473821535074731141642622375670316022626928442353196612197915126619639582315270367583158981231128913497555438971924354688088102267313145346907615148629155493035831758607493451792405269619136863020383000947033354948149897043091237648725293624025738255031896474403720596142224292816414393519895023925077000504870064293420660239467255793849455445625926925482407965067745401481521210718696123396284813384954001682611383599966613156029242531765716758832817142793075899091926926929280050160387328713386096024350891779430343531881687403362786141539950455839965497789951570971015372493318701121512174504506552612543405302340235699376930037126489627005485949812488382851171901400437858171171784032222508150224938926095110896246883750722915399985324425258605733804585692841498241633176875492004318141870226685681342916174396810784000843329869722848863254803636916648423667274525410395411818068331100531163471726321898336221844219334302512235170190916327203041121229279785808698188068918742288272498396367703123102246533458232848473003563372651155630077589217811306747266381859280372114341520532787273189397938659705905019023130698303054232321491763246511117511306056444525790980401331333260397242575709958618564080518685792379742010667947137670629545000953640476059233221769502084398594314154096491843767321754997876911967045973408374869496066816231636053226944905530311266098761583344976030602722107569163579953238685172207844004754218040722493745312718439653405595476123418683371841494908118171996558657015721240605724199965634089947849147089569975677201987017094644747299493857411950835039187328893838343387067509409042366365850555386277634777717265884140382532900224212485817161015299878292178919441797224852413828616359112063678091869131106206371844757912888715153273036162485449881013180858420868024523923902691586793262093088975985797692433172321540130208585321173475303208289292383215913833427589855913924682183912922842032454299187938562094207277665424398452915672572916805717389908720753303850653750932966676593862815477849885865619037524315682819863149432217835258320385363571791203017881864346308068855258244006766812183544532592053413394867791760944112453581807059206818948809470702598616888732358590332794663909027422864605735280352714715222874439618827078113916156110333332788111472174889489791251529352701923580741229914880384625041801361582825359200083647498968751493946569741649172040467628186305024626803159087955940627029402236571805008810694350917098445204181380467113223933809195524350496719062031001535735610112975561157556350101326690611218460804544104597468915687466417311003493285437234146900373788409987708134597225221432295478279185223076566359540303674246646861794012589887942875067074686733829110886529933269417239413244176254316919169957084842395258263387849947513996208085716720769092617358792802309121787802310480145010430434722698640944322353418935865075621889123859910910644297529172954352448905807452557413520682215845847755185517046330559117474416480981837546338867425819679652095102062169692372724133014095234900975101391645088872685026258193112752177690413800958921174677398606274562215649536838111495170986291951599265384017580588448907523284029444281596804663598943770006669046437889981164737125811390617122674518507014802425600744410477227814907438156469953434490409854444358076287054993799131747027507251339559677751236683148011233414083472799380306083368223947743656994750694656146901106449809327783836739424834204168149166900907136937400006486879274562696480081170083388943585869973377028987543259976891658651005359694548486433896772818200289626304397422808613781971061586297837871975006390901110305652002274345108432174558699268410364438217702080713046559503063132398059308458238490269957491339223648073598148440597175975730638300513934074890836087655977040714019271277959415890565763525053396079880116145901623407494387659054170342552782792801012910905448329713048610608567745813901655924713956980424906386086048325406627522925087883290081931769987172892806121655725379257753680802350613099370245678100805454163963164583114895902600373435736389660727623954163701736921110926348038664513653832377701225616068859006100618531111750565730072368560730467991796638552123914457744288914767335091651120870401603737339721651700600646223869779265842613452930158318970524018693575324244021220715368273932770078045206752401838168523889409165653187415324019634705911470884162535731562974789212537869366441086421048865059713900824423234958826741796119521385714777335187164013932816363442606635797503428745293988943538541817860258017356726081426266159421966455290443712631150887466741216035163341979933723991374240016213956525628478136869662971828064671847827098430698585537382816971488301611105126856747426190044771536497787827748191319895708156980839096326633097484923658386217562089606797555226807827119854916454976997763991704644650079556334316286864526821903623448187065807328235956766132261661513673400507576080809434744469599270483735168127335758813173963650782835528752155909461582201340035900276087523122313613598075809886106840966717657067275103315968664247670477067699748908645853476198258686123075967903041472372510770141917615298297318296276014618803900588533173905491343425987642412019988917897874933875964504326915606445560597419870098701213507627699562580568028399885109236599314623011902778723809174124298764968043407502498393987564430664905043971049426213276921744077073561402324043200719294828071192180718029637007285610166960137135157182410673219714148543591506282493763432035677593102837789294633493020085598981918802511015173806797614548843249501153175403961704273573590459942278554270699826896507933647998815971432522630940039254605037568, - 46114766254243926415905163412680313592917179240773947008883493687762559362300347078199137714636333402069988915732593832608825241011010283022917045213806820860559124428980739383001406760687082571482311157784507398812471940558455258940186577533885018132415147780016474477399894805216972475238165441789898981340760650657883853663277420273496429674683935779646844378355008373949245046320376219577048659599380634926732491978540093645156892765827122100461505457283222288528809300677083253636749835467525164794363474537787616399121413477834852421652257644078163963542931232900828940434429941526332607829300671442278481178024347304499567526609206027957367670012341509925363517727951236227218427083784286488145807139281972942543389540052084093199490497590856559538128634531383277635353956111345118244023919719139825962073729352253018516378119110222883868169295676005339008328003866387214999950431894988120292114202348658165557570497012885688420795033957708472505011302863436540947827701311894728214225941104040901687076247694486238209318976828586642812952470300176761111521071730985659092542879910432349507616229940060724478449419456753594554175626844397383226015523613617695317100585540338938911600601380155274466875939706097308335031317975812503615430366312534409289408122233786979639685137422554648344094258820297978575886233679969989955671618721454074092660545213052542142761892287190821996850978583348914891483878678550341119919505831243196180501930499162277409708750105443424163112924715002654429232698178099602045170407010916546495421839743106305530375333217410189667299822677222307447602735042719322094311650169465573811831685452748726047067695752498402811252616975858015412196436145760175115534617187914470165831912678572203197057154752601084014199845170651392005932624814991164575680687856403716866265273915340869298540569974025680500674400644346424561510318683231740387341132098280842087713909554780728052377307085518248234548824348655267257903699116357507728973247391364106746202660236183968842677564553821329907502412577201875766606440029545424544473301288974270727938667361982935581492045903487906634359525708655320995854102816671661965437107659843686677639236623374597626942013608572635663246442629399230894553763497768669667114661289206530449986183815907571079452839769219155628900255562231964490741530321801557172297579906722474552716397051164002181315949500830106332621278041176822919104764330038043491088283495103478120069559486917780277735880676579953869502448938663235716785180582493695836550489815078663434590843119458068499588062980511051492330158569276024167509965339479466255837967484237174693693204815048394105367909795163387980239755576694982509900936847167995352182310123678002754633391515463503541300626771926915652317851151210616864836721504915674572097157172571728806220053085919324325981198948096037382244904579175266103800631585293860079785304596931151793870018050808648193415373935602992108991770180345814759880897652331034027603312386736561526105255098428390152508273845718456683388694677451054386539320523845461321149499802998658236687636354077848270408779481446695527826256063514182320828725244013531880715084704101083987639505800740386049135809739561785745325838447990509810987132515324711721357569248767420425599271166631499497956056230754939253409536025899108176679494434456002003421198979100596356994962940049326966457206383311057933779658751635601245878698657188080108533143226670679357857775034613798203827882380783479540057455260649227356087125531971921941641187740284152041372523120430763889874039177893568172146225434262767896917170871704248703806386351416413369862628170364700474050626248792295681281168897310507966788727755590655175961227260356154075639280303624059515003201401681707538014860352462041988729734683643946000793306461400160845222886224312206033737093771455727077568391120074585537198662334059910460605673314637532403809594756233708077896491187321724013079296913032577849377112845418122687846500893991048532105916879650826214392556273190335085264168877764730540415248275480643842833063901188409340707093749851015791868359458375365678605741396481685627809019427147583947109225209332288786220666246004315133340300748559839264482722032814127451659120807602849163945414156525047714813633856325375842421734845316925504509458777468287869529406765586028470354590442901488075353840740391600598833211709393785018410107292426373081733546303265301171279374607644599325057790195019968560796154749982778716696774217780079754943479194310089656541137688775812633105183308441621962398559217809554184370659936710727587331354079576867728223287220889824822114037927029233407981913654917438885381335372538578753964604031304213351238721813430810613486826227477297570089479385658671506679746844658911592912487564061783752940297691958320978624163271844885194776023212505632934846254273025218258894186470395892463392938899611933891926742320501355010865019584060122055658081833297788958679107071930197934719818560758424007189097935758012248572069573121688160776073181107996324706328336664890352953915054288846266582366185233822508006851199622369837320542990677879265287438379700988019864613791571188143877722798107994200776390455665135292912397626351991763826873950209911378405839295303145959389051687214480307992407035880933852587705575432058262688543256353407251392264345491773394248627509699726431262137034302570023548068225173182738697725712029311520444106023925744822746976253474855832593865623669417450072161970190508248845814920808894793819429807670808821680692187762009126022940559892604936535143698439342552777413827011694757639879481429703078354661369635735863721902128213020673869332211531723354734216425695540855950747020649025490355266036551091307594418488140078814911132177748320764289962703254889383769876760001897101613587595790308359068932482335987908123187001951688773197976560700976771339739309918913104946847473617300692727633855133152180528649961660592599085621417529454143549376016188245251187529285373203905378784075596616145913239771262313244942651756846978595028786899764547491691688061534750305809862112000764033181640878591444332664325522260821629252341300339826100113061177224389476392667364264028775108431005137844015080302865276954940940483471083930450368147323913240758784999102671890635538147269573832738471243658045463835400068635903037452016490304800276193238127145373676181718098704474259126081980112436663791845276775844852593735064820755245065320513830862596780351480624614661439623231994928348498429074462445248970752, - 2134681723796854339344392961124693054561922835135599698103489648318825885611243334001880484417313983751168171573676883048178704540368430473299007111911594172122232437478698165508534694618793916242750962806929755857715521796943813796827863843949700855953877578831010448598691383558961952527442866413279174991541205597397317819178362034024237427054282990385146968550170734444748520526530090853801932207151331214641563498869936151185839010268547543842696219778458819029555493072603368631806285774822452511568002304455382751493050034340633626137853542075858143449281229245490508406838030343281653604772571861368234629007613524565477874812709949504757512433423025643877556748779491687859024989320640950876034277592163644504208479736826583480883691704551997414274328681076898159404796096101663375228823182227373872949241274956473164546860124277931439686014721263081041231448315722635191438740066426480481740834807320932470383534036986468957469725207528097737657304497799126451973299280013598228198814193989452862662589320331920990980741713315278585821007288452239149031093002072832386227481116159555936471149844203292098532240601745034527528086059803459342493412185543459282950777483422637541444744162039755493348746844600552446682512982342200203045604158256415301559754471684519364252546629542763511562645985331920345221642457691315431892368494031962580765603908336626699992835139482568650096620729026228325523587955113500727253355072727061155450378726637342334620920680551546094904465374871852800630347291427598200391238673829449740059889769987036718445377312918951423779818472799607632969418636625582513322187277619079567214457458854178516353228527478942207790480930155007362743955225014475733693811967214229071007011623441567383409779059374238751458603146433344705903417872531426881865051903630390228576809225863374678386402796510576346399236945252930963397650964862051610866280187592476642246530080576497029407421534139545386528964272471540070558615868382289165223405747204381323439266963893925596068203836778179472310272101253569038298426873718116155450048866576445026982322329935130772356189622011445520012987492703010192430191162612242172981939387912998419926448420380936551108755765977143257610520548973488793877126496239422649649720511173346757848208639845891867301657517838229328927790712362434026779960080681326330853809685276469475481038052788695902943582879971131467930253301363082149035869832730948054718663119013181595690920125279714837055631790175102737513333425187928760959431237833385782457850705156588364593510266435164509130798657548743290004014053814332029103710533330264205395888310381148164203420094014148994474822250755138545019058928457979554967590893751675305904249263194970670834319056642296018833979438428901183518032679364921864810480595129307760219802293153104700751369575753821190542345453191372664550342792017872264133037014291688806009242630662122362675225797221813881405382605057719523415954413792447102208381926791934381931344629562485609477940993925159052487176166252013215610432033144831156969095246204349235410066934980911839550576923666442501463538446403277597725101308702879271427311739947019387582298707012076701994485743947331492154846248701691363931279348739931695860035728442910708500099964701828024782789187884494340013638274624755431428373825769003371227056567281753992893914956694414123597404160869069136637285146771103082352773760568149301160726235854763367369985296763852915828933363013535644817445025134751752900305686217585636417214696298157874214493635751051956318394655942186723459725009767457902893765789933866643842696887912201789328157839756502516583327669029432007995337963098541691219648544820983629701766652862540447276129059846955731162873444707335258633021927007238518462523309978351076886245382589291617824560118984503434628259773913110024566990444314980251090469936538115853994225401691909730101127751956594969547536106884898533918446217029206366388512812260762767973920447605186162891593880106361927662176270241111911480616871175008028223983205028734380378521656194648868611061346321475479735878538418475108402580634311741129502634085571831288745089198840984571348367076266464050903433089971607878615413918954539693182204302071577425516356235395705757868795520962324712275340068526721404592922913304693445945205418425993050113716276397009528174672709336962546066609132348239346365144337473159404292353899557367207407052132961902785292959456511313543252627060205475629198398098698193710038350429174713925307728440903148327770076741371229060477677088866543501849415847339701204908059935353584744722950151345938360511171344593367554304500785238390593175268606099783335731628612568102680681511118233558011891632878753793866356583581582157319626064739390098025139839484171383586030979730708610382564519861398969602471909246902250602560240835169543052771364293577692010656130861831682841977099107054894238423785058218846793513328592936000035232467376043502341619037994672588069051107451660278375795544492353504112019934426250927017236890979594922938237753647169241252445610024479757053985058985585890978980191028346338673962101688666485213979508146172700220327615685628569660123596517367569432672248677784305470882050267827403171029623545191449662677610596963385506376124004139974327028634669507499935667400125101984889028995145167770242087741129032268469340561970432344333960785109627222676589328410318132699110919766888624345243681537150616647269863220531888405007258582565361971696238186798456297399811502217541105438455303157423924972948237070540012826733497613644650071667091327877245204352519840079959863257522739554229079399757894378114303351349640359387509557557922786231764261483808176475046327208366695041826495301316110879874470317933671143172287845751932093807169652727850981980438562412252259494200950318615385758122443996990737533807385786449799263534566298250790534843483290092148891563816203196292953771791653422133295353761010728599258987737428106103715736545729385307017890403132049189733010155708256200143276368312500517748485093186319135667005644365008075282160894402495351469677028901191919695910555851563570644503028859339242753390019039526017974004502741333290688405780487784560690530023883457869849790384437534991903712299523602813888783068737211458099969749437517309858208691675806120852078836567379330024821551342729862703729128230233475812329857143239445761386655981633530034468565736660558337148263844278044067561262733375769756370699558673374924301168842190952331147739136, - 32767685249839017808612916407872379326070527784935816932703461156704470385621033947334141135779779149008773977208891107336684969908514173289783612643585231930973635868649471263406217473026179310393140657194588697602875725832272337179157326394683645793089826808800173407718303921453694182156893717495679073735183094213280072741324218541257393788581901497206672515284990651673600875191649503661887148577617392053649826317177963277819151332649800074767773213924188893187558962644418766628623761881328803124437750848036233246606534787979388192254104291425399293748516716028030468969600216598254695667960416563423848821545664853912076819729253898640960208035449867130083235481254128934554089578065960269115859267658402060467222362165300845786185725881071471685453349800976239501318833095291521470719681623447665882097304289404389202634452475634490542950974419326642904101508837901448340285626084099351278588036000171956163457828878407355397836542757039259111764523167241873410371523801616267911651028661657396891021873060782685529741460846766459364664533200440032170123225179201823906826429866628419798429342678690059228286739665937169476554312365935695630810314318767086001071956130777106482804321038826516596048578166873531908428823671095939575628982691036004495651181348774895845239152751233346021582679408368549539055400422002030692508304700128895675510568662447229296442969073163478420559536685901669176691434016995160053832878000008912884605694174907148473517335820578757581424872926244441556852241828454966068811576614414906569301355329842610156522307273400784087765629228431933331487515161557649268287915886573570398783037371726400413807000534059954737979633636494179389063569560556811610810088451185260446357051507883522517705831838986053600200758878188364295247259102547039461748526494524177569281663430832483322134682855762482610160262507700723033752596475767082750705102784885961796107594281740799660744351120682606090203660148756913377031267499779921809978746355251928643546039458811275326652977884551652652207319011417219715190041051418240617732004183981870119112776877418654946842092142436886418703605498929496558365563052560614130526588434455947481179601338137337511286445224172655672172442045541452647279304753179391606085247948217783966810666121455981811472580835589024817843081089098046877697100579961601522957284418798548956321163793815387950596495673427784807367309683946307494455739205767351462036794474109230834774893879413750169305159250959035001843792094381447523251369147525370843754621369844869357939237335795587384388164442935877732437918007567640823360323889838529403330413237600323284268880021634195193322499305834844059607878751942105445799697778440741100870324217611239201351282221699042454024756482257415516771390834897559275058687456264079657686434815496325042367415427038531862455601004967479601857121469300752938960257407284216802453084469789969374941204082526141983292852153728870561411705302625151457517407150721886984835921540058142259522221379569099872074498001763875175162057094821739994955933012531374885845008864837699091644408853626836830059438900564864977303345566376421248182850890417520247035314762604387873107068583019557614546869946959166032946210692321327010174138407965907912294988666803768541310575886579189724692911933638222640056638750531974761102656995782096905175366179747083690842978540195609567348200666384554216114238561514627858871245869046571484073754010440454296312568053209901441121425713742385162542892437396142354581436470693003805747861280848488387782345220901538178201955259511505348764546960535552988203146964792612123938041231649636054554401075179457617131783666494090480317859965587739398448561399897784491123111730049172674540274105207890179422536042505985843031560857998641054077967441524622628778589902364601846680638785311457572006446186311605512573507580834478921715413359718358075612525099699897503502970277884791574041340609370027241702730591643310011494921987345506155453281541075421740599379950461960725571726935346832956014751152872857216057143808110028992793160865204018642939387811649031458516477087933475012087553675895200606119613285565341658156500413350603324949794995365051163457059938537010939403271605664973101385655724207240810727991570304644202468742473512872249512780078373698277478044347861467596086198311800394029215702316126976521292413247178692379435708072099771012074250182132217867623278116237416569370601913277675749895859414269563978759911366408350898822485719309451254608602612657380069081507369785066013531702850492138468692057124988608123984172827096922936885891368122744711808060196635616712953990213460179109440082406127975715709117050679562698265220563577029234023631822458806103106866970867306047812443069849399854752685487554320395788866373389467846244519680032736502234922857539072143912661543979659158829490839246400003434931629358596325270798064238284663403153992893659793529249862668099973896655214067852254365065676168566493544420676929969344133874076391202118461259786183522458592114212316383594707973863122314479060322518065573239836175979080424038785392459576791322511384338266826749776054730288325042821132524454005587851354521452252783780300025452140989231418461009417647745938247328728107833075886379614570840540544970343010734651399086609734146552970691219881534346447645894746511013221636197107967927071163786684638510571484970827646011611110830080597127184124376959252992441541288578191798332996901954726744858196847742266350236303209609759999940881660526744632882022743196659396555485178415342330898632981493910187799404360576001152420011938547012381434601611980965648881103574430140380695582211451424638889650148874733819181107994152763241982249862700018782532764915336720314581916767296920389190738325211512925579736039389985927588699596429380276916525955987237253312056542750044487793982097680605571618728329229185324442388031973515120534052529437056214436586716665184508274751337586668056323419750656194114333006098758727669586872849242903748200136371892460794504073433644405955220326872676778066651217530027805729084919508535836077333847084301947629627341215867162919701081554570331967143634737803857809210039308074738337093615818570294044680397411063201968717390877399046406193436468071928789975369437364083452375756054800008518709594856699045708489265919981913038051736116653032401091231866346103409860352679681948315546126523041374229320422956433828496325291447784888496277728605571034361892895195136, - 224235577601162617003674397196370717347602546613978965840880027319453223768785809071318729247349419399899835373737674824053123349811729334280582751709856980486209940042856217018843808246173484565348744520981261829283065879223920692228780657831077543233065852844670754844314089681337267240502684804026428215632453049079698200960624048446517789598047536730579271964893593356601588743920157274859495063827860228716680995193808835036187963040537444986904150762532750094648052418251486309100301842318352702861860100229858716176273827164734117753668948260879869439638225054278753153946064989712408523809921935640481845070272957346468919968067104605563333164414400779263941288326759534337195380405369781678459567356226747921372887242304340778239906264107317900072251125243420007299857015483142984816067637136023471352267911492405546821137719002889059195919705955154307718781812662854056360242328914024043719864874604801608551183296655852591020532590320259161542268675158661533157214794433939964971039327762189345468015802554653938612703193894017739886517249023444574210828266716691844621265278073192865557103896178041541858011566678520382188817590783767451179627955178659393538386337214784901710869672260492943661132351406007058797024929615288541248545450743629285430857242330159822217418089350587496933298847129342809849822627158213151384978073033426127515938081671107576114354143401983166789830969386324154274667612905146474903364409333956666096409250438329857163305763734773289757165818845930388306984712474881200937806399205339684629835500872800504722002534680388534908089619152554565739197334964022475292301846168767601850618166385905206724139764912742186264918992946186673874807805557067132078097682125539101599408980357882618357065777378038038125620595026602099726485748354339409240412224704183723654184606962082894467158833679689860038536757178582746655614901008567202715032835860142204090368017127346264510013643432784406716909563351496296327290976955378292807773924258299228854593558768050550610031842359841645240129722341768154000703337093442195688176093528197721475780686754732297976961270133255092662930359346646826497471760643484949369635138434558011120451737883314697347497109379840957843665322185287721323502116993526001065868247361046345182773001685962420984899117572928409717118501495487759847867714071376452068492498205842495632537721260661870840909458388964330743177440547207639732952842014473913300022907808846339434916985332482176360658442483365591759565775572118346720431690521193828573688559816639589108307166845555732174812043459554484698620805453005721888330489841930090582875939912486505008220730480498144948944251788900654989422621414834012337117699076841905853584184784191554548450551529853693084896757511046513350570015649181057857261391116505744463147172868328215914220907326349796225065773601912524018044089054499955889321431925153791295507328710671947843527478512655214038571866804909758358099798121287953227177736734620563845533391298595726434253718835551809607657762917254863075652756315893483041021548166974053325731091575352520925908427644470225526102179539612322042555394605901481868914013482647369709871934123309696974631044554343104619288719774808053349538206977887973325368715292559079683003405509099247174372231940556357747361118042166233170001930133213748731021883410889581343078072411423210205375568688929911513137998709679293664393602252625307007018900233438810737499405588292271210734452089844740551451044346433241287750231406197316258437904974635079936950896287770696684744547834331345544749694160560106711061679081982686574284587023724653258313012951175364721311967522657206790622247244678768691368397492427157526481201139192089350106803063333618447032041970657233461292899306282073454980354582831842654800140252562900844760206489826882422254083106422305536189070272211973271986327501423749142307062013238564539674565966281322572896938231453242320618270844239232028526117397005749347239182993443349850979893669652381726058247815395857559371053741216116048435885088925995740830277848568018614555611271419087748805237113555159996189004359780470650798032107603021276392481026443927222920268551430596115666286637223207746974273854875186534091393108932681360206237672932701284501537710702355675879296161352584876326150034750707427426856761837959922662301043531180044741798769656591328438579143188094538699800323785712497671887316822123210040755041692822943305332662106327623146852713642944789813144771017504763819526424025636801577522429582715391753309994170980337322865657929809766236729285981002769430893286645639968847024798989678355770981368335530904801144721472010345913363925133745351755412829080168700638695769879001091963399863769639833492690095910938359958745518337025899725264500412767992765110764348222751145506920075832045465203162994621076934859022913889792722542193799162168604866758289871064729493727185866568415889616453930403951593246040057604787091905654361270445733171923013137214426592301978928494729622688037875913598907848456887036127410681774762696665285118024817076329786135182300087765632484540941864913841555664440023584191261390382474941520526183141383522350614478684283444198287204801325839025957276012207147383392515738172800273039745780408143410412961781052934265432724356908976581269310853407847652649250352744078689450325263198696665415069896967093392609371376103953804405684840828871072923034197130739267884492188676547897208632118288158993666551839138371242850300659110887918126697070067293698685194573179979360964251456699130281552428245565198342348883765672820325330114099579100803306409224961114349703290772793943366048691307749577652201330647405709363535003766820189136403695102749707875861393250841419957521560742326890190420801686182677554619870844360745805699082838242251473958823957544265432036511248664466836835132032384094071647700189845002352941860163172149066202901113241279915142542612820321452040888679302631951792765683080151336214277535347091539034327106693322009718843625226900103145544414470923476095850485693870223152330416073720747602095750096335144273694433589162443328865771246308249849744777618272356471604384545119726403132736640364311008889165023351390953571992275357207828406282361433225494439796964823332553526178164037569237498974562689865766836702882054129897986375287186166899568728175371411816421653598507376466608772472175535052467939963310071337868759820582491099880841078623806032568148557824, - -1796300364520978202322312174286612536703963087499437319602396918762724411126944445295200938666019346519636352129301719553876645721903849971635016989935557050688464138780198944918775680737167709903824258265760414844368707251834824493519532263581398543929431153418689034135134017742876737253145837247256335549696192384103523466974885120803449937428213593333735543313682540810938766547488846659631444672808233031042776297038160669444353065716088418942261875865765717245159142371604209467814467781750661411766101941699780144904875625547490250431081667889295755588366157537297481910233309572586840070489756806502456137277462429065782940287171275615571628815059660735817627535787046047332181528703723301072744852418816304923146418947879294986470397732993827852052729565251229150292332977441259539472982042343538277413021931093298807668201899357672634704168793274174770630407963139442384633531870208344272106754301544360969419548455237926696553688026835399974364089135053880026784346274955927464403775659836242425995583000218652311005621159328897152714144493545742035245150340890544488109661216170864921476962029886624965865888761675161083701451610474273832563316986246435009739976017864771873057333693298637355037314427645198845169480600256516810088678547800440995977214256367432923950646924301835790625190152279098099205659784932524251632939369504711089073119204276252832742906031337723725630281277183928510063667176671565713188646910572402033360355826100402018021372782211345607365459735119751789612501671501811724250717959063827602219594892917369043836480747614860389231333564558513915312161669810787266583052308454489754566984993594410199736211983424251724485929317287116423713004110553875604787130150750108678194668844910669605723202706818294859546382493443783718782803727043412514729424482811145406376779140104148013354440621972230397441906552172645280713265918987300999959675212664755804012963862334932941694182564496220986872311199823054186165764880109809829777141813552425091931946260786936887939493986932518037612189853632419808643381767052232920700131450127732567021133915946839269178439889151317743232941322646386379530330255098493442747184130895121159882009046452858553546536134533532531145289478772496186605057113385159923567946576446196191120091410302156881087745383637524323569323254728372510164441017661478660320467241434640160921992805198582030983511722467334929615271092049476067071409308922273840285230246224238427102094227132793035199318261008594376606892609066726257819384027933623362215211983200321017330618874144940319906387061781305996976517497309732650809007674349489387604279828257508491691283991647251743229768637640016210075663289659669264366142808459199063803438313136013582147386591178399620428479351379979171053983320899332877872447893000601019447597903942612494403084212335879629515318767972532307969363111307227004579785345356416863080964562162811352731170648666627639579537565552749187245998971658017494133308370506011375249279234375967205107098587229842076838859956273554706874528597349012536315079100813240347641642874095839578419262529643678948244435219595421199566369341116911935460945122995447645017475651723305323300335154250102111225839069783171497363841482039991655543942922626794849960410310553905178272854182761019102705558497620078209671725550533971952428311576384841260783094935636138219511974861822322287490958894184310057797540052816262653718380104476450903614771089715442093964943024537759310449154760475762006125506493317482908179897156676439722966226971235724852310346715989514274914480101669064615395021019216575181090968849027487057586865765375391735215789231021328713430249483228197372820557653112927245186553368580896270102539994322692090925938191769334774756484490575601334480412517520363110959515015791452931662910912671400008190986426273567733737604524982434892112869343840266921387415207534148879442805827884915593555192315576967267389363444313603316932548773807115420324885418373097689736883886417749981284097851048076560050860443116559949826589971375668509635099205707848973885683481752590631298275121267947806206197805039742741085084683783962598525324701908305792896218529809879472313351338864482382270174006420106246812331766663354722597726197437869067085598598820118667212891123678337395776083403357949837251495141293832525748586425755002317953028507489290300756033303108649878545693123679473751235860139496887112903872950010115168244731433279596730961866872088110489438555548297076689121850860706758069302625826394224195103184622937028719347655914446707832299163858175309637383073412188653762165018902704203868558648758378295420252927959686231017796413316104085537708887904894469634838563168544316722212803886327878200656249089443285462453325169257259099732507304420550890610826070538112023786649207168834460298985153649948676856341332286646565039243716558821415782687152156667898185810479646731283890049084272517364535847246630197623781457735899163392937492016285964255616677002961957425787411790771254701794260875071649840520885226192824872052677008370759710133453608696068758445496045706988178583422020053914737612704747509603383339972650508949679489760333474710903442176499111613173077137598646805593177593961113053635052345270738698648469278413860848690303058121281914812744736217137577898157417925421212394854752967006303322188329382572439540647641837461802076041442195966334719084501161835051099590459839546327550478100111463430782747518472169890374308910584275377689245943521284894476872979107178234392730918196294429578269714103884154954399533250167658937895444311371340441585869055909361059952470903594033206761266117678428760401515547829880979312308578616798716108351764084025222111613513787592368296675027774367022937286868911530036581030470941223815355445896330824463345913714270290272379091006636303657647158665321064733649090334369676125751749374596148575787019671937576693044071592630332273479521787904659818354663819650464675572918853558998795596583801565263953679857337427539119961363527261989125076847135498023190928905504089106848023373015197168940165437708936485656069122711642121897822103689825224956185917615759143392660060522244434178923533946419496342263287242377257477882855205851745121567116333920109071092450635569715779454585764151315837457545818541340656509352289569310445979898260873796689260952860087130400733805077077010250871663268147669528294028883646988132041541074026496, - -73965712009223917498610974583635748153406663646615922961492577733580219736032818619378799212658416241576942970828292909619203511260924868934367884151897167268774109052828484349947942101191835270200019187154663172277971549117077592642317949203821265288696989321895707115985601400371635292251084206115789517899740287769861651898279211130361203284404037499463362102677017924641282376092065277111388561219182764059163478837272748829930549126587013294599899310167467445700860677284614544250194237827241791153242991862907650340687911401175777644368714881479342840952046092791029079959508178688126884857646029888450413505623220825822359763321750343485126310042353965054721484540426861135407911769023821326051047286785759690289971986612985644788392524351045266278851538981355770924657749049284198894412520615078486167194377961756749686775617886663280810429673609416769119185140462758929072053712807064817433216376928336696737005526996613407175369654545003916270986721296685896565935917254173046251178321288326554509023485364403335286960739359828964792189405664002004892687405266390952151865364968928145697283825901481982824401558447345117091937498003141728871245887468167638126763597179537319164706101673462987920674974694900006681639842836905848812334934408622363821403975687204304330906643755186616347606218148404979564078420297864352950268644488308127647372084752913841592371892102575565440773151183076093597001280775895776202394050560641345540079003176701126022712156083104269165811915872830785480578359427016771196686812398421501257211214152688303169594048206722526014972413394315642015397188128377058835827463610991024851590057549733936612264624297111249474737532681253561026395489704553046773614344345356045350858569788551650898997579538092243389223564586324057938349603080005228192088517111249680490329682629753895563040213373436910287892661797866164236347895241014834375786463017989682476450919201733563985672470425829468201759653946336054341076832614281738371562294159048567960056251224424828095988490276248318440847285841064726233243516273365814178055786087836693856301187263666813505587480833308566272517346736077608248191390548393045648557812458117375352786730389016208248276787001844111076398614465879436257188744845450168223986364274233062755757831301552844792152740833239821067202063873635192233889204501549550210980910291866212660226326402204628646652214481001424025366395886595065843693632276732372363989931700220319639203751912193339856610373220249986626552347548146147791946459868390495977013484404358224627685121634332377860731185115674496396157052542789188569177113821200714952517637471995629781448933859247919960125133232601969106270688979780155082333188521896444571263362706190324938596383223675254766666694036722849855913028823990997197009243097637211724551265331956341892345619795471579080339572531964970399747940706340371602786621000453685878147719406594847018443470844803478093652205027968836396297221755319958675233867699900555966059221034466677943730457001099177809114319917923261218237175960378934613291900468718518143042911004642928787865689191090619984227308518409670183312404831092105991321333718269872429007400232965870654830447942333754757421909102697939741592924688532235923967513238316520494209309697219796912046055168982707963450837972425644977071443585269681293437897047261651315514781222735444286584101042529739699553503168731410153987533381876112490733096032001739410401933396534318373648774735936028828835366937110597008838080116160215578994379703968199935320496359767804322518321554675897472613936856000917672447547138947071129504765327979603263428316920794648442531123753311304267051066814997108056179922722681733523746302907125172898064918586867561275591980273229845373423953144607954256989492095552163731616683620329410019972263553224803978518976263292987905691349561016983058491316161350508909636986097716535139246418246624824001220068224995858547081565391338599916061557870182273582692195601813686691027815229574413554888984371502098859631353492556728871708826755029099741490741754706040181202330236717151922529659548078816138344342937017487321753430395472841962916173176690790804071846322385515524488882341772639070934897469693199495326289404767914349758283818141230923500572618658039252046334496205671928177469281623089718969562192557599255344914749715149407519941259217181289203433899820372343199381449636050155790381949814458145776934901076342092463346472666822155068141830705458618758282573215440404886069717066697645190854324532749503388881702514847303259918428055976071571211600776788473553843393160430814271474268756582822538355141472353907249202437861878111360599034220215994493621147546814224261822052676265086107673194643115435499206942010663864657101956289672772542093548354399398006819623725030510711083700103454878820667021797756727106124504587860069588863891470033147270222537786134586746479890351286419932649763082990936270824216738834228584849393420529611471618904485483982019994890159568175385931840228412005094177180790377533861956151994484931831135129013940587038921005551743613378252874469659598226901115827572201343330294300186992461204936882877679916415522736253116864876588008972359177991247254890101863356383955052996039636639858409307519706339538816680579238342393446558021613967300529639177299639766334323899722579324570327977880473991651272089751142751617112830666147666632437808042798603623104213322617847125944919668064877832715170119641627122104767721891272370006768553886913508782263427544327305345580636372152351492814443218386184026597732968201750595266814036264089977761891104386571278612012943054150733387921738846992766833956348837477888259275525665406961286694886623122567737304870751607733601020751153248505192559091674558364382902400421342719790501003504959725126352543830197476599842023236864622802659659964242036930735113631958952068995952160318734884580335398087494174553839994609639502349673353743746898592025179421912329866120649921073056685855469337209617805174147673363952829366221440153883640208019960104995319379899469287814711868274281522525893168863262518777644963593947094570377998915761018872712138357447110722117242621849723022654968636353931687426762636436658883812255852986414325299361243482709929658024063735128246088062845511603490689556249511520201477659341669934963366608082917051224857751074018802001555964164626422749495839349735948288, - -1064581117131941618416276092165899579772475861741198461944639571533884173468809953535661294724469896534568243525445375791219684819806345914292211471129861886395194547708986674129945038092596152782907785884963781610748257331282050056968407403743269394698957093380938446557026985414582639704099191946869148919650228626927176429154206837155084976279254334806536532016263699603673358906440916003804398295393875403183096664643279474988933983944791423201589313282450679082248294465428331969617853612726849687033726348635171517198544631085780394602328503438674493613076579202594287119751456293390460481328449095993044244014133696636045906315661677116559027330240125139807403255657514501884571838474170092788005802080845530495415643748286854884222196193421070789964862508840799493786232073968338621962099692496924172536906254695614969339679105507718919122697038677323333601465763227793297569217382805518157839515208569389108566512057902712626280041781970324588300898712945435529357030208075799039318614199837980960113470727182386955634327546794302160201519981231632461138069457908660714060182545637679950343076083756119489829889285238678225689023324113123169852170131660126800935294738240445792132434043050894482800654301173445438967575390036028670523043459062170337480166461357787885788118796262196649964383972607969451664422367107871868034449894675007901976417229790349866584763398344855444846063857930748674144458355343014206428526166897923260838675654398613444769669026610609891537902735709989549482920636572412445973367588397133297216615794241286572026874803363822280431665956048133009569040937895896038670215148955745588293580051703092386026253657239168830718275497072442870220939814925190629639244949712317080700209545969094258828868868951413893428113783931226718162630830281394415693071526205921984873173885286030330981354848810456043501324978823042012570882401200521445054884673176617539240998132071328667849015030081609358917334724199233007017857705795621320215537962141487641540020282978186151500338455632055955915889500837893167890771725660793531302664811076863179621222679622844519008968568971505530409224428026194839051671006723390185118644310003781042968508470539213092900147439761317615672757809652208351310673140052796119728425234763327577680969215325469193522771748797807899749661528865196777413996857918279285824030395211895386656129755317487671430386282636868129650514404836729521541940738961504863068000933277299832686056563478783608581049820079073566220092988330729243473819108553077583242387144613664545621924611542005794990503205572894920397911930547637295415214677227008973667578483589787453352791163483302764240184863791889260333936425219240736559550263373269981631298661674662930181188378844484913883402949536073818749433615331796073879793858714508879200027838515278220643260312296563056494786669507457254015362780860918885531830784780957905380743290970953501349695981858553528698803365045584483664836311647618162960657864476069006298536023746320691687513847445830685620271783001900504857551633211994096505603378757555346440695515166152059729751913759532610797681403385743744702131510478037714589435963170238683592656143028224539760953468763736077976335031202254323178704217022677845047675013118954309287028933070002512829106764420562896875905932480831581220552134565040767420618949990305412412716246495944284960902154391045943718242582334675612483296731766635118432508571408079477776642098011469140007207399607442818502782945432690059939479170224545949339624778088414200379540119318271146470629783229708328451050642820428834368533069466154969364590458946649628327853830464276795089680786641425294780966755125283524834230209157254135257736845153184630254145522366431909348765281126761448800127764315225121152009486704301928876336207585766935450644367795259643331008186729368151351738360442451583905678547108253688075095016307431936742033772023506793069217321678550124634642717678284123311436604233364561625870115693369751018805306439600231250733935936848662286497015862251225020216605998856294738490098894780915554779944745733796908767069903703352878071794336792304092143927657357025365746823851455324644368047091646895023520383926063137081055177704753142268687205477608055564040304704991491829041715261601960557719485432260620502752864500617441269618043820661642874753510225334199790339838849902422528472797037877932175619485689111291214111832266765610121403623089133403675966384656942710503940675530178115292501314729899262785219689585558086945744259593919741111153081423413569000104740562198172833130900751371241864270383398343050340998124297606714182726229488871005954142832468680580085586016047226881301474891851412790875537027596621856520057942993941115539159615689827688082401777859938204469781076982327713956202433459392730839606868370107953317068179672212103814707822817305953819140729966877091595590722074865921682847068748732412544742594448113110304015586050636267656350645173846299508072776932623516221541791008701147324758292841021451126806462247162412384932315803633870662229855239525359221899533109017324886330198383866887709853277255009224117796161180711797860905012999489925048161605938243141308604026910227444505152234421899864987674704543423001132316290043864290890008033957403496520152220784001441069290968000814396592406110549127064714952812670968344617533776903823213990959770158323868144115592812253753506695611442996506468908222681716370676821988088720844693774226326736959181876953966673585525623903173318081936875094549324983021375753852697886249299023391873972018691524571342915353904173372810802612330456469601339707997102478242907500706915796701199580342882216264468686341311914754789124291935775430889070456086059474716169552309387766507526861925074014202562064869154297552754679166145490586201765320579330012603523473963495784488153244994116440027423718284409355229697697566065590489739451182845431106026315035689866950974807769990400509128262617879852392802385174937283558728089246290900201032590957845981208550402595325689789803874707098048667389408769739206390939850380116293757283961741023661516897521327714381406345726324393011907817240571870944309074627761292753029996087227912337261395639575748604029296226662192611681374013399347583967736488789388920304615587656175660145861788909695560622400301700485463186775064060536767746891638626679594387591135232, - -7213144717075651424202445608190543921001124527807523471566347870851159272551512679980075673431602099018794729616780631608751507642626208075680724045213141863674884184579376916088631301758825227738264164667840735061452555823982590352451473098008265061943523772052241889120927762181122247923784595363001386324102799650299934869210796282436799537770937111592769747233430651300934336456013754294759425666934742476518542231543990934380161529497552844963679231803015453818098505068314658938334394340140033373622746533372706173765413595781269828279487591557835246488757209963532783396609262886088179164034795524315404553985531155994304666409593423902394565388769726321714218156202069840485376833055759000648878125016521352913395421074198541515470128105654038044473849036815695803963364730295745331614163452371239127955296925989739795341709119338424528428491809892311768451234493124986582358120933615941638040363233170183706790133300736843734002484404299674279057251780902451081616952706330054578173486765771283408441213016698134999428532361299027716276782025641510614671618547349376240563197082754059365204382426278096649939148420120431522628116073827812636140660997618744908973044209273391559239192844091400647421409724072501458799389496607671427984289399773921075312384727634578788694850783209989828026321493723819939994689101550538750447248576396730584195258604422566293176582531666909950841723877435118796397945306292955296605543747732065875954340912514121413777911171960953638262995595482964161099842497989553999417970070727531557997354908046149120883894292557537671210732380693193410905693524044930673796698646923629919582407326769461352854279028701377973276342169046435047371525621223283793644014536455958553593640856614606763405414335862465106904300031219123862819456341229231846285226223497573351779449695900083687161061784467956777266504971380451147575509191540612902439915765324963576559254490582891614005029289474498478537319374815398913507892374230891802041814926396679183834247378958324384873292210035920760754026851200037284343941629599522235075451914963598159693191302738979176089921877602127319656887692349706041911630061414184203563175694530637207800534726060381883734191963012910549055351082993750227845449332013656533289149804677072037530366418340830918525689124074184820196800632868345844218053356013451201080140053020922005552511653415308290007414749674213168895725457906468161954379759361986809385069661739653692984259297302700843920785924649040598003671452558442222191016572340986005537937670585991588979070978305376437756630148493945163068365877834675853381336114797136726604440994753640221646790805241570878534189345940084141834137312261288407395293139967850154108324131871384991057178208806695132091139720203564555066834256230860329155526738193397247408441710802283049814029419376083702600664023495684615914079687878490753067683018338452019091003327996064612995200991561312593310084573602580807530188397383576830440041965836481158058441166135386117480190355030185658054269122820903590916809187110953686903548072533898907122430111264007814252237398897979574205529670596978948069327255715602400527513860445410154464108537580528798372803645219607536984565842264207270641760652622718964741631577179244163630491416345752706655947378182541962438230262640250454740705015199621209280977281671424994895042750855274484821388037584288221251410840577684989532747723369646109960976341501241052126979461887293932393386480271862582569149025345324115788218611944259419763428288599974573782620175569535753821700395167960216542098401061894328439253998310227463863185017394342284192118675268578041739615422941146853162682185102306903179872982716409016210724296703058969377743448783955149921482625395850223705246239372503604978771767318355887193618699665183435257140821162875899424581459593616435026873310051898439818151607165590601195528882681892231522126139854564703742187310949703952032674030493447520643786845094996411222322563845495750899622694019831614032875189258640456574627705027131781743524920216950346368310935193477484447461354183755417388809009913122687815981145278511329707477694173294560168913307749215235275313327100744487769903979471438164441857150683425956703012092201725749822868516016230581958687378655042814026709317836558251731427355397156796002873458092299249801302455917881524168133719670887266370650880352083535152756233088381585147228414386871191321830133589392911023869891733195129718368783714198010221101247373930597997875355552192835761824917935721431549758575721181343197287592921287264136639651304776347837059298783380594270648643948625984647825646456072324216989738173396764139538672084583218869108986914109041955444183166822415656516642994439597706518640094825587441485964267382772211638395550245333486700192138270511289722073221574347824203048204098925741744978320825460111062251609299573638164526099517634114354134049371017982749611382720198211606034232821192861832906809858573711101363921795161548748132897934108533064951176618560556363306376753633720380296649541310243688133777528976920591534623683866515188077777374910055207035025673282010081770018486849551737572981420888485231803582196463550617992192398180131462210776947222682787882806077006410126873841275026176848685027425878445896106838788634860017553218969710816484378402474228797018380455627338390303284025502348559637547077616054085381005478952718741532529225956344394665183092245751748418362216576329310359545791520355047495545077420899859694615159602629821187746639105747530060310609138479099279779605727482402298798404278379395161760202121668349669589006605115431152357122349235949619803207031281378219619593087051667013242992991832616474381861986817546463545545521946062089116869425740981555601576365790041574201803840072430035840545289579743024239457914435462023301133196119776344732717278956752473989117240136814343333321192413429188894274884859916404422745353075099774622927587522790042047555063650095397504342545427320802554779869897870331033269728235219600714941025046673614053417210990210453847670849616993913477807684500519311749993551672984195208800056002273910597109123622988162570065467700787549325347718501723530944067897250237621784274270566099172359139826748904758567008501681970535581003713274334249084918798199837264964036665332590746006259256559397241546843619328, - 40251174223615853277717250460280256871699936748541726493430106664769237161553123754327097149996920296341814079045356116303701829486806375768064817003922362060659425318970236718432388344587173592709450425577726508791436974889584703381413195760179009046801057319348115057172982013778818782270693467792696702762557744433605681118357268182109436183521658867802018313227870201228901587892936335453252940853187301404570661134400675026317655497941541223300793131402966165551956831739763687814866185333977502634364196657826157729352042180371235577951056518260482112121529811364358234796443048363641062861152879529222551541627344834175875987418291347517048381298751159545623372379420668089567686924321111142930338881110024885252701037132396136870610283016869644619398211506373776015908439036201225178524765669320517476278081245994195773881379044376255968039956102783241055484181427357410113104231589044847636051725145142714521872148462418371072739414981051769927547885599417522261579377258580268285868857334074669939757646013858013474625250898614129586076656559524299074204118347227761563041808679243019518720285175658869310885033973043461350723476513462837329447266276904539224417018626964295103404575256381596264279154937213500135237717269874820846577890820273656637854108919940436450999719979545779621007904935488372359825526190771524868032675129686420294955181404627150442771190704983196354520918589567794126015770524394317010397741405789418998267135313467531428622826270199200359222222502945567570600563063820815984131473903444238922125407336330965460622826604271612887011267254566149467511375496431721616313209051352577858177317779615699738332750945007723696004489556826768083728844362497086472239127421959292635735704554026069479265535999933410612689907738514303373147729683380404682519459732308885690840022279836099402842814181030893981998430235747632826169135234906734715834936651506695328883199973625661356285917891582769224930861452433644084269249890219989698043856080748490144076783993483294288676195180860934496365760578517192654250644150979289018243375931564052757058498782820670567599004597189265182491850069166117521141788417587289501800285788900119528280591675047429103034556797044689828920293509955237901508123966866367712585301970610005132893720532988209765271531609910319440949457592113731620430518413803380948142253502148778761107179682765610940345326048831905617281993703957949220654469283366950311957326598993968456007760809938147606826875997272786056809359764776253314003705907056394725695184374233784276778373959369971896116237491230672732129402768074442119353859846846761838039017437025774297811673257941169469804641457810747190440250165900580807831639786990114021871975481743370877667219042416534503699647635411993778725246008602137142323329066562855617453516609743364413356980457075424349094590861099070058160981805171986265025235149440719906872463785844323494067992215739266074209004861835415813332968046458537152561288167097657645487678464843744067766586714258753701436679949317184738088736131665743443920786863212450794578490690497402503727564532981403638063073351777735699655449535571065905681263020062832534716076709721699941845855334332777563443963609659884641101923851953589670435385938549949314969266659019108834683141822450380425748528419207047941211701995637537549685023979306084208038902046341477736772317122682158343553612756282276758360095174454245433475552500905009352258175251569841446526984654204892311968561922949624805278396468322949332687530054134248866230548144721446624456899410742683902859218184270297192362009326415406942822913703696482217763603906326407608771912927208004218457034551290645872859324947825586075606944737468013736645424465468829232763196682031367711877083921801389148209168565389863384281559644942320918957785221306242938506940208969996385609066067172459265190653339136249792491460119122395475530188359715212197997426202190814678168166123318348467223152619101884423638685597128033888097401879514813827517947000639894852233877712909732946048274566826718898141046056979991014121061244515890361604619986041823195460826067963206831016622063921688213418435459884764416811827356307453927468985133489863660019515757310186023609626248346431948539629278297309889909127084299695619087425140615001421138261782285156114708389706888025830486481675132789313381199333120364085432286505994113030301976587506346890220253183038766419282950791713832426847955178253055825689155785323726930117170264172732348346489362092288007468247426622243421161958477830680152175776641776751714411096365178356834111029089073645026174084219631237202280999179261533145323969945219229953795149868509649086454549727264398096350971996921149207734438596728551441001753244399393081961410432267769257297899748207149721009495658468033620422045445507438912996114655239599468225036303940773679923691395456544568262162967685225371777760603688105177200354367801827867820302718900944529600926669421938358137084610190928200852157019778099545671583639483152664696030250873386392768988341947923041502248397960648137151040748688024167879007920167664109320867413246304068039323226582437865431475145744653641551735940891404516027095081291758732744521544468737699597992408199620291008589328612326470025912064697756849143175214527061719838728741395971460476822335494453237536904434502456630700356538848937722526709558631296757366754167830070073191862236035474548435674959695455081077176155976256570835165755788883651403294482515024501243934576017356972003102223410545375379339355809997910542569228454521182998692494724857395839907021108487517815789025900902891424639903747758525304740727534687886627049882221297309205880274908380683369955958397434727025343746436278546106048486631975356739387823992627908937604945963998840310537216515231374082593574585213286097092677913424133181411789087604661392915871793122138704586410786623126735750950491048221832693690801753353813499969763132880092528433437633920445811440696530578492146910913578290038181022289250541665105208302782905831782764387839593604213895625453840697554773599494046949129898575124240979470228694604766364760874383242237535516277339505885507866096532587942306685402677299164055982095885827040760311879898620671855377241397665291828808404162810010845340347953399875186188144750517611921408, - 1834407648201116029463132500940758352366638976445762306508330327609942452536518359222990668432050404343317763769544950231485732950531920133835004676260939130951596103835347038063774570124271688299408328714871208664103134676513033024042765967624238407738232946072699122665770078551984164959808398946038202628779584898348679066943316396509734405327362607833543863634858322933587704511143719036346096605753201529703163035642781872300591557215871726902468784664791076065130332501647705212063470618356690801934094529486403013134179166058890787971625814555306558645768188988163611341137042961303359356878659938620542381120480783981880243334509912304932748411474801940751331267141544306738153445694294673521117983385581271520334172331927231404885080973190878421091129575933849549259692089546836670081298625109459741866046630958711663709852881173983710528974669126459553754385589974499888728847188564555278889176958364768236033436898841377964629625331893128042426327368643583116617501971641179275385187276556798007262447442293048389818883208813501603521743893392542904988694775139743789638888780080610262383404765053108218503280830174143155079400577385979072279271196996842022708314711804904621861112851010260894233010250236218015176712006427489203704794075011803168114439832385167092508277963166081272248926734509965224819534307608165565986534936001833732817497343216771320843449406462136669638454443111115199621834943238509402784161410867697585146540883177802265109806732972644482574044653648178476615004233109301657966945567616629188657277937042839257760122758440884066703426191656495951592211568155856206738619044397933409573825384663508497834128260664358357688658214669381744028427072193759542902884002900017268470498823262444809300099165077840369931076273688001651587990999543997445279116554098255706772716297930510515409451963103232199600601307551640280206958372970609274527332922385098874800682016198703642180067190761167154600058057775701841369932513662107383234725562218468057119480167609019559603277336292872550762160512025782498705822830172854706261702090972933011168286988753207175558285393238250677361715942172261137980564956704436249871788451137843836211527893983716466037629106177089123412056072811143814671348990848070117565683510398676859515471007336184207539128367124051485065179647037408175877517904265200418308871309442507415387116564700719662272113713050573570928288450591157538770252038154429721418018352948384002699484753193527528270673299699884696008476568351470295826735960193173704358129933082263595285764849493497168630242353781693138783940195093735707051774463982654337273965183794183434673323634409150492451828482596307686389792229011075426162035997468231818661719842067487609758773905243975426942292305117004250153596440473681953883361311869968197311117615224337435462188765530813177079794656218994532412897148564566492673397454356614629404067724867527764978264126653663596827715049455092349706922883377978293723450182207301107915830076963661364842639389260501610445581369282536144617993617189945061141597012032484415666745181688909128128485408109252650172274674856434236343786367858729481564419417243202319417030144131632193544076394837977262048001124203853746837731044026725108871798897577103788473194128066638766143961385025997596311488185357243627132722406355442900847590237167678824177494478965081669455876855162711407553936549766214156735831262261990290450358628161240868486490771939976338365693140254345285648830356226130004858197123016203770608456957982090048072862774434244012652319827662018046685032853473750943614466944274924744042279074225059784562003875256029205257763231036064457059783835765643464979560382384746102690264266592162045021024307998036114687452630377538798306808656761059085536062951806885604262003509909293212719562734054968697694240725308015183458964841082993343073500725626014486621792397598947611439406460486919511635348729128437411473252866507267153839050072829618720635444597276443425113887177434515640479345656135785118298614515473955612016954926690715680760581135587785379903681389879619364636577625833693572785647330844313127841925004628147209427469678000462242473426996400887036670374087963498124487447446034354874206065127783846159412001158498098970843179617817866551992690493523324408940163744675325668604103129937507424042055582410205915157680535589513483643984255489560580459531570234393542311362584520733111914927060454050246706464153491363064952464292494879542139152215147851328364155911642241764504197178431105169775410763874445684358032482065334220481083921367222589048473079149931736708080495077295090258522291411821181898414884443680876944590766407691130944965072556511901167281519443123273301584575406753958843892129844957733731771780312683837220632779734239325511000548685595265589867148533277950250798956041615933125643029294443050703422476848234633987738141850095251387586455223917745643006218308368350794218585270035146652116824335167909442433290580698908073999561361689421450930724353965481694761948630117052201251986487503304046081753390072462354247740659159077738785046738035328733335915722458769159726239121785923778227513587036540858676429104145530124686578438045616648752846660203824227312823937902831090939483096619383356864939202097010177567327910011464073729297716948210177004117962951247390668441257007634361323173301476779587577839017344211869589535362485294409722719549320647404796340881460229817820281900271002205041365690122507900693058162159450793846648796015927000884080221630406615422203075496288123111654451133207894424725714398657624396094577719619931006550434470034572308376627517111200148368792317909868216742845443180826361146954797384635230684142948588841980345606366283457134782097678214523174042228932992162588785640650169387663735339662793889279641583270958802389333870689929992693274850826629677946164946836590208111786518750273120513511906051565310999369508770511044498973446325683125179265462920738081594608404977507419109253251090101468748309342858575461346720027721040041928276978864577559990012454129536318137362967679319477516538327466124351845502248836091126544790336866444294835202209340525646072266332831476649997822270003084087045723304483958921503658417592849756917693783133358015222984888540000887258203815936, - 26348883460483635951646982082715237529433073942529913315906024393828134616814028012590848334870660454063767086653693315954455420216386381941837132724706067789410737106042165256914958114491725583810180685679275623500351740659517948209301614467927100478793078569338155441350781125918440939696284023829228333661500006157910049652952277085501834172423628527358629460697834679623471665228432233009382478115818903005269881494401291015811727779716768443261608825878365891322600347863918475352305322513102695855260695960952641890831643762428767495013931100855154275764190869418639200842619764337435307588053294415827730270778988995035389568791902301679889087224681571273784467839976514888341390628956442305169768373412198253342888109101963487825381514623678874700265877785924466663036821612778248854039634094641588750198860622697150836460243422436569443699513756660000308138673265533220545616964433313969787687510436259072925137350684110433089791523274922834032013838913589090294783689812139864144165099553643203531176238339618281487360299481530923011432416742465043118084019206977849564425373392967126209454105824509690344037191720254351409315457387247939956473175517414915888582582204240106257846177699233323946052104893510995212677800997373148715697386737168662119188590807628674645216918370006491097379504532761192601582603253473920951494440421911101017483413569871779129752293391151233479926383989283838326578440995064308057696857155300738330144117551736933641944651518291800920112373256392703706093516442606493072423545971157423134969725338557541612903749287145387201496728949820977965578145083007289347724074621169958379289449501519810597478088474295928848201772047161087715522943268585027743464610342363107311782858404846445222618520641942237042239782400379511904058171329853886981235334450034839810792658742281958843034651100767399991315210966586898768730629231951751603387590623316065966582331921298946665311584691739410580776617946364648613313209809308481071833116213020071661142060674671866226963371624076293155891103204299711272747643913680781366324150786377333203220864373964267710625610763211911201663186913012609162110226402327384311947393981723487272328460728670824046456724252675792488653212061125227070192983395840992136401000800001914230745449983484041424944444203092686426983322252955424423676922900476605414605719061397493090734615517989468199492668865853353993001396847198262484640700103189516476822500651393360213631252335684121806933381722236405946534745507102446363733633564227940939286706652433736324297837973143760333802053973386719896030953180763835808182716974442547865177784941571084217348921173582798111181153923815908806003951460766327614745810698291036442251949341856420876730392044597879198061939942332466402882689689618406771700022590957436581686808492134671591666682307358836683872170426750542696534657313061713627109596491466972546303907714220702697219112772880945139628128162437934629141483128864213608839935322335297302217409206757944463903874874110093942221569857584376624105405867488260354152790642983085361313376382938627078090903623770154257934188485899459323819614172534008422660453043089445522041410995543907724371986720173871453049316773135588073827921464507064316498553617710933625165459356307197643443321859366751253086763537778544815501065253008329401906193078916893485732379507306434073964958303334364634441939550274483824978443852725400763859215187445173507253309924904191552147309070776561405480345580786307392675223203517575099406484462228507093134668345169660353078023662616612061949702022089454362019672512681115536986714444024955413368595001514090395176748204911085818614114195620317269254601136476670529641889846000887908351915309328464004039021242996330331608515982222431054503885258572051241357655341349768671027261872833162515461613433330353289406701329677836928673219491655630959247985343308986311963910137357330425371758020280130764015574618566189887942521509734974675907713654428969780045028930311268858427748901582277999214401419519562265601144145966853560560709092354204900299894629670177334413011277519485793148660670060743399866258232017477549298665394359662726746440298030358030793929263883251568344138280205448915267827376207774415061445752971037010344540037019324556550279346891183460068849993198007019409895077796675533379926354677660598075142414621136447882329668861508700555035854548290952106425698553277795915780469845294489465317785772284942617831359255378854581219583756562197310820840114949288224032486865254611877604414459956987829608180208859748082937678646702232920070313032961031936969403577933949441631845808140148737131974721092241088997848702174267956211935053375295764793488143529072960226476668037173680821378194761928080441477834090499350468959160323675687517077305023233011742918388581553149723763035959813903915540354192569730096887601491677062725328415828262004953390384748475164316059286110726812498389845273718629696890240442477741661784627675925244164104464687772801575095696913445622151167041585444984194138976436667802928546133813590617116712295187907996574808284640609579602325853975514411757963868583575664370724183051542167929085683423413625190416359796006111405515711827197819004162763785511380349705984449341882316496599148966044722445813615123690270340039198102761529205092872154008323666416608159448775788445880180942784900089660705287865779612047883906908475920525937026295246472119857222088795790825350294016273583153263320278237113584260829868820772857058804817581539254235565446732114818966774919570581236286915150934894543493628949126073443504435398604471016387856277926091800753397250307278384562405017352161804012768369086448876539904140958573894058739431994052150322309047536138199426316520741163056446740386000300672409258267294898897334599170491599586020532334180092171206605661574249340241580501124799167685420811626045939255979497769124177945389961293341028217411980739229828831567272465101062197161993453470277518122789009110902603579570179492533017799205247512555694491061910096982670239547658716666598396059751417088327585324208519091286990391203160690432161547136647595211419775022601851521231723247494292286077183903184123716909906883104608283684635392633770542923319655785241247744, - 195276048088306376413439930924288711641588660724786995660298504302580346753687103175341258227367498950183289289366339222981368299048906306136356269307432138154042385815218474279931827723037646772087204244816537961967999732705204927887029194988473160250950210029153480197754226166220355083111856678482405947902844461510436250956792821317040404633620554590604565880465117477378393541711652345351517481909706222399722506289358823040725471221832234636035157227264303228482326906355280919539785656890856330743834201757134180983604657103895610833136392787895628532364353779468315981829147012871371053932616351385695474829253286902703700491486343110821171573730472928604640165760985989738771271096533539102815165087249338973025266837741445645475611451168883749548085021337326610898441954174828343232524671878527868271779985388946361873304978677240422361154191791906820140849783099943239670454722020382832338927606639916789459779451862225066001990644187062319098451887216647906083299106510993988143392675890757115233671391444722530588356607949818040656877744369153082539633411186630826938315981436839116385829501060821808449630521134580296651415304875535269326570207477573900477707004016161128966909108895304931192397727973552731202172050098143454625901530687910406676196490501733665137721706182778268716418669500327203525092525511705334903673113201064657899231416054025761100930114008164143161545783980120208276017601581458211619857100220655262345734004386671778031366253512151284942512326512935249979695285623976419016674887225537422043497991246889561971211528152837984174618719595787159398120733237323337260228392146770711779879340312145152837223420380238455808907527097774225558613377916662980690910613815389396312228415990885495776953223792580092599483393812338143503505081424543196434839774317447391085670197533247513711479600850644457647252052445415669873986155223552273111443966578691016791213356032826290594134398625022901763705484698873315873894296346137448880351057579786174129937897952494649093099741966940131793555212742519759981581691052546468531930533404167545731616313585570324501563239148021278313553250580799128223509864764928997759302379604953875959772173108952216847927735514518499751014616492121019347068466652022114565998136466015049436038326237840183485996810558436060786690415259532403062829261399339663985150474117962685408915825539274826243385299505111980133059908617502441429329786643916787194379432760584240167411964504950133338605971746527217248597550920282122270712171657227745330974831035342540239878775276574857974133597500240523893711860632892269073233031040319628827804941440448553496503658376837892988530919624562052048909794955557094330034000023090288156254308267653323768894361060545675135597078053892960366887039915787995956589163424826832425333985667318081840265372409714537943012840312718792125300939405875130952080166279566061607065199665434719352361767037321557458896592734427170686365214004368542472354545842283643653179041834110319933587807895556826358011283940414882592863784527085180022274383928475004605242649819832624486362729805625325559259932198144410950828603514691449556509449939897643929595181646244098478585290560755382585589868464743804847654107455972792737662595217568532256718783449977355282414213307048670318449410985230897910701952114695096431304667006322743065088186490456182807449437945079165636901596404669884585987286333594249823227864879697534315734637929825031815254444354811609665251632218359093141804060401474319560194649680467319535769841478042474199112184666755850769569741512412188838531383179795587212045000810272916641996887075443357972454207717745519212630777291722896721915616596794039796640050725275490922078578182949995679943490045910101680255891418321444306646282995156662167540635574267335858831138908404249444395583800077650987113560835398495192645477022037072300723912131033808510408683424924841151682044369485205312669874153405403357592467392287247913928568167715178103137963744457753174786413130095437393741594584514951472283706299194916649131475554797055155226097105452111456695317516229573415126203589703335353635131913245133292517997671054637903070848169999142146565625096019558910122820383461510072166288020190248559304441188305348980203848487216475038102470735856759074539884997986617579928651180777867790018178738060154180717651316842904969107702139089760494470555673493040722604628149446437646778165731191351032708309116497647406796148828246129707000373426155998898841164052180805836726999716539702033689304435247932198368321541332069348247353857563690456898086693368202013220677722314733216580267093229467233700333203340714369602128109105687849741683299193266657130700759914598395911142029811259279247887813787344247910076592127149561270737359201918947269458662820573812786584475325889302037179833460508761747569547527825696140147743752767660560967748647617556143911300259586881481107144402900781408323080912070261152542629244916056572205659764346713269389468360475965345090417273987248245971634325828649728260271482883409461565930934789294436349154614697829592963049204905478545321122560216043930607255573292584411087159802827080966292254033287040967178613951319035108066498365472813165479846327029040204653765868282842629825657704205120449303078174362223498087022024916773555562056257833122579313964980059191234347252685290774835685748463862046022259775506505420356202582004566518772925773275984156723858059464006364986286436963008262562484860639929068270648084592788154639426152261104836408859769887628878447658665403961635080996319959893131345887156793682197235374857511850342955874565763217295989765707747748911305114804765085347999721906577811218953013443842953250636338167949771167311613125693176723377126009508456289144655534134034292144543332872122260723089204665071045358556870207021388655195629479112445161437467640881720441660642338302624397202747985686037184881079910783387035166624372612641604192215120523827984954056527452472062598803107811308756268170578424098449268833203954274813671356966128904356046885137519275473746920639994647839415851816141329357476853229288570011028497976118844773226276750825373319322463216120505692862494045662879066510434091352327058358272, - -290170076517466834606986333143366641165737706978103547944361599268802567809181052602665530414760850521454747631325601165564495982275031589498490700080448976621695705354869878488123479362319135388215700766829917630356615794909345088135258940974170106762573375626689785607866838763761629208697341901031001374745139596091632174602035652993048687710759114377888640402500448686903854247045105717963048303777131408610915444086066194517960067670662705977747919346681994569684859911674878712226038951161346354028016661053641896274032338013863804866250931771226370825736626557902474772023691288504179976422931776073612587263559343761531294930976397663591601680206200832908886644449643321896040539122577307711286505647585563844456922784660462114163738208277335429597666323961559071773518148805825732215001445775347621704676301090050291194747351285393785968938838504543429538992890992182582165378222581653905062498958167836923682762907510446720160076080370719912168464600126541454362878255920867397674077830833122860885471258424762487170623190107442664222048510660318893382552399292776058889271005606523655612184531579848432135140673220709510048988795030436916738460023296767116127428309094214533971545176607265889106136473480974551829945812708274561830677388487176290976455812564916650471694089291889746422276949192982546886961081634214644275291064962342608718157511333125968159242937132730821652812867078691989098093038251163810866262099093083670075803405632135042880551220165278062838413941266558528442917893216479294167501437438886260559683306664042049781863400768958363985137638054093155521396583926788770397068979089253417601263270034426559092207638360060521983816538138625161226389688507117425066029083735616943794290199887998939448402364163974746549384736218864394117315622288741398704859849870844795117708138546687133652166566786786155184210503963458308861471310567074969408935586544492141363324968431368225620027493962318720303348120418357439711677423829131964873284127634178166012955242935069480491773588863412749303368959511724975308903329301457874627546376430141960427598305599079530276494991853430358154926608095820901931431942043597402187389242570296762519717898819159607200780791554544904883560305795000422841565501267388909401934764393659023033286372984610927474047890369095520886243268773822936257772230632034353693810971280445766612482957364368809953735947668991124059439858176112282474307527974040598115924615266273693026870668678259497417936347779007385222742362568518997603238416127825791494583727510470402759770178278983516919648874907436296901168788293538178523377946693816612456247038003938147223896318714787234110453890349619902851260414699060401957660796628683865373832404440053784956362575318956213482596796397601664061249112291160328873387576210970991027327587639230425978155712956837036856193946909296792086263157117273319761406995846776802654601547874057484045051827274036986174113836829652380539030574544309674248902265622425033213710311361501883827530789196576154154430523917517286387112819672458906990050886348108368797525691147631112735126858930304647895868989685304582590605539939540679158282731051893956137555840246783548680106185380969520032304769438102913465827732772032009020962071615312652036773236925295065095901255637447410209761772723810433343885992628363707691993190874320159018669313309230011465175795252797036993462780370591181480288925384501012413432712663656011466778043395099115089845213632806312610939005552380457476716375589898083512580706044452531790929803946159503683295706963747050752240551030517049139277176499341349038791331322568953841072006993835212216057264299915401339787542123688389610323578053378896635179479351564725626082803964827666935040674510685232116418139270169814484809142090959239203770226818546562159680916790268946090111417155482951549746829772582946880352000587511688964334948264378727401303953770051335116640735007045742767010808352235158272420697416872168399641577022025292663432218357455931225696747600357800518518815845851923934731648620163941005810080486385552726271814468070292558602254048755365855522238553751189856169872053736040345826315100486290514430096081113446299930947860858324843836929562262261297465268741845168240552316325134517575406648051643741359433095609095648012296618168288938377389973404444288926458952755520297854327628490767269942190486410187491618064179824918925114601771389230596774234905706968998969850784087330052096314173070869863065298782455085276539351104621517756595929700414993768271897931155835567930582273381478366393331633711913148424385961864521862086077771795784147594538859416941630842108229560267119035535529535330134465319321893538415117760016129442147373744152576172802917300832316140632487322984152104954424754471082002548791766688494577462287814009673044865022705112351404919676205043532307505035538195838784100273000808188175229958913053248438224213979184365547994433422020358327531252486881151269723498621717323917227795675819356698960109161198472008607585905524447726053493598165337082320556996698345966035631376523944434013872400840117834785079401728117410551816406789731676158240131992412046735641219950769547938912198627567016731512020926613313098798695946069442323452152330943518797329441811047161991067626495116572817708240525306167114067510298955693762758776685163245255343421757023789194983626148692340196381711750762574796534005206158664719983965240909994489290749778381402722865873396508444561661468962238494171753132258066868494551264136210341672208740146652666754615010080333934453451151090890370188614907677741424669761260713889277252287320783709091123443964653959956837153465041955944464818868558213771669780833785897296748277562320380891855134081561901807722745306752324927120159394801281087826686321658604971567998022213719258387639126265021041079947671505174133476373797244926957497897254225837422282378920015671304425298280633176921939585716647001466514458165834442513775054960332032890398713426267163876231344684622442431797702746990573634929775232906533104502393155870683134238431738126482993651828913126271096151504614159783066090189768324888909667496340878482509096637458143594235852139739775510773760, - -31001659289629871671355892285121459889764263834266251710936483293514578137961874286340372524653322381959521563963568028832165331744406414429817761589436736500017829325297765260381493694280901158685267520125055981720463310118665661471980636685041129420261543263815270000122051985223299567336312431761755789804030254900553864700975672753934264351436079230523600208775054785525038490749968716322708938279312295849106443474194790066559972856052546389221450281577821024228517111135727524752376219365670937185058848688760478798857596214693856791288123814437245959464669429547231337110891929766324361198511035259639456891969761422700672621457540994723090838198198393300440746736565742513296276034511424785464633153387310594735247964048259794159624547241710436432166192943342206313326188926273657883350081147531710062299643524751947833611659523438384851616844709259091886196531420911655574302837725616596061344065773631942804453034555623219061818323636136027927360187273340693501178914269941057255529169088045094851260686338592380624857422878148475113948202478766015002380474962958394865922104265683373089027409541724670423289549171121399578148674974653230716301277498904364933316409724331002985724663531849773083353298269406989725572110977032094690277820228223141937385169397972831915587738239648928319547656131708636559993261911280075087363600918939847900364354891827064680177775277762925576394753097887507534353663800560459852514162693695814985558340575946019498601809235139310385718594123238296152489262732394230109696663651302849041871190098117245462928017769241806301948501001123583524031401254998545894141614413320992339054466275482825746247494784596446659096394998855079851843305950283875562192942944415701014592604249432621192609057828269332082149171603292534611052555521800824328292834908377179057769102079915252922884134139869455119761162215465873850830283832435348419961737173097699374974127115706442786682985998376105765282883157674659480457630759884963520567990020427540388957183842504121005157158898911157409053013419187951778688565883245892691501148953714255917349966082714310651176863920953465819963168389955646990621660778056316544171132181525690735319980231293757077632239564443055963784509873568671715925672436039478971685997294521996955704340731073403365257030686194486830702002756231496188129676024887070083696675949100480498191697696246173796653343952006334671905160648677466432133920186749467755047738246708456596446564740379596591657894104714083311027697773579380869015609162010942298919507193808783116701365511929782286196487041964398600496857728938205118450142074510936365277835412720789064396903207961259220265578479235342022639210415549776353020055052359913712794422868431724149944020240528582303333212774109585005719682931253527880890082434709368845467251971234484660877168972149647988658030772805701257919833007792847626829470251903214971277161275683311452353809231102984062127172697455914768178086421899893044391183307553626721950889906169129027459309060672982584140959312859760896333902814868553785341564724276249577838564110603655200997605791962625292356966069597772820259917972019171715595532438007527896519935081221568802712335301709137227794542002157938902559949840743752111966086221613641049599813876597189803676629073621597024659119588986224458484987129191419865163237245054782498499261441272800364283937091605068058359036780808997344197931780129891321571282028270759195676240417404902778478726244785818035566389633136847353457288207160253956536048700313211964077383067597979888760681604205780932661554919838258092738693128279025103833755387103283990627124803184673662079515189829667303407096525538393524327338528740763415097724207345603775984565615444163265397619113186975486688904763344440998314424321625291298065828009273150066800880460044859484180453801594428474995709605275391728639703536473717707054244460163148321265339628575003040860372959973776267860350752916133056020246404663604376256609456606939392220720244253298312886879204182345707141425680418544552542376689086721583397390294686741715249710359064285304899659196138044096675505503082656314648629007246957917161791955292666012630043733294705222833335870240629279150288693079233686104380401298310764712461344686085937365840156656960133915962872181418058565139459116614556931674447357111357372840228984471155653456403394181753254524109668554148539972071320698903683559919377694795701258577669564304174197826924644222475449286555576036022374979537851590827649033116843708336889152513796959061594461558304154847913347393579988209207529337873663617777863713340230491299714862009224375167991572515844770325408009785088285577715917100472923754155639281145772645637133129740926483183579277780736235205631064222444921212481634347302709494129109626797893907080555382042936883589185015839990589672372715168286225524812543885106662900011319360231045784321542702319272143007769667173789391704407489458691568208321491724391295253354810078496825347151403099739020989685438541377695242833659060026357286558225616197595556134309551200653584862445823403146850753021680089680132766615048740043676275629210044078243032540709599945764294312691112257244300500484277419365877353000043796985227654076946404838512600029103403241300218264028934142055396812606817062208876482142938071249228081024458692578898254944272221629560946457161906320506838561958656785018534035324800231043054807371167163672790781801652436731218032995017692740473234097327182172068293789869795901461416079910325125272581858869897438732969472644415923554552017573645111800514955090970350473043085343821198340249093653253154714529263646771008388209153078550533128791753173718435580573276912427331025045680740100697020262364918232500555261771351562620796682405967122641370046171526618069842804820586083602347808699841738828039480111038296313992419250627461913710250612193495077083976261674977343084989068374751875082024491622539495975744966168125745172184288257803542043347518284913698644945858476393054474547108683862735540133670456036691276348525229455114356667380821376547807210033991983743216421959182529113511784894615460239680721924396268050154891936628880703488, - -483493684099585702768730989050961821351143174878509986305594088808362251056456835306211077232635065707036722279086485050313768898577226738240027414817440483688242050436496286295788188004615126857337317804469660125216088213450291891953023775151947962833617579051015508620146030011128222299319220970412238068709173557928960160257477614440148214186571676371945049995984749465867446228760986809554435949314464212712581604834268561089329987552627943105814626139656990259383619173492144275030623289598723554571274864554536365389423476250261858452437913401245692343219085078011277375075682292996569550180762667468667332320994664850233102138621925036763664120917939989417064391485865529832144650153699966564072571038605218131855201160934299079626515313929990391123115073699743288213853668967104773862925592934501129056856911868868571079369683191064305309172602411954907147358752453555699701040766250609736965852272171868161638325585045322810754048756007734028228380685895588879167741976281159059335467484797955009606145899404769597138181846521187921648704441882841565043520606110098218592656704445610795274441417332666780714933977794519142390751111852885861059650815079553620847396415351827349311860086592306578380374348899177776976280216123766746088429972992311748950017633041807288908883318245946976044415056890087538763638381584203869030831429024851004982032073623130189036570626170407876689331234334019111965999551827862982401772668490581537021640586401467404871239016500971452589674156481517833836071516938402772714252877835900249439258584997829942080103729250823648612459628496353132803580389248616144352690828938383895814672911720895116238331534596621192609977829379948288046898681552964019258059913058118713444363159778062207272242214289968834057240187676751268072267785538352359606029676476092567611765734550864892047717515946310639179105576344179136604144681731156127602768170063093044247982527094319392766113626929641947415892249863086922863958501519325646653255769127330834637252652359954719071113802396004749266740448770447068516129108667694188096080853510751278972568640795750201327204919520282665568535879118307504673128878646809265359374970704172032974443269556891818624693123733376915316156643425513614916122935432835932190039666723776630090771763265930586348211002200297289663398546729365854950267146316263561045890720023691454447550515949065033394237785864504373832254128015765668456768132850246811952558005223128027111272170250465745178106866736563168955192115278150662966431888515988008087380484684588443840721467825120895213128430017664729379942933464256999551122474957630126912930637729290557771981280583468759286358249084098359772875828361044083881604061758971941846852288148854952261110837497782537134117564291386522700227228824826015910940050407401291643404749186298574649470902607966539473827979519029903252899642702506498741105158846584849507470218889300988266690365491694712996114070176219404594849103152770080622299518661896360153679249084932762426142312016597900121207843250966330951524826766854926717483647199430661252918038071120054546665072201668064493169401932200130473474537948347105790362982181196676888077687013170478571349483168076429709812138667400938669746390487112433251104142410210068532067758203433229073715617750463223399718032635486060531145472896210731942949950284430977441378204380285354533239270144899237573023817874485171694883867323401006245066053280147601564542317720169649919188432569813604223663941003311690477885785092320477663251176433560457542365997408126457708651799248715074520924116968761896959660727564516759315100097574594400714516991032626229132930440275000711194409271861971562746236950362323072586153402053330676008215161745790699449461092744504228196853102902451648601770831141574716848693837798718946801662046123531794539242910331499348055356541347330992077940370584897117511690500664565104563074044395566118399631479193816055890057385674658212735353404947399391273620472476904545796395445589137659535966327215403463453735615699125982917677157339331627211976867489495846900179506057970867725267595821942125895008486962568426949795517073944994461204404644926105931437943192806004718173661227915895263804990264972825306439786703918160702077847894173765777206000873573590736896792535548668567662307523698841750777756950235254723386808942604008171585812535036042712200930212929764027915296991988292397656291813037419267820186075879201901128847832042504664640573406889922045255328098360511418356908273936393715958275847551259754117371770788245896207332126049679906506933988076076951107522047365612161968747188107653166447193983631794942386692871572831514637550004132105651809433538108853074365425923871408196487845647805357052774169641330170047537723460690372996131662559382455027346726040283202536746669762734309922375654296307645845364531687105292477471898013731471029493842679479398572351863386635853690495368496237994074014116108704698947748956128766618386908939631491700168230400769015258841027969776784682684257000079043306950098941181874602160163252159733285089884475132107785857773243839188071147352298153935855932908659621536508233834074601014107942814299000298506496570269327920517174404657170326505031318215323041437816517435689339764961824773737384372298992253672520117844321433828597455372673432072028473077446913778323147528478137663914795436117700037542498465575555306017172434854112710990579368145814071660126016419911880382109332416161758302763374584279002173410487061364319835419061580210879671419389624187468112356687091565425843033814275807085402697917341074092200608378515077446628840281726341325329359486304360658415013042345463512879912214366871782713504779737659671398925175081992853881063908089987160798256384482035434946658468382440873856077622434329523012231595188224750998920776221069391865952857525769415630809612278465180841697757543484670240110951351600475748311543834021049749403377880376881761233768522194115692024478930873858038231747824416370939789623802999915290675351063906725613927176063814371348704138983332821454439075317725910888729236123370060166928119068862250484309158783818399744, - -4186238115331821031756289353047975204575656014642699796731518279234528636879451473612341407357505681000702728137187521119601512801801964486343584659411702776489928726052239639822883753515187182001005475237637758127235233135943552228270438518033777403632333149524527757335617097842668222786965191171400993277240073396852575303449378559806275711564532488146032252329096780498356935932780559490368226500160465133585173125500075196541228628098311698586239378694140418453188524079990075482367696867097886448984519583095222941251987880000924527612123650142353627531164326056352411762729654785901392659120333500391034786565838767992270077023237640424477425467996163621219968538708966999854980095147465963972618006622442605997577460518107137395565204796395648901373880810713059252500267133823674370054761488138456105199322064037156547885430658377235048885024200253179731249069694393404125981093261046009153097592918115909880028619411502558217624993662825529071310558239321245859337398993250371407899767384399431849265677536893236049068168866384481319678971364330786034278079460472030802715640360464806594034988540828603803056999756658646841034419645139583817392351132078151738827705178199092805875786562973791877620217172979722669893454666779437868886883964655697163990290711765610026645545573483068931119579360459883371381474538664485209852482927249749098717409052478840821779434421956098701040930995912835315007832217628175959623991323941826398422078358310340704151541752168951270928389308397452029937330378402489560775664320880666754578215304631653951477986364027549367691544008074081234788419768685160293429922028884483654697662102519098661677780289993297432245854122296351826103635467621378863227091751233145262244986258321956574478975652343985246942027683046224135569799965157089586998481066963617113739426510758073882963631292670182260768713411840131038691376227735062494677727690803748342916496848572803348907759225256667574187444282171294034895750550689590693403283975103324911994650804114408236365836834044841667483665853684891852616190024452925514499084568464548771960973236418554157647659031400589744750653158090911687083780405182556216326316042991570677445364574475507890654396946036190285701392964856725392512827513226827015107550020517855153436031223235883423807438996836594876167018867376524227841324021552444195286273143781643301240937782114200818372511532931894348510053451443723817667341167500690125817411592468452201049219884733148899111185885282576162068149066471922722137423877193369030133525430995369508850695831248648637630821060633101621219151261800910508199694086566182785636626688923294302673330217722054971821532247276516673504468772792877117687986058804341941124169950598291123981380314977960910750826806166638678446723637128585893244458546350440989291886401679140024203356465429097593625729120798339503198765834319072517493681901946991059765279894574411778260283028128976646803224344488635596946312025449357457460987928029052348798454672990580255794249785901386631701785608370439892857386573461925977107991776513335780197585602116987420751146865449536311975244324814329074029640426766309618301476775704420123479783117670632212669259566169932398824297276209415123662035555597613007974475093043918728319010414424948631485241984988388574332376979599071257476439994345395409460716523234464280863915118811923197277645456242296058901198545539263365927877136258622365902530474280576136599812519209186124739620792490760953342489390895164437976136291221093887667402665370386388092804576495975829152497002919762700737657820411843629372167270158752294038462815620416334421478074681015561410007571758502722757255821930522066115370886791189232701350358203403906314377284851974229163204630974681399454697407475080697084182747939489593252674574920213021151201617754581099537748933964977836957207049616399264205887218656552431444957548623375050582144523821718709392010251199758937807292711459558608943655364715986481176335049149632368938993184626350556618360639771742844896318394820440882412881320686352715141848001068790767021241509498123824688146584631191783502352779638487462586093488747377079524386149139480878226296779457771468307545738694297070571176756106845440571344729436563166119442468768499225114786365473868547115875498072912677896259648017217365924931081509075021388851310582774620297744834356337726550485837746289995496214867763485040417536861391974059533312392883427395086465426630109546924657017763911236269552614730809084512175418521992400566578551976257694277572465909392894786185141114771227728286970873079714472668294108067576251547008255517514403735046910031552898731587240174116769910838683165247421671617430839814894940881619738145716452574358472164002541043553386121788254093113809734789030346708078364237835312705796581955843382760189774358522717082235733095066061778976133736374810880231271588773113461567658867075297802781750306791849569055681400711485954219643839893462297192843947557691916810717851200147349582943292618260178188841617999474620536887703385329870334516293676078171211047627736431031628436148467548926745537000894447115918411964135129749684136640254810103533416930997813992055627009239606410975985072227146550513357289811053285911386172800109305340140655290645080359990736872407608648885145456153660228658026126272092504878937601974030091160306173807932425993923982609495451335392017564883714250241987656332288729821372352465845607700250271600458974065855721236569986215866074676071543072863165354534303434318235399960072876379362528663213665115050052195939901009409286015548103386047427437958505824581026355190259436548172789513937934492060974035030144841493646956865732797315908472520913682338103328181204807909695753506357101485179821068297686389494202771791770678461493455467027437796416033781418006090728432102011222408483309622488522844787314165340986369857043143405535470888485593311733509451961860210160352713758407752896482251213124340639066288787436178595752675060688506185577394320327534019610645675401333314906965968632982380898920993864616070789106257201619253705101429951239131462893568, - -10989734543992791289644595198779112472632111065467987735304672143248238910651283665714756343067406227225105553585651551116289830508214187701381714088114255504678588602991728627932643018305617062668726947406863638350765526172951042930310968458165077866799213540748467244073912330442556781884173481156364444181113835759289386193701347508850727874264077485072124566969956206019377811464915726165894073508961900587641937048900648133386250474822780027782064464057270981873124994724913136337441702221676453913562119738463701925016866388249764032419837790062090275922283533429973979472681804511042990714080530393598790865527909885221387991257073740477424998925674087053091828930732423579838698982956030955291968949095432205982057848716719562893481279203321848343754383820392229742304307085944195926237708771696868620257012534334346697797959042015798409666143264078149815018752001492172608375138484399896876452035955041582582856832651719849267593242019167392884262616367057010590824751070266366546553462241262715152352915807299435425837226490468040197540675029405854814364595450967675046155020988596061402085442886424446762351068213522206906380589680924213897653708212275817455232255011311957282544787715200618357236575915074084542710021780281307749960055381026950617027226472114729513563785750580247373500952992356817247537902140426142745891545345121413220572090267129543852670298492939508372041344063635706518799309873505116390029674774332776761503315836096565509691991372517957915693745998970986904410701807467981259055642328254818057948506227399934150083162941098637859973934999646475498225387865587960375345745508157096305259152692822178459297284170630013796323378529202165678248342319923941144221805952891476649754190922837360848979532840663779959700647544205893608764231071041302333143751685806009384183149178614832853821371758935835295245610515974569436434233595489008645095849959149714983436722487044548622342895482303048625784614647959630992249906645205411058165807924291623404054560535552135549599474169484469487545017131834928377537825384438559678664699738771157820567533192939620320809700209831687895360128036243531168382871260052622075539772785326952224001030699367027739670859238423519592087205882571443084925911276904619440333125136348814868634359154104792109125754913862833937418790798147914480687674913202422353069135546011495897074227995419247973617365204838222512296199005347493884533021295460837481215757483829000889918974551975931860978940841641469042131327572608697125592893105807078106757123599876798771463564793105938726731710371494824489941544502803517799362668213675817155780987993202389570824349217675766483309035696855278247731780556177018120085568142665543033335764232431323824859387573906623389463352392468844016075571650661811764418061921489641386373856758923138280145396601169165398208709587662762956449517440999906086539296972043434600194686438981814636108204102339319019123677149990623739276555808954363564473921381221858250768140958421479119270100688862938608140896912390232323622083612520592532891371770933003459951374176081386876834252021279526010008054671266357626614934562261045227585147459472556467441228435604438416805935712765666750604095058923699070764805791204059218402593647472088112235923262338128896994168989697953062512053649931529506411497365337260444421475215978864015726022826397752178253144973689685798178014128468031407148492745109332596330451356051876690875102412667185322776013134643429005697034373368443417860438570553901894439604163553240966414840669144692883353577728653355716906499543198563441542534216323092481567244084311579939558638368866491132864682645671789820939275420049336668942602878349695788940762927506261218815075621721644074974749067626110612360817677968523677290923147032503081991003006695148823486054095221657140522278572566977049907990158054356952480197630577064091742571299439764700265993796229518508594257732214516757040024982260283709883337979529839316631241279578820849700990271932876435872085037619678811966616166979786430607045223022742880066359984883637659078896879048309024562735046579321523265810398221533835033981744164163067580465794310266007139096417354047901012305225225404930051410738295230527805461413479976979533606373893868366858169119222852589678528064474017751741882165397877659824062150542688676581457292170656065761673353963314765742194807894426581227457769448992995411450711079973547919192359960782480916660705224034428457803539348057443863301231257023069357779856503024799289220546211956565584032177954679446657409931483772298314881620314790462865774026390976172807814822359733235691322264387471734090201151237198307858641720594410026142768082451501082440847830136142146605480669490485881652885735025022019409286894087140962272844672988473729212573190961170946517215639183514670648611820687122516166882076181058847673627489595095857001238999689328879704423360406809633280191966566512307342672870363742870320779989766814415921922580653323194966587768417463004088312545796660734978273125552030775492169585906757690213054489580909618268914263770765275515451549706053745727829161940417181616495281842346359548912877479010109973096853276511805560694782690445194203903962067039659045032659665115494963693545180441475335159151422048293546854805239734160241918578557302032761415371223513928836546873971497625817059664640245228396492327679981904772569801981753035256058513033307219495652218626136117388754766912080725450923896966324775661010761317191281806859029268636845550167809431705042801044028343040795730970646784065488022302463407903475707656396670271680716331638301076991192886290110604036390348800968252948464492168625921584001072456850423095322271755290005130947523114283333505321302321003310095131339479983901515289091313700857127675548565084406082015272921913715670229128268176557290760332399495470670382742635344565990195422956852914649629923211662948916115221463907566936551505005749135428978024826961609612779955062141318407163933990031533287912077085102399875855247105115120387767183258163565537548345694795637274108231680, - 303255701245484374190354586451226256015129647265796446238644216179179151901556580205283084006656959559641431799645716901490913841731881166403889418716550504282207752811696539592263344422416746298656321281454487112604736509434508221554165368007510526238288698475467896976076859068664317268169338437422316017937046026901922507234451896633993025034846832273793000985548073216551110259204011845999956731548383773077056459289273266527836891335336836498557833076929486869642057017244281755037706431088467616471058308958540407425311800849172647704281816851851585748101855147261518239247469056988847298332967456928128967454913524294584016686594303194938792420470024770527205951681109852660699685098226534192806019264033096455934075393824726323807618053356182996858331587006799448645800662959851950963281147219074103191994260875547862356878519979453980651101569856898100997171220855502459751351521907680033973842220130661857475325467412028239027817025026720410060327034706605760003770996230195730900332331132550265349272451857219099022374971080723551380644714058221403806568300664550535255876454916078493892139952158050970459812798556608248442056656720377269046086221240980393346463282489653982933065219732870746728943771408401910859710948264563129546083905861464571298572749353814884746850499285574871235481233846971544099265299664113820009374465025314558770321973997905053223070145007903986305403861334227204894323930758188906745895626438945660713515727580771348424999135432507964724242276829120388858997180431597500922597806679960633463366875713368128086595344536787738874476509507478527859129665795030318368082133132928003837940467020244461302851254371354953325355913654842268305826370340234845927909751659685518367146350699819996991156710108429466830460349470498258299741331583417945142740895502320292503812834529073282053113842056711332900129534997430534519452784219885766651263589637623026282345000843548657829692226700648020930466993272686396975912191519696545839818145535581722646183019680826363654561632837491120076420502556763419324197104399539682229893264641834000688467321652546112788191777313182894536724253935578069682549317983366793617674590158732479365715087024064122048967630584190941746368403322172915210180401408140440668868629744084542662638667741697522212836467894676399677799682188184175948778262068396915464324815872372137203802876627628086594719262664917855303517644280719763946582903043063078598922821838744136708765735118678890243436514922125458567620067439756779959547026346632479769602338817356664910741068689971909640796332541358990531282882313520194944765536265991925517480413648082280142195270573088708718044947419059891547092705115359776552042063446452495683331214687516909741109654628750120844053178326218487684960635758961912574575296149055103357062147990879998334149930263900520348629584378357101400872410531337590956151006720564693936604339961923039252697099062207297590582756379510259781832036712982344490794358306376184227529133321728768426947027021675430234093427049544608264855757200321968376965087274396504694484504967396223374765188754118911538285034750431490719517572771454880537143043803185159984641394790376639678962303820696168462903864413165932897621110862243120415506228324701762676549233673578720026333638730816389052114112881349570762562826549527942593058017186972957640709691022993397115501316631030874834119192862562541926677817651894906994573994228162420114416593687726578484104500657578735313113315409566543782078097077636384939960742603520249156656674236714038301983286499588944787620636547911336478492549333987370570939942802185873237738158367232736894676781031545411893021798755749004698636539164628369179813908616605146014566481620811447114482589230286118056333721855434836915887506788827059133420157189230777087660770198871465501009386026242918904089357369118493939774604247522563449554552716081188466522384548141805093992459941375146744432807290292376499668920233623758373017734854606175994955913838260854931716100814937373167750008336437915177467843915906445439772249248960598226480355022670969262026258691595147513087231074949444518975096059722037189365913719697520067409118528830157628275704967030345923714234380530968138754396736756367454466264913179734760278991416972075443601534603868183872477609949967815670806337304373973107180747901727721738861865397404873182478197718975725272272853691599718422356612176847988936009529813124526985543721784608678773182264257561748187731963450739083597485874133786952583282667140479281900632023329412391499016174775204084684678321087004305563241025359722570682821360318686620261065335110095764988926456095473681685750723493633247753980376212783129356057446852871235510540536911669455737839142527268009859772023443620665582811360824917253266108035477134223697140761254045139393785639842344006921217343671531257849199721368143864648864194560656937180651328535984715155436363746625992605044563810621929994533368131778413712523119941910937436676044814641661152390743054204253475859730021732533343487409582627190412985846249137478268257750859513061050216079457703629425141728810038049119792837720448046530468663280429385147565320373395826196010049981724974238192490475016029913861572250677306077934665801589216102762689723763308430127809322502428272979625186359184681995195465876832672227966693307377599480936207158140370398513522794385923818034233504233989996941614479004161785493087348371055395139245464547065140589574897411681623994961630380277026687321118487330952834254592292291461349946604622438896536740570817618786945871171371358806547592840078811205205149148201151416485989870944455745964326738949782956715401553998355271037158570130654400360079308190442111559192644058519049069146476404060110438443644037070012514164888144189597372337193727333282656820969789141245337627972213560027271204638160568509198052663609053886259089502936847781790123028047480712287487264604255249512477019413711881304910488495584199126766835404009914093085729761495621220164115001397299066471646003151759007861964800, - 6090063186643759814399908114878745216661102425077614707094337329223809231043099346995303774406773856027283348249366213117772633197346558440838772581741543237603812620317263783608498513461303026154212569723720175780207133851039770142975525170837904542108785593143784645357542112106286370895124873498087623498441865276608265023694748418292855492975721532526274927526930289725081692068648626622325153425820430718864373278490046387813461433424647287352345249333196003062337221206095518051407096579815364350029350043649112175329513251534856890830343310819343956997186208104850371733857481117309560517691667511208722616855178842393135166269245838323306727578358889454284927479940298470881439750881749978747714912907408326800601913348629243595756423612438809917029014567712630142141361210032406679067167149882027630455844815364188653123830038970165881301023827662565140100321659764861214901234930179954403975677977303015727055156186726264088277818060849585696576325983910796778262133173588535822411949823189437220194649826224346866643430686117855002925944821304464900186595551737791354155254847721737202331166913561949757572085261421701507819533424671026999423202515981998051508126312038996008604857197540099200366896488134746170238096700927814717639235644496586823179063107658570928283220524436279504670056935633665152958142244868242042376639425755050860113307116082982444580479436324589706757777191738097805372918969150369220084057866669151444852358106770413988080148949441708424917016767947170405701033222612548239888462198656208355649527307481475608508046216225490913718017730107304728580955562337240526340048570691576919464549289547632910920163848576979843412615194564181514730595676365162143359194133785483656733911011288698362554934346012791833009918932495041105591255760140671510900179516224673675154212748640212100871904025886694308297780010184600264413397190172443756753655959259766444916173707913142814951164717372311117116190551150855226624462644599893741095232661052805907168290077243059797913947668190502331338485811828802119315162444867077108267235122130064720772048442057839592835438514443230191205197089904532491021423430347198735666222460157679347649762388675068126766888311615220048425409698844933483350672065424874026235972533991787780333112321989106544080384210168185497496621196319308536210956425625066571132253112762348474648414313766449578207270634384765868364139725747759214794707031449523919955662289397814390685921211848697829606915325476587878664453530951187064100698336507472697312385272282742147076628157656803825585673194731992135218882963086785337925885641340033119243263642415529060405038159048317856684820139984725968387216192536541229512929811687799399909391430835184527071008421909257793075918502597901524785893378443051376628330241173493408997643323848563481877493130383651210962015513213647000510743804584756789672618917491264854140134381710181379040375459858185066867869478195485681917039001697571322010196869461985257653427514392744972946755183298956039123449241993658690189777942556378645389444679991442224638540603963129464496927038927044633563398322518997424165890519529640831429041108867529924788433168875450147500825104629989434076023155412076442448573193394504550520139305758025571705395035288498092710325399101572470078856982423343183373753366806684052768847366614172281979412839715444753457626337766495875787889705627039412314606145368537970036933267081622306421886195052962790488163169149984203362741564627317316199635613680647839387727329082221215282755378135061297938386965304119227274998039328647420209241837787744139749224684758233585802707644248411346839029516347194766090505753544487293639316743739031397917757979612539789826013065399509570103247888888857325203609230568357490229088500012302815169172070903843120712387523761290194983417883135879499882340916700817866247656478292007216190618400964424378631702628769916341103538053017451319751866776743213573144391282762194002184382579526801719960164410021846049006917553006397443212413547710893859653242763096185742548197476936109463329687173429906689966989637804806817612229093221278145039502923367619642496771883051993041076216360582800583764332249223524667456171704508204945295493319498495103939243714273746035494278120982000035628986368594346946478363829236127515622596924633746465699039064623894373292334718076466990821562866158804141666022177908067621217891279157215196282927156236826258067995206819846753462452770730438173342794093630060415814012351746376290211543148192775491379434379936552729692676052227759365370785984284124862312124730860387207467177146574396770327390712192141680447584685242732396881224737271016720093496546315086058771769225787313657506412295907779604122980246382400649621984411961605400009914091387315805171060262806164247818679129386604637667918040312550680303298978968107754165369750778098487419790587021727696803132433440625244746234841927356077934766875094060662383819320229181455825055338020400734477537793060808672193083030243079194943835015992768783179832266305243278879668387575381497417988207086117695009722955543839148402172158204887653401422771187656056421471955597115807560436571371676373982087530428554935036506506709107843747824565257572760682599542332167716615244824568510762144566797122005778094162637964035039036274093212279239536425694628015755648343094949702505024678048970659425373941196757558291982381257193774716998537105630938768132090055538909294533105192811457980791015590962156679958362071390327380014940756786264626794916409734500921820140266045388626721315547640903505696535967544725077034999742740697954350821615626079563121849900742416370789953087413999475553134432463398957208362492153228580623413630380193266926648574920727906629577158111555877362100632042274168832643071634455533644266455345385560295689823054671146819474668725264216718315592856291605207847794176454658646138390076907954669787868431962518726529358828712216841031806213084068789057157811237971567615755114695010896272349438205600202752, - 64427582809087183743200506517792292275199308207005605696318610655335219998782621131978527220790293611391864309285765119154268610763169697162435992972929320942994350729983645019342727427143054407969653664240145801301136534205451447406313218806986283127315859315311076676814087429849372418796979476643784932853341031810983565331273475993316844980755492780481964726232749160497203682174044811505020818032532732192171192523120995863765841996958664829140864858975714296902485350410944650551202070045089384540044733063491904686523928739744724658449547136340085494859775200396765233438588883084399280866758629685644535091553022123363974417075758211607077038208147309458928418680406413216428499958894312212301664125796905302066897628993635503682727896182074475615948508467173174898797438371866271011082818631759970183615428494656250777900219260862049524297968555757156032239465002942014922316505520223461848363336116478431220287174319737384506109694518069453434707934272528232252685535249535427508700940976044393773557848021260167949137786306105241476182032097102283664830443553117355742285351285574844921649106770622255911832874718021546929224058093266611686454792209963709909413068544871199689652490455977233042505245768354457490250068714029341383010724212895099226693319054589866435407542865866649174401113636753714334571787625141954428398851506469391400362500055436406953453448817053781800971627051630859948046125538143162562817642871569898872147735763180169780820275742134710985025612677874408944297017836359191181883310093726383844135273521391055933602391455883961465740735878904622586048016486410868369627970381544148552869183747814700278323492133648335822070891137525326795723816715661054189171741635407386352223764506801762625359901819737392213058236298271156658561364835080983539359534134233913708123893393197877299089687773002450567831189013482260312621425251086207491104460774125417119092909124965422638628356981069228934867943726343165828317972167368325698527873200773240871464254722400806243657859155107657997706272658301221223196173368457101378128017938712951037879539094511209958817278904806970665686978578300573405756633152041665298110741949242551153152016160283593471422624463887985181618704046559554639324935364969662594489108787583206623027743003119271715239896829575934026089813607375895197075721255284009310820044813912233878698743090937842142378868953965753568667121614761014594964078220642146560267154218239820204403617265904273717924676917305885102119651048485747586752460473133801167831989780274841388302848335512964810313537749851715008598283858685453420384016672619437284249247011771386634366960031324447895998892382572574366861228269088149171320011931786951106816342166235683494654682664820014670497040853458534904244118575180203096346995850467954559079796094013523764953887093199209412130544269750773090059415449303131459545334915494374313556482196539755682564277797267476440405463833091546143424627242978126030551134308183101966531363013151380118269629405331768500139024100494583026167215650915487288211565406610081328472819247635067960934147381021663227388162972551246101220064912459585230879296701572436107589804769918425594627491357108500311694296664009055701218742685999253321869420160740420955623023131398723984939108498609705104210668895270848677915131231473201805562217925354563126064558833625716746690939592238495614643633402123362838653428139969056806821267900788611778244700381553429165599226859882593101518721697753503889377453009056564770963108930462721713190010035535476412324191302435445948697313654943151621636867129043240998882901971052768544450153384512087342281010452046050932458758372094293331298569611096156226875863587041782249698382767127317667516829180474546046816221825978644422538217955403699367653762408945567578251913129225597269595970366202091167979958748152687630841139572090424029910260960990279747286007470990188833028730506126416576587821704883306509397825839886644721997475363425863786230641100759159116976971537557803940945429862388382901454768667301569820921019490536903730076893327050958875563376756997848780419031966967061550185614998463709074440345225598082035117377761436839721085689349940916068242683280957775753541631899160758170439531832579564983675712200148048920590857692981174769794186642422460511907481274254338483163478257047492967322213841659446607938625689045593828032601958455721403190154230840173883718444536749017570471948704240702408657252808058079309957145000452768464294964283012548740219853522896415891363513648304757281976464782610019452427857119106225677256287897198436426098087583270830163331279584368278455808264283529712610474085411634818371700739572587728805095748508663735032740860673264201250075688653237253371581574032448254676016197010987338824584366368855727293080275097618913490703246663200851487208918623831328939222922470980819311993402906432186674040617366978258652658439840510322363258758305696208288180545119775162920528602188193863716221098700219296322628881610551332416901834206348727082059602653365525941602318558306660685626792897107267604378968492169044484521697832034444482098237270803545240459932460522201918513799739621008644656896423081062998117058097578322289451762235986266960008377705869352032403636790500490225915300789861311658299644477662296860376990930952860296909512957086519144657886320106804321597159320660607260988075920354978945548758125931171168587554781129240002429519571816989050093065111116067632742126755521757489488704267359707409497296213551292306248987052702158006571254031262990126818728156486488014737752071168070664995759818059150312330905295743838790544860548121626183623885570326497555547505469986345297987922227778921549926896744380360612861430263161628328403248869158319984990737332485588391916324981410770638871282163366604935480468181267307597487020946940671586048417608944460343840945591523526358778339000317603161909396831641711947147992608403420366745739015113739529403920502204711514298094977024, - 387342467591370761524657060459668136670549821710984134669993486109835312921412525172745845064273488506863459329246571417323317621421520688677324367256439050051036961377419914582941160428168199815528277602408795595741898452304969666649470455596604429919630045756698746319062674070873397354112768890274309821789644601279409097427856343680609603367102791218293487420495050455872989625669434760620520913283765303199428650413934816512796855350989820454749705567670336035703570634152212304507381339446643062506587694441544900031334369279764802352621334298769028916273395160449544540668240312239842383262816787732217866004962071111091078929056050928731034983832068196166362098964706498225732741790385445701384255659154143995836789582343376213209576766339991380315460728859311440604830159774597551456128773052216931206028248808275224529769822368707191436903701602570273203022313412079170278382088699174696103818905768673585229155685210140836013642376292798488552718722592082279934204902490938715958520661652153904642231127337332136114176794786552950123134292800779686859586868811766879438387523189908036538545115962405647118080040597634063324294349109705345041901288210893930098810612677622610641557534639313177266891001014014912010479583264685947188084389182625575860266925861595214181499693419324861771236081482645122462095993377758233087837511759028564948225289450971853064020874757367847048195286342247480508720591305462841113096326390688179261163324465038095915447280417433972484719880910391085154511096907378518065364610790602550455175881734095750077872984166319998128393862964973023651201201105465136846484911272599705705670621457221186189314976717557906574702206874955048857918850095707459712207499955033286562686483570889779068808638057163190210509827681780002167055957038531307832132219371724815547330336032231769815732957194913047511115590618192070342128449536214174800401836735550510139417320715461354800126263510814889892847407866494740411236781294386288306894117563728814517576151910873474920379946099505862637416228493774874665776427076207485241397914126336531973763251302896698602082529112895940701552583927908778069561128092256196799661106791009581445427635231252697145604269200362145283536682100915274789841315428835147313207013127225052564372040628624229247421874016341585299539030843136915891128821767750968952756146664837969487475248730241841408871632075767250297906330108923281343779577501877626350623748394631640067760085756024467549517752311383260827071875535005339443832850141416730991882261148956742426580872043790327570224060204811067142579331166112390534250503697960972985965718037402973080172793641728343041692885823239266833894109068471285491071145911686025635052161942187688989517555955256207631455363559668141914516259418708541590680390119119557166094080687527313416145455108046186261040975878154102059869136267320820431930487306254698429773945018916287323237660476981658190007843514506731291995662248300483362535965898798814744566145873377258006864909950900475113830400403870362299292285095362073891525466883943801322178636875635483878185918455733739719663563585435966422105841968463446206944902181560601287000724184673293794138967467144989087730400463836732951248632080409847493741409974704527168026481606939968238080530453625365022770341137737415603895642621437833711704569654719309981762519117247056125562642370262889082197036419586727887220597842921631542824537601812874511209131788069488453605497000015447443215141637128935692041144728421172258854847198764927170073115360881874012415168061796038375459578055903336780449724250201261581525578394284773387866877444231079148920248255057257058739767443301177990502669270580614279625463151293845748954961952751470824980657494005789989325978699754321611465942974075104453341598243610269286665292263281358002576819069209192526276127962065927011055512240653484047209738608638161555843675621151003817841739921044842764154657710118308955936592810397379186063363243909666975029168799382493503490223232345219971066731758259923194535855319808582293459846429502349934144319076426367951710886505218655341406522379025042388316845939299440897397312609362520992223837543132567604939685852971853271398588095969495004482596476764619059656805390960543583527267345888984521546256675771769482206131838394692628109459656777755520334400427402232104331242868185651510397527269877546744414867619050523927032265703683026672152240999503976330330860017266576727895453681445002938475745895081489416927999399414023032076646660613083008834780730137806373420081400118558304051661076696627927559246876613461862007315392455327073593673749916118534876030689145998976984308151712726779106161805721020161952465946599234359861377413097007404445725372322865272364049273179772118164269594422633763734210342328242542765241926668639127970844600191906730169299067540132261623531381526329675312086980523551506414605734892318007376637055727058047968515135251860285353012993792592546189613547703833920006446379619021223541278222717491343273462347172713241462238604306463238023336322833291057849100351043277232140419335245358801882230882441645183619044364781149067318890781876418480277304342509797354458335805471529062132044747326956509151380929745244448548677011819273801934089908185363635945836519527724377525038493603628550321436706844780543808505738125068677327335857141208756970316482775103722732751685537976557705220279564585601599282885914095745311625000408462683885871012055265642335660046498356499268766998008083901508212675472608288798149697296936805014217942813229303809066668741125267431254156452434939616720434159699071857699131728424319656034185733573696812691452687337388698405432500817989564823971003798407671181294539714231228941150324949590366301316651814480181925660081463170480631789462351519792311766668478146774496666544313182934772908303012814651229727058260808289915339228126848730246670524292015013776763532237930843885161152134967191320578463105024, - -347214703019677770582682448529175009413817133731002818664436715314870159402122782526320358298090148643316923303712220990048177446963860419983837951644878483910653173484492328872207870156861991114441538492165803309686911628021988273135780624488347084320722755918754887564165694334053905583857356719474679362575030861974410066268770211253999714938645216819976596921415351391761243195507815220944976870426608105150285895593130006250529383314224982858867722235466708501269119251939303472465878445221687436476810422901764063838965287962729782054821928955975053123705165484786317986227580730647860460772596032626480225658893368222776471066337997453686805565946436920954077191616802850355196855486778478101464064110072306295117199923537243847224139523656643478970374311034184145908348055601743461761550824964774330670622872681109692263818564444389343574409947852189010303887581248798974223250740914011444551108902122879042256255795787599120798046457565943660682824436024800080019342825472124839689419770679627735828690851662061997664977711033190026831993178850360945342419509229963318618114530446785931448309082374185532714760126404443946918124301858334214445348526387091525250217478456535242675220263168492758700409770669195451638249302672935119082213479190822252132565777870363192153256066240481094535215976168135655914910556031852974276184698124186817381462765917076135633549282702503928581510958612714967201347775554576081290976553267103012758019041161662506543214504321270684144600578040237511162868988965745814855446438613630574537251624206092418181672192982421386647366476156607187838733989376193170682075630118422675607319649191394124542603353089265935887836412732914840420127459272414119263801067227702856248969658469455013844257117394255935463557279041344451993113690020844529601238896507597536316955710977378680716547975327030888396796754386818789464509560848570897214216550868118702519491688657720225687103050357296648773263500601924039553191010299963163457992459989274328247278224476178258822333972225704834859243981890867497972555368790037525479710880897190728464367571202752543666768349667628693459126989256164400797808011889065018647376933077194471920906944061687834937651884048933681202529941583804747512210361391462737299170759361630804086251461277971404954147291896225483164220994717980571452178820268139701983693581004389253844686101223086986037969152381741215474065688267315132631334080328571123284310684523481255040423262078345140413480130682878861900272539088215862045940075445417785504460992477560709497745816792436937731473374362952856645215483829756198474248924357606677276367602194661690094894457704963416148714233018463268022886824760545305824344777241541667572770098327862281677822095887696861018631611941385410594175949266573645331094814818383487286533987652145590730990301594063016768651875993897616704450541022270790458712889327816523862847678426320194351665261380719091498954390386704675015480836783067787079833206568229095316304308339201569652663151050069553274200465987191202497275468709521530409259169339607007347225666023425652327127510400116858482074378877844518737430902309663921218385835527043639853095141390758776390987641753223583591479002356186112616827215810272781620232753708847394941945494608952425561933929060127881366684473703048888274342960558711392738704813795012061668703759825799927075390163127969633308071036221819717620893036504650428092443998211086063171597006340042661923880712468700269921855788702298368890804191790756673270429703116679391890808941962260298949890849124499133372934222766499710186641078209338813033449209397008778881263206096673313313858296313979752051712644247856409795140340202301618630242916857168234444695859765429156868204235747016590982882426302611636617980205421661509371566572228162960412706876101476980939257089752814371854218634712231765801713801863640925192882586740375616699637105549223219293573812023416870449448322359943633581037509299880882533540884832314199123027691324175159392384915244803684071806031267480038549257317352473105528693907248131512484460200391182794014756585333955002351274109580663825592264681246690997795598950161826067124245256753180411467461870300699675387346183274538143090672102845347647861628521993964575241257730376648418732960718490086365991816737463925893216611615576159980104719818117376624201863344172977114898226655603207499885760700942572020207718561508880792562320951908694104604361421332110616165149044121242945430008479182311639873504429474646913504456336685910778815439695174481368659549234293788991157282483559906995003439617678726379370624577012671430354478806526244775402818924363161843309977223384363992491444096720712558381603732636372433054403359868592038169210202340084092020138614916294946465610825487266401220927276419718795675877334309097583164801176453536718133180974864336627465253709293869605881394385121515053963567805898187785119348892024329244239857761188370987178290636734526952661489915207937867932009000020692637149975911687995179483387411068864575211884844605549712774498167204622659467579774331059749003275077683952942922076161382319019409159532790183197626473548536659250226023122991784190152036108754372060993168118480661525615450924890787239782489590734075944020565885728526753072462660519181610584203137579476442995629939910421068859850635322458033022899403473915771322513951350483310134389131969182418239717864166504070051209533304300685788183031766158336414259699296973964249009774450670399388687052329313264789400834078053400291332136861914621311240982958429683007530651295021512583539579016449548086876412027231922674913488456541343323798348931030495203272279096501353427338887875312886080494087166014860435347638118502574324114878672610390472789292877205552532537063195182206624992772109171083734247837313144125711392569581960446887177583691203074922548880423163230412712216276295452346549734712024689589049298023277974144417792, - -42280083161162927922630622525874287365817785565441011140959508488905917959047521742193438738347799598385531579869108237885817487823251692977698264877041416225240167354424551392031550407583440338669371265973001800955451884577215971585206094296100593918035285889980191029855004744732058222219253256969385165804031548468235718974576040806835662743605401296805252497970150536660354252379069426513975770696352648819399235516311332954820604534832431892673294932240068049352602228372603490076826249899377116395679458408166090756166178072915158675117908868336755984734725694271918625372368284810488136058775662628357088435917993273734669474794691041957696192698778131268080977958186402646134954537184899545973263402538735338627092060143240778825179540481473603833077525322670930492361110237354451510270525626803224390249582356732477444023089936740270246163168617760764997169342242688412371054384725817505172453229336358446448721066118314934733331282227621940481541295456867074060378569359407177472664468800240157513756220839041042299487810046036958913520700332130809656813946885354240960903559369915646837689172566193614678688874672628708996093246618620870636575639417627686310014236487856294830084927147771956926940627612452775630551388288103495595271202703782858177393152948786749352669577722672695776352742061130176120477684050400966484197738440306833538606285146211867766508612242280900247186855896005912997678517819513937303840841887515141441222046947444612615898245367048739481441296850403788720056280731798795120579610010203052299271337314786767262504028298574187047008323473875494513612280201107416122456903303182214478307451072765981569266975355060521877831892799442138686990068020095452214541236120137533527925238176517722882667352347981796128495631014230511286557278365620198469260057734157962065312712450637468919353759086184995308304497231833548797834951649977433952898248605378783252529454840455497436802243605502250777069902712477888010194237918616982396191535281735262173526431665640011947042742169804011305175340003628124613038275097937218811688159608563118682947027433889306892866650934347793775035537975760044808593079608554702780598445060408895952588478693183976029501496237568518173772543249278739733808965327310276569707297702098580210050461775741973465402414879184218591465098572030872008556415849835231613288471838857259347735446625109781253155091362148417404841493743109225603767116306070234725565439279816015161963543252359242795759619614256577563885628852736386547633075514725360069837134015595896532806720822412693716649347012564082425829224739392523823354982193547079279176310223857274655716148521698505392213764664902060524126476091834316589871016855626283581600679575845243363899727195731197631748759138643936922434188501263032634511862109802206730147878229795167259465056990700069301158796179072045759218102455888476072017705396302730581910793483121861324101472763688094373637711157526841405335751364612507882384902352477090502260809153879070820569046278080363946219414660862496777161164819526922220691983567446943855911983421620667562148916939741624513705907277178943742204726337587741290331780094912759057187144060305212963646693589070742598957300869176986879618065639285124810640966205427178948848783596235549701178098425827715098812643529090307189898010160019612156693505545610729840699360039300018781704343676862604008532734162287854295492875613457804144169867289870432748451987892793621317857396297524853841879387146774806908962729328686372631909303482679278493580454306149264795519766802059537207148836684275595056524732830887419637603868528223523235420497996036486096250464637692157741671770459123264398882413044302184164315306231121621066787149816904069523119913312603475250817691467912812124502507332413592400632610845834300375991586539960236759319895912401543634037609615188018252870597773194659382976256722196718419180626324226814801902983928784575396266493056160099997307832704023798577898642810274518930007765210798375582258421335856147180412344079256143056412700076669200560090435051344138014223730498929681161756909859229168040387685119573450135575281131392433732363300770746555877488525800734913005734860555466743753762492316319384016503102022069491263597183413625411205129529780490049511877773522729679892988911952794602379528330723099276941232450468037041035907240472411191775921049221215125347189263502179519484939682044209593519285859313272843357223954698214302870800671998138265354674732968770140437798401612599322938111502612792682445673131815810706259479894281153639585071241200627116137628668594976918292381456538798442534428790746801881850272628825300938856267821854485568406789552428726997456440283798057190190530322672789482975068006251488772532833649689203864906294377760452396025117028637964982168941695778256979669332822889509425851579750558316738227085271316532126327587328783446757292834225425395331531644343220885365934216449337045459302737371328314219920787820290042810244489443838009280292089651668788789460694147357918621841759601978248972822636106368169801267614306623700053317004872622209458620196519652226281296704156866346943175585866699041303054396758763873615398033848145928760557711856942925633968119159439254642916413728012974987176398497592080797175954823888174371971734872180151334216867903438008020524798410187943579184353489371765075672640256990848195804645980223274078137100390086466253456352605362743494872496307348711471763001089115372979349500897475369126916832197365479625149265521564288452471574218504951705251716233039024210481982200612266835285407757034079837257908569050866781659358522426661337473045857776248021917311014325965945639227727560375460806290081945126406857466954186259863728119875525026472714390346322392398557256773411812351372062075146335356951100391314057766823299020289240846096818145952188034387610118241009501701406383803840725042334229275344896, - -613776331046660003702867566495591117043062400295785161694572143027619477510424423080308879032765439803296266755374209082051528276300009567920268397334635265722278198596397417028440074854288397232725448260403703569763137612939518765390784697595993196968769487328224126127575099322002935629223883894305038745585385671138524711990443426177409156768224188301634513338717530565063795005909938599524080304698112954494633840495817162259517906257580911461056306047504816638909581323012018219321028195391126375518884296583771286596329687281511053116361364135245899757858379652498923283384480930786895720045582991054746804393678576799373805030149256876792463236249459661599595989031028650942028731191131665774991848458364339537526665741590419997286333994361621480770080578835605213698660574623040626441693097077322273850785750405098929967767096599380343783235191129042180468549552579779073563487458252122521641207264232077106574796352366112194022698951863408183065368037590909470225966526917235251491837227827032528718468606250609091296419223480228023137799471814415252553766870177033363050597945049836279145828948856523602826800901713740828919817195986050825544575141554534643002322372320784395596081365297201334855375846623739070507809412314423461757444997008998062048678469887345385007613377989102065458581965004702521381560621939605437528828005002142387854611243397468924442013020595711905373363602878761384996212489666207490939055658888957704332731042789370619394106647806126377678195284606776467739192343243555105730267961572638754359081233823494508665693277951615498508665133203245919557245675388936184969867218844348936193845773300380469606725182393310692681442732691959312413827818956762994665598196316382216330884457946168193373435646201881091330483186810657516589582642820347177648981398125752941662758990236514656125250988850358871672866469964330374709429159085055748261002324550264093569188284296992819533983841612519558688856117359261298394071731831845077538283147080967922340856782922915095836860176872297564324097190129058314201672430429111496685125363717632373032773004429271615690959571540715737529991231837675196646199837018225737242697324806371393754229467815494969854956044156623063981878008956152849569753417247512752605869661528658747852427638100544311756523570440211333269784424033691704058734259790815603499867894449730618062159354629890055780948344049261689867290421164182595395156063917099238788563509538581148377340007855886718112080958288863623747242832948387541685220514903619507894630786905470964713997681444344921787493526405656702050788743632535697829740478590798163387588307707932442866978546533543704310908875515859799829483050367990347748556694107063665220457154551072997367325057957414363483426556905938648381402405629720388124746091982028607373181941991868123305327587664479326138818962413111540922960634294659634144279784982608246501979123515387332133000190141249467001991592555842198027125224416491375330643413959794326109982209578917459227429427544661853594583194396896501174797478971349812001001318766688113914746001922415530591613991463724827470736152293310711073046699103186001362150347851521556798075848673453541882228892855880684058576455056930629747359970331720790084156667452786117908897802950396773374805000824372847769927940200226132093384952098163404866605405685489037241749622316532296588098858825926235034417449214590183487819694152010132187473807350278488630821662166142527772988363280381345088137275987398192936574466976249523771208144664503559138809681216329563405691478214973250186563522257508803626961957930163024910592495769044155053440933418044876740123036420821784120991775895038838923752543202036951973353357863192261541572896237593633968111105240828940189810140271882544324142918931864080839839781331888848234832074920520526812128283743306088915396118834153130326982737991207533242499673126157214102753505086582174978877748670329986697263071997551074180246150488382519772792121668497073285374571661530938748184203450397788052818340001926356883928309304875305864772646958142666771279622879937066319199217192411215970426536775689929844119134982127022567035816666212803990586058825351517828326941519470062042448801573785884493812588853798164971157373048199619845030431593286647378037764688488677512913164345699903734135246895288478975306932013032928320857939558077825785593884642051856580550396270625162392036201979261729255752085167569475258334720346736028772417236695246944069877062437019401829299264622773856910368272162346913377354250827860784191720970189010473694974477146410188772347237020358368667484836412559394324504733059182079880500407366689510579118283648580246102736686883693423107080829250044272386978856733380770054209594545112409959092497025568076106501689525018611832581294676303010402222336246308594170436135605259479542403588651744532147751852068260134125136783540816261041836804249474645900155871112244514915601057095522834648001839807838172932777916043688971044206877243790512586045497730403844787123092225359356143493261377083613463004854447981329091604269165861030903374628017620776169006381646287494739352902239855540161642108043016347696432609679998958057273898212317124305040847342252534347112972274966288666788088523399221262126863768681906139300438016335300631036182674088436205000606048842968428160624965493901678777229468358166102193380582505124905598452006774208419015173828958517202873949751584234108077249515261802172826494554073202201977469952552155553781863684242812496598434072957113911108983210410384537376460640724163892893800992269144318429696728203895025752389376935295004627218204340965384540723705907243075487976355580191363713453364460722736858500581186913304965503602873659732840575033460245581856165981106542999176513687679524733746114707947728086825108355245524057446923148042798957192231209319178505496955304854801088512, - -5549580842092455001035137460715126248285526654475410684435468113691085046025270550448571014754860921598751887490728924168538581733369553949866476809486004457199919115613272677915972715131187798446950204576137303247273025549254406118481499715157790779795128351681083863954534820894745108008320208215342440462377485101031910968859787839453706540816675254910092699949691268856299919370415117108568958097393853405914966983871681448901965197130587331593760693496459093191359133428109262193556735659647001201995012156580867910709057206027053220925423575630251891782498016446122192997970923981691758214538484480468800000150075810260114414190916008538229632371269104649250878034286712271464444012828890109600085877299682770624218065852796473962838855696123713162627331398862034005208577039060726819040749846440267097303738364233709943364155273366969406893571595503182537970154864979421369681349264801938134642448808638601603444086796862535279724898411542023908793666671996933063012110850486866467467973542077546884070084583651752288078684626993690520425805444384134410554867016635452334764720373608858362015667608674632780872142794976422753142906486411911548666562298245200164551494987008009989048024651088500294967854937806502131004575963852603402694075548419308863630776449622536690837039153252466399662413408210960539175441164014091559612192389399112536434910444327702399114687940652616556096576966850121080118415694767654103731814660142922718220594475321187682750113555220645359709476355040599163708190644465798001451291854294355539256521605529329961661929427160167919661896705217888727727808436847298004794461425919851123468230519539414650125530271809901272653731048628489006133262543173266531190178475298401735052293104105939107262767370298167826144868107799351953868227352349479409978158843700701187691595748130052244362488283573462918296362298047225456996301800880426517920873544057613970423525493211400089863587691279176717698484758066029129516130749992375395285433180915625461489025590447311173423717893840340437243936939303676102355849213116109700635081639062509570212510132419198132634367879610905401192277115273849627368917073245387903551154469795567986364485383793732956178148151874605362071901744613833392051492000350428738609655513216821518623561355733452233504283251507321418854177275204332429860131511067322533421394034777550699469842808343455621084587850739087325532177472787506656368612672852855532977886566628338561024270306294308283650599676651365578005853085670164988716521185244596868398937241102384334580229607337638503250378939341461423017243479072312190839284125026645467041619479448479964639175740890217549860364120488705272517527501524072717430387177317174757884004211223724431939389279700690733865016860452456909066499025570755326973098156510171710553292290801399446005460036191175168374258473792407965094050733152020696339462088791115887145899269520820988289211721473274717916936699395330276355479272264035628928496636177105715010741191352218227739368776506356040314754837156551352487660103525565362256708245426280890648754174430382639787696628426201984857695071052322784822595782314864174325590986044650993655023949231685727890441423096989460807823085765544063511066328129245914405057180083860716822827769623089617198026827358242301973059932094307577089583554725264419744999934240921299299874875110698689344395730328837161731660221723230436896294885637659510793590902158273984201079503427709531793601239946466414215318077976709553838577622584890607221008227651162984041925604301361339153490368256545689672783731574929419504643512158243185926622507013787174985698233530432528648833449308969017212678613553215956500899652706726170174567888709061141253191218344946497014484533604244206341854691999605388700356368365212136204586533995915908207169620963519855378722840813597791933287545596570088178482810661028429234387133460202222406753752564959070738532474195918490502635871530105867801251666309585000356965462238935367371843446774106356692510803404545045152757659288071319040015112983423182234491199455862092228571344771464410783871738351216882924381851893869800769762873206868536070097964150478416270001960595937427602969239563755044062161189050068619153298874014146434295156270660823750185797050514597718013420219598177738963288548262839241664921203407071448821033914961239006143533097903383385839613976415067688408572473741216491404285479426354858172428762710879742457497493549857538858795932710244873302629649441444108636211986165766809948987343087117748521785599060627921891013741746865581588479884833434999479084049650319177242143324731935582906332833389140747214512384885862476152349946245144833246238836465398168712102062826546574333909555788336511674490235476535784412840975457963869018517603771305466363728291648579361152544432345208817604480317673097280948504622589509486302523008910614861090104055924678612961669141163693794882506043923395752693599414517510140563107394877068210577363238707560278309996659404392150968915248972276606810542653989927253672914645391912697742797948439601290455913689975611436884012603420370521510270299112377044744541499463726471732517669507693753552835055440564145551712581223002394497806657431153242600350289099813788586209814011335771350917944683258712139717482608721345696388141900683581053469295542706887777175350300705001071947253346430131390945365289343103447589700290681869205427273724207380406315072619650756765287830424272018767051136862993954400103513063147767507460854063256814685566762790632162529680509494823729569676385484715063461498073931733115285296778635792479102744309152486168115431556219565707556075831782859363924713254228617055512996803581700313378288519632190812169278541296751620934501365428692299366016729747707297558111986235538268689694423086746874997269596350385847576361519172658876911580086272, - -30995707740677987951911593553359672248816686723213738174219531964607178402656426616679667616742466931532626645903343968390780077438882454961884276413586492913159214741315704601407478502801250850756371959105586010590854281701421197794763546230009892103269974937322266831819334110768765512365595228352802984622386929587418027199649389343956302644307920048921226019087718147457117698699509375466133357456590966246831547031619890736540265984837182912306421169649747089996732965844122997390664006335357041741237412758676994365742333902318885698983033855102182758689791040516491507954473113141477093858894822227276320602931431329607639275672434927245967329603258641626895849828608612353889376819837082349244114393574261527503061174309610657702965001747926128026620419456774455835384310219501122632687775341597130124711557548209444605836047584962217861031836147488906878820403755327721524486943294977114205925356002926946393332050984881294573008883650403821478910135903217483584742936529300525174913747472452847685669606409419464620317863408262473284168710401130057760803766559280406838611278197991847363393600138214965588897940294380292752170325953662138697766003509062029767592760059832752905141170128553632237048283537321565448235407165158067466530465180675019793080339675426326529014848139099137806955909295723705545494191414318741716955620084306024436982694005544548040888726271175063871768490222371058397653671050373085665382089564430324585774402185253347542121429402323409378920407760414802239374344993696678873985030538897264944749284877616563564149297626628626094074776250977791633443886356236926895512208180878981821412984374739390299938015737342521957115097319231543755813926511442508042658186165947746958573074497737560465999026534842035383183069566271403254810067961663611566759282872302266337407506702261605039739275339580203270164607007774607851504897583312777795257284711910089499366472949518979104096605849541499033043113709461570862903993800999686959747095716756780241426789811974112356767668922134305683853386212858810482587636041729931798060632581157562882612608836462842094754173391647195326201274899202198242279484055498304379999056235107788757748877410774098218374588244812888441151717092754739390458532340525017808444003111348124414273364571795452611374254579449710778829451228098116608567803260544072101182164870157667394316845317485011785394412881834519897259826702437096416151327484244449042598103987862351354887514819687941196994827399522509275863055265513399734757184774380562128927924335755992753989401826383129058692916288776712655303620543357748489273037716740708362694184652661690238419998728819919876091957955886481757095523047383904960137000595221412412662013460330212694462822658491788858982571760458997783886901795187945470978987326307900894922703325910243820742370321915147091007318114411965723579727827011072742899080388935452925725828597936559108942811462284600601295032937591626381091768485023218082700182005426330277147914780869513945759665378046557020773184031641837423514773016548895604930227916678616290123628752427558253616887563855076908756944456238940346704832070230724693681648878636871741514629954333569523324428803722744823049420213087370815829606117760430982418101211534773890283395851335962651374053654236967656073618205125561329962393607766590122365161172311333611656155286006765041210507256312789736766784982413943471630658286889170351738492193038944895612897512857884841722887613915864040337606496382382058768952202279623275552754094540818783910546363368449459144432725703712641542479938265888510596133278571366605165232892303248636073177518244792261926708472613625726470793847168481118490736066545317201771609217006051084050001910510812881282125961023673769203711106371019683644061586137253436438336094608764036592599506556265964447626502403233545646858949868700550147948251278096083070453717546673031251110141280316465656090872807377634127779277696770163366133543405095095788363583779869915828210048452274568731706780647648181118093087134794869954517921261623646352051886039262633264745878771271255924727311668464328374405071267128829584628045031728510056945837307806319116501911511429750512447380852284772903701254661900980311750201363938001508353669117106671220039997285099620025810574934696246358946666758812200827708121324952398074421258396099663683787421441531612100081891148640263175753575580924872823024226214160025861402187885826144688961337792890112116847546632203806413259862879736155524743300398844855375523556533908852864456532590653381605933684610351679397611587450037882935621116936833863949160166415506137643433296796893736557170493875360462078898688088791182411034594164298050893233824434820424418628289339917014367385885132669525746125573267990360705274564289730745915612934121623217186024281981759253379968453322466731421579026520054033414512344683402599325298969646891682675903057900320731877562010569183847427619695898196128495813842803227092353929825761207179911009472524461672721815447145484254777919409738551371358631231191990030119986081146025608158796658022806866682889605785132412189843123003140602200824913037439808597294797487930276755739201943528478543271601246933974171909763935765110971861473860466582486684449981719348614753809850315426289340640689702609259234394451420238032059557636804306025537244531472705526029382987691890488109850409807846930794526650085185160412735307617633509106443728552182878665762960255542066965655374213147434648659935412177373607017159062478746966238481288734668748509978437620665959088541459034677851233536704405770578801018665247901022843541280394084462695800055525654285129098716730977946575242697020081292685277494277110978914973916997057352953589515398190944980863199826427647742180647787872910070302632509019688734432024407097126567079313408, - -6413742356385207026517531721211364401144907950531541032173530498012946838078396477195744849152903078722235275537735003548767588454777246643193292744239269852516449046226882495152074779827765756932248082368185610940990029166101612100982385984893179392596392745989222581089855313069610094986685536541658909865679707359280137260266896080154861947547607705934908017574947162019207914924688144917379540954422631719735942261414190781875091991936765063249869844142375013331769298187204686188848740908706355947187166713458706460234958118174124517278662922892945219410205561790303282572129136405132266573526239629260276721307546797865214834241069999852192858306635611597248607192881287862272764850452768583585873713083630362979029214126509987594341382227873420798598914701910126190247368984426594546273353876742612571957335090512763504690520866076380233262651354386293314743541049909725623038385198435561064090634515780584224654390055196799287555472679126081255522398090832158213734950473231339630059581440691673106889291681744403618842335501761835035418822731268988413562515447138461186192455215397642823934022140165260117076137939982841982728991167136346238774309534473771021167526285952229769557405220022576294543397741817766570717484174252126512843358174035407807980191500436438182713487212495577397832575448387623847767762644126222369948087085157678732658145788839918848464405954700576084987209160597674052445471216612044841674123014152528981044371806980297208973847110326881072047698509648069814906102348702958991407895784741016664523320315190522095731053071183542947487715891340048819560736222402114501684098599482511572165166660205617782096348532234775178573281740134673537114419131952200076031874558082280109103595777231055982108248659003893398820448565348670844325825508779489456767608161047073574386265847956612992019781427593843604395112652486921419186206919075774778179718680718916405695532406139499305533873089914821807323251748333483076446331659111521720592431207372609848337739385951048694456193993189948484306655367381263200480045784220589464327721040623415097526910246356168451260936185958529685069432158390749039690572466217552218955314543556594369048959431854143113533500822447528513664860281391049836999690712804531729091315013731814757052970284591259914753651477857868783321399452126741785479672455684954987795974544670404632049431354318080720089727993183190062337530807615620601654640562019233989334228137899658754691357849388553700223004094939989438519801290066822462022241007544401245379305782182492400456115727363768316956992419725279527320107872170960131811785926549839518605352811065550643575343733955484574060492490836916456820073015459643814271139717753971364276180665914587378933132194140449129322554885850494450149726429398261558760603826726806389995724304327684991634255509768970202374109352940283690942038418740615383910027871609012283793705512900650759279645263511418030124870001718148948501339054423733048740557795121931172431682557308562729509232995923190409453439609720689231536215310545555598319082524599033902959830845460745311822393267612148393839065514173711268040262598701713154200503802735995729317686785563096017806195721861705244781211263363899860316841731584057213084614377507265804519606067813485810041641733900255043895315468264698166954305576224573034139905520717913158060452175965728519363254207301460017502286736009929919000500272233307181172037696398372552124694102627522295654029319611746669293565515952184039108966271101557672900724784671117709070586101578906174795658910561833176288096062279010302805168741721858816403489652725796102975027890605498673744807319772310065321707218076424824887730916732259532179052116506015081031094509129398181536506740248369014799927585205850342160307581139315468999670820236512022831981308933698952892738580174836971051839449982782731247238484698224295923776403252749774844205560635381695320927040043158848104616921339257828658262716541549488423936448739262491517902819296858782810437544925052225610451240554190395862501668000475975224154276799719641433459114321067296845925759525952459154085942471684009256833931106525822813355584600696942649286423632431065009029686867304264804800693578746077076380458104387712450791669753704879156028294070254191076743114260056426008068728294965750892618942727550256069712946920251422797546745673086850318746647615443692428950577343804346099702481059786829258571546400845988137606109407128979533996153357983578940725657377032985797664372806893996579643599185331664527497931996599421721462401291183645149882714068172262923381372667958854834928813163621592316463639954391370518495004960081505727643505065203111176493189091061998203929748775588094959288935788228631522732772908281012658516909745145219047151029336280153534460731687295594450095398481472071765972021317806039766145655623975088498769158785593344527528053312322459952967496941066071146573396116661198075382656714783715429280496231400474135107288290850333941354320681407489692253007474348543818771377163573810130906867426442092039478461722061698715234531170930886940829596076078828153633236064789126028836142780766918506713591248333882257258122866347255388305872163085270576922800549067412176810699833597163094595228214361979309615426601855920463959197963027107230686461849463934808696060563307231234082027971974374370552745254848703584416181597782124001130699208032375605809790051052435124432497954069315702379457962107589134739521661208747165852404133241013665284105639299761578582594175796552406660963318815492644859660900360882566874422278690516057502672571168003768901545190142870817501259330941241779450886043805602911923052462802525126982213515501673447051894737781473304360693011605133683316004119184043885310977844254434200935042652957606674432, - 2344814760248037186204194897436226594712432874346175818967384243368239384297662205928626585554046703872658881813387537103411242529283761169934326422831474894672207119277866637317343381551920301150966578697503642415134147397140176871547126294301293546884857672123097036483349470444535000913781695863048189008549750787773142196387842423840982999424364619676058671305009309431277321222413492963188233511948007757193380719256114970724930681082032331894387648479627790791345390288315512121836527686500105713293067973201233753722596751130620526592973252690090238526827497715291059881297172120298038982663435708850159615504097950615753922533163327296317942005126091460251178072630939844159419484327018434570071890179037360236042591735638132224641235292211426040887709962296226163313268054223283288571980945776038985900356129465636139014525239352240209047132409820644285686324669000539553224881941882010717186619383657519582346926615394857323639120631909087545253506939834110476092807812187154409424802242947835483329781919916087063285585624556371395333744545146462235642313058023441305972453603819652462707432321747223416944344685032628219789435852174698387948036332444858076897618622473360257059228171715661189750810548938976096534736010359820362958621883922345326892740853863608944218720677993473172478164621132153304409831037227413386706519724702594484894868081401802838899974523661779713993437699515161678100620289767406899008498463984010010735825331016914917226887907322457356290280204874487617194215384991544823419585867551694816516056436408340296825109360055341519626525642963243894049461666296339175706596006641879146349698437033876360710795978316088600904024093564379472063801164332939293991424550194868547663732331173738630633655674460426734800442129382046110881882947182818610989315817748873532177929609776660318761474930750026044105957340806502844709341002589682575435468122281755289808904147451369351570735427435584030203932681379091531654753475051048774432592764354214895455873264514752767173375458872035665142859461591741143745014444861766297119586048803409652381950949876599299682213680560037240129670186339539996412855976807458233101180963578837271585801367466954158749343365854460329433105821587277305698306352939482564605967713908983464161994020753300106961845330063813266464047718635593217021838112303638732430223454969743204122841257280720433171202186172145583830927342295347145309568287933874159217421046184858796274954485411292518032814229379379841639271575582600893279905987338182020823371546870883682060225605338942176621148391010419889806497014364855956657988893874865832161152782020532273687509552414171924739634518388012559812373945013630413959059166952160851802595854818604919517583882699355232380625695704323700897034045053543427940282452363047100672691648363584939034574522322668385009821499169948691260891015771866014602936873053063086714225391482296014461217284960078217943279278867622024578130137343003204588115153167568665194870877365099554320386690497175263260043878189854322575524759651901470796446408755305706606370774306993204072859135872955527890900809658264972395853454126765644567429248097047141049884281654312796491703965723114593836253441331439854759169551098729829622232694524182173424586965198293310691129544228289364794094233834088082041265095544132860447771009762372661727471097425163459718041788706964788846223587455985639532882917869551666372319018221064829616616412554691120996331969536729463229753208599539782990059055947240823641907950358464077349295968142264100753723295018537715995491035190689668352970054707092070861259684457976429847377374796934504785052375356937388052005911630057205328062151807828397739621929474204748345197536195825260256816055821520387149897370645837874530700589423237272038210635334208522436776931001482787542177543017915257619579554864542717738675427804990299502493718453534849871294126435567244323695478660173859798101592780931507753719155792270252733968304614103833519231026071225586691727501154601261457626773613946436815962474320946103508224217902207616436141588880636527187039000966187840376902775450223414525683447802909071344505286836930845317794608372286919734722451654188007516465485999231881576745560929055018021670877368528635498638588505673194098400964370998352538056926388139320798767394586855109157515336201616858493748072050320267318177118757289601119645347092566886799672669068997456308207197587076835750100150838452850635296753868218422220475214697807710148071046018940439589259387926570840818920379417291650953402057228111309056346561426051439527848225169729513035458741520185062598281814948842998753708004263606624893767937976175076914355760699872170321878830462813938283109686439533239648216667857177040709263683229836905486201467738382386848307233401363306565349338005492550731875175145900547500477038531380813439624049485590837273673363792123044663143416282174207547467730019229331058319467086212833468420246724037981682738887939000707959173708209463017190021119832079442168942180816655777513554290596608061698021853499864104808730423505010430554331473116661792157012521638052521899163281868060002875658503666822775116863698813262918694022669110114139450466962248593058109374448539382953386604948194108825096009045818679529899797540126343235956622402303964777485274292249088071758557185374195680900995152823904324824969478720010395401549246573399754280253279791333942492757610861934893303628613381239314135247399239245922049337812179401040567366850740293366303325158649386786012258951054942549401870275762884421464346465689213683541786134527247282186869419643155528904630461147980636422919443926027260570222336451307966244501436372067658280426718688984697638432794399074338252045460298569248686160086040576, - 34710944333434108358894190565958704217099775655234078602750403686388526218482605473459486264024322578313253066546443106529705948400699701061154635168711058190242414512518013951219963763858696609640816499718153298662681112439267660664571894950513233174632374447549580910302678125946745676005442515920494486556464238069404951684290332158704368838530277747297301190120862319914095622034680579376444854857982468486136196180487804832524539855129720772835996820042929860176568787817526746757878567640556823278196915601062033095889905473358782498304030752833156349154235918216619808442518979119041162009434025905314539560693601641513439947514332303962947598503050920647551326900527545215124654846235459198189497585194984877093121083618089904735465104500446971744983738517314956490506888867803450924644302205653903038297793474464741794989004582697557179811491857561368036084477732711671654011528339947712797981270009802269826962019201592555210930535203529623839064786449781556684123645393297120024566910503444473597096645118483783452474978611830300935189627700978104505141687688174133616599716907280028406746235600271043002896000736756586442493888907325408853212283563001976797993313242642420476198678853372454943888868594767349840202696262591342067673571970941523888832592203247935941865458890357288882369577030302736840089986276673307402463434452614808455239082847098479317851736160059094530866372658475021776512402767121794316328364181920657426463968171554559211610557595342591453476416601799607162394257175025156215210465431926285362842593424745802420178560986514448384725580238125952517610722800454703098514499365993694473155924564418346673073240050251895534535500851729657464361413577392152452632511506926487108964688987979563996022790355104911943751643652668445589976575388353661325553254836032106843326610378729734318660987072820822384892667369606779999829324633285400365456671310715816511691289091697971831135571751828605479748072438052920902944922924489229917541278011565212211909024469638124366738889472724679414286216246059415859012191692974776048479939547014069944019908318443961830532762672419397169059655265155327553870206165041418201306093016830281068481235745488241345695502831170271559684559335197057829442413815198560631256492862067135373924209398050537408475000991073645837440960270678882055339535049189861525060870265511643229563795093092265758147475020412929834307111520301617034513085805305723822494969949389300593541376041730979681960888423543539372208825292875282007104991998030281166363506095164727111104793452088455527906872633387082119516116556448341786085207649981106073912629589701696578393059863485622846454046988506414092878990607497001192651107738219028417617008504170116709734143971649958704246798686854785790161110562327127796689031398556016740538938904916603375684775601425109839304877557186635000125220639574939327099968277024224043315704852601722355042429917513987967755906666388257706528705498686350684512170019482323885632034782398722804042339901601439018767460177727706328625481173972301025772534582856783202548713629248356456105323498644509806260624320599887320876611767837263582683429637215239505911114666501757815643147171390556291220084227952831987493430725907500665477546550270525441082103010719004900891291146087995446480296093365134724739202684946617066028810368370291817375160815218403767109864057878255673513148416004102938519034016493715681055686657378194274735292914585101704319924087254827908826846119163498974761462370392528056827713128661474658862287414865365169408727784189446998865798712998576462588041652920037602118554235518300775568840885296130129445055533737711588467809635577708193769474108558728590663854191642120100683531192723107309879167199382063231432657313665741031374854623320324181828484695695887518664659942382270158764879123855381592521155148122096067006319689708414053323009088756841989912779465244020194430832422215419993341393854391837713308514983848105759863932431905460253710182077331525764923404975781760772408579496585730221540434282238452807046271280134549416171500725546722746674554619145280949028227149515637680054256611570193457451309817238965346116906171498208050229129672258087382098905754854037286391567986363178159967783784875676973446607335747094796708693885513580952508007720522230331027574116715539895947065758815961387876668925440596257362135491925197358351864646970725080318239614752420976377348043756491477311392479297092375590382773018425424805522811510916962807239020035708322591607939472315661834407446040470816542944553860096214429182987679805041785966063146080504282200902974694399070342003597462870419846556756912923465464795241645218255124824585403796273912254706825091412018886846395866365300470541662224361064114784705893046121216211034886231976415441492004321130266441201512346850179453065988892545872416764342602677327343744747380099333246667075244365821162671320614629044278086337687259091952227264609011117739424788525472600467963126086769694265447608313016951602209489659929851503512160661548740532164169795890190504047425577531392505901210258926303709555384003687097790249377785697856300886170346687378267913051852363588757097594776822444848794807292449994346877294549135515453492381674307506467974317711342990861881216741461162289832075038021909269344633568097993290080193236435923265231540605467403348596240278397611649307083745170252837195114655910692209043369429772863677017427764850776150712621441774012918788046166833785237678284906517982292406028214309551647604392008144834522934747014820041635317171524477468936922103967021146674373387125988744278417868733567284902661187327985579937534518608043519438443448610346033821035601726008251954592427596569267035718025216, - 331718865899224663109079865558389154602011397876668759572066637666847457921084345782378670498378081289766444747755463083210652718609727260619001513174333556920734923780588934311962728774806254087028294197165126249486198142797099875431354905758982765867412571731072725678964121111092508074415359783971245090360020160643187920120272850598031315552329502180090263066426698500486493507733811193785116484734936592655394178184992207407972617465486606257070875216624053450204966624460624041639679751459362119532249963601288422944711240232621190782114626465134535439079983348828986199582044233856395878444618515395307587490211155933254500437732162214730827703364340669690246936335570597117247438629852954047702900762964243214695477087620982688529788249352089201479300606180692958388847530000293104709804831271254247326627566444123541853728647254973099495281326353000266588247688052894200440506365558721906003489867619488548778119515960347043228949092404905997194838246821863331726021771246160026120905347380605033802810954050428682325267098954663992846614995919395125972583314528258415435001262302878188343367653181178717299186003082427603356337828035150948955756248487323216555907318870584697650279001380110330743118563962935469112962938441597956065206914982331802550668328070001586050288729826353581323222777534122412155674430733411229912812363994198441922669879662302601259033115245062350952127555088857923537080051705056126080891878336474696315342164473851505226806139722171732259792685013863885143375145229656313396451536339011443772715396860928318110300585146758470000015149503853901981891801319975960270360452497196516170863963426895284660476304878312305411191978135472321519008163658955588558018327405215832900210656367058165342621511872397165018183717917500096595548675188880701438491754389261184053462175098635597583156466344536148748012450766976661269257250845359963295883357837836603129091753680941471491151306286132951930658462476115025719391505470464724023177958242986023983988402043594045086432366670911486697653116705856694140404656487316788941109296492401432133296605914017816705189127159224105389087167670833301122750029786203184880837252560286904995274137088101034612758350646626015057413131892776898699327839798229078203157730206516740958020705211019756045814451249865234835073673312597771173537521165384297559748824597130115029098848726999319763310829617066714651903837513334940886109527089240596502655953978281099491613160658765283838839479605231830449323028577707724114333708665669654566772170712811448590115751172763339836854193591875986442481180029172462790689491559545318491193097292794315417403603589954053978702085184319959248948469703028618562939505517189051132883632299136545003877440426743806018445290703320128614215282815330935132779167501098116168169177022216169561845321568403600098528821724674863883414443484047779062497745327558953687530005357880151043102876942048374174124986089263572791472610807033234811065956130463119635966260162686519454451902692843440882836494584548640667614818265990384187654465454038306643976052841738188695219027317052445512074287376456082504527598749172362758653195444891028599052332132187444051619142356124855500546581487503445566093641092616484235932290113635374711243316194318235251021189858133668148706152276267702321628455852091636540362509195714039862662334641566551117655271592807039904819123015291806178503698476845341897572573326088488886420085312237959079032050433401908017647057992702273271677966810768372110212199003321211770166492277255565656897002666962765722396922649903621577613132076896499373616711195677491075802386552585877462156366118590291742801597404042426612475875978112824450161644050556906334247835927349346982168684474751986496752788809297019850884676308938279298262553260806085031287445977784532883468021266218496601838854721818018855181526134875909180614578632173276023210659574392182779736343951726756587292939035749514201462240271729710699366040211153343163296200268238922744051169886075359009608838833162536544725650584744154058772117817646196033294046764154919682238368325853679596915892120073626362612643020823219666229882329460233835739240680536274812269428719236623790278937964182059432198966188445225027878203202393481265301053709122741481048256787853159605565959348448660951088725394130693174434076503402293378881378584643170316087776904760965455975237565140123534330795309475856650722702868254614084461613898519442037262629311404252908770507264404799562445724516827399142677175529622974840202341444956335323371246874325371789671739711976344379803254076464737798796196910585360315415057527706635878760665166925007014074162582884863674537973577485722836341160057794817076935009887238898259212202758222370494244457591276076511656191280722098882711458812605982601703951377161407555639812204605866570316977185774948271103580305195534985135269121599733638264988339564344263018094581765889125525072483106161339070942955543419386797039546278786093656723169655678176568850192969331407335519013602050096501481059180448347001149273474689491073289166699829716037041376524049899960397228376500703723034119991896924869374489255080572694306788949508238184327727355597493376473860489342507518250281477483616570638956981993448980548043873187517449109158520787353544306072314005568369206208048748096130398603409002404515892502750290673741995418747479751482137832953570085981072713310211530856319601662696728362016906656110603526586588808036036681151246888725348033022975444510735864236520509670194925145427829617627131707723420472119314913620759681914304466502905662681017835573681264423049610322220092204729685570676039629305972535210222664047031706329959267368435712, - 2332635901189147538921097866276685011139365091000047255688271614173001172754025974596168442389463189970389994607110584819709810673521049202005085074581102701803228388286867236335897318664077848852790910520218920919417019330516626109613135584199356482566448412298034436813180906504438479807205381076232443623878062584852354559704603128017136421591373536990120490900461702574376755401403265890015363252960468320845696075839185506306594077890728631825772029264153876922931510948003669634799871598849088160792709663321636899424861410480867847547148481846945901022421017309754411196279769134474270716720713835009162753571576063859457152078828846515638955370707821049003073532104029141859238245689672949561065991279023495505430529005531489509212319677994275765732470244843200591419054829352599098637766751318263589623408788541443068765013639913838561193312175771584538457768863693870617290473381388236866036133270665063275637770514532180962030304480886675173980739576793097930092082477930296782432503002567638960141044973443807952065487763356345390673128807880255566542459811324770211425917599853396552062881162490287360609430264314734833745488411459536829545351393607337939397949006242534109131319481940669391399670679502807184125506737869642503509391514015922557149455994795229937375105572414969266974786173315539909387472821819352316376516014169499259453216336240781740430860862881179836913428773063591752582791471286735071039149072459390658329055177660879018096692248458046001844648187586740171294490046779282602498063884744625081038746475313841347641581219481513536293617401428246950205997171020771187674065558971818225204176051606568191073078380793531423691781260487083317291279698152282815578701896893752796610766885452333570444873024401593129888850507095817159005474033907102203520968952839025046773940022300712073343865264492622209430372690606352431871149870631047181187126600436086140139283646123995497267774573335527120153044535208370297199272846159985498666750209767957994543888019159119779266554728206207447126799327685311026167074959525448062832363267133479992399134149836159045085365204163771148391593922923677883912572389770636395226398861480546711993091675503032877734030236062992562793545312468424639766709642177539371358995755019016812244266490582511107936820904076405948355439076006626373799274595951656272867731813535458620729573411580165464738856386294154030401437199942195699525649994447841119349884504994599418567457119641346023614915981181861509655486473165022320143898733025100867582732084216488622167220448828280827745042875300312326930815065063993971908376784083067304461295365845749056369831502215567487229665445339688298483232081297996886206112719075314433363633460723908029562851496069584187430307443614495515691684890984254957636617945912336838661499185795450853092548724241215609927069285328716290074482654363457444888641752940881386628350866447124134324582261202919613447447768429804965097410706131052300091372513405875029451732213369873619390304299248136460269270306091966732020652658495656136578918180137578670588218681277224514902865929051140381996162434091294792408810874866772241519213510636196277352569665180116314810036404823385861490573090032384261099136442982983187799760546986009325888217602541702387873185939391456482451306994716678056160941409394916049878213417803987643001523151268711260312196076478856683084394670806509925174707152001290914948656163744785589875644625120780531200572975113030089731501458683599463055974316959219773058638356317641902390647576289249083464231757448526676584283891598063388458602970584137050985779092520599700843895433286675235151621858251532578517922228192169942052254036255510407723412565625528462535979602875943943928590162227254293029291601873183316367512732666995481911925853573107726524868806586981414172568642910084430207444088504215212864486216104515222034430545478721826178421281741679077097961868855087647369500960020950182691396009076488571808892059538871965572014429363814682466696386661155616363968866444443238177118767248134384761812013620882496039012655712718228994772561929165558327538315824526612511413131259762073339542002225565273636244453855115236080286573907963256037475403859498146763412991726906182104511268573357138756041160937974433787207225204037278857432076153118397180577320618139572192170509921959888722752510196864885360214088698815511070426918964379005999529427166674036587978618666963749573311224368890440842964064682134862793589824620141676746591215576213101088870104862880024784391446328996768719584676764109021664059300131456841426641174922085353217883374584501892291185486822158040210616159974455134209155875056518622010235034227575829415495028426640618652232487389440472862704462486889441113008448838745706435669290892243885299465224337622598315630998982456596604964789733703517860550708407891130697734185787043120037032176584483027644105038905446918509661567324686035397921144621016141968404579814530628952183785054378514264164263713290643385016232518096128322942717216799128538238919644164057813578869555179995438282663086491132313809879534229365505511272637929444801656518988330778555570697640833253877710989893895448898685119631853279167331828785775221101327523648338895005724179194419299314912320478601010459849457332766606517628679110948307227565959850647460651435091908960062993272537999449561982569073077774214311912513525532261862818878192882680915666935428229771223040692825404577545671515346355440139658850886845016803854937933674852863130559049996283794387879397521587286391229181829486454968582107143329655865146927350097616020869550262717454041678733139780832799013193988715581086914748350464, - 10901084484477388233204590457679684916142890350440309082868708608227789206746925638751991039983714220702138661667335254428526449120079272284162169613119415756319263431047075940860458924828563172366250937599402443303098823340402047902092189150888800107752652760321525193743897431676986127598287668609814860168170738445016470534091193086038325850195417718172578924309556831023553899743464647934316082183073350533664841652711089582462326914297962926965512892269775081079180707437336224734587001882226909364473413870377841976574780338871801059951102787620532671533762325195038629229517006601800417448190712732108528057310698637220181330296020371153933081523464397619670788761399798976310488681493560723385748437652358168508501671678653957591541877781775414895577665960179891795759009844075056591439174511052348780090254915183931598344068679060188311712211929150036449031475426413185010756037962779539122973455360656995025760631162119354760930184027037037262985267580008939580951741848139673828849375298780155430685536924059164019375507291304712810184090152350755180756239806891807335553764653267739414144617660143821674608578175923950586064607610624494079517615477755774394219776709181550903976033617897180982976478908104470407735023154193572177853209184905429866084173742469710660431008783741890411229263477953338501777135206958153635777912420558851594538519422833522593985522085827116918269577364854136085390138414813018255357256965691899196086507887871259879378933055655841059722111487527805337188696832425616820355013124377006315005967288485112328177945861039084489826291997333266896269017914989523630822486905385013065800367999685863677197477985497858343452242563829780314057548326243458497143081717412204255398136486843107243281133028168295257072935764800385804686979620023944980775141019020958528278670903117138491858462240504627072311061346423775662693408586550269962321945452163154717468131089936191310466892812849955762417037465518370750154137458091257789604158232101771800247088975358822462110256917701217186668125459305426486099386908693940578990919619934802130868879415867032131811796529503333768721609823029644826428388668572153428685781596240906428473907164663796054257838488182568399986417546265957360342711893758022197758144675037433986434103520066330640808978479112730362810690382242309445856453325865115771720541216386247092422352471660859757488802356506250042601972631442101349090793723031653900606950731628471889405504539822310506883568832129817927077611297078109399581408240889551418751606077761706351183552567223322137086129968275038823294899443121715806722129057792862106363758844338882107615609626715934291643861527145025777722700493990091331227663884022341074181374523909252371992996490192937321941594458555829759804449707753547865050743043276684174921457022365439314649902027848483884919814364302014569406014849859480434748201716762388203885874660509283645339164098761521264578560260218383991274500179651564290793787634020261413893417609267431689693998859073622831053435250719078440394545023182290491602889761937051385205974453605591803246508875770286298985910813236476891716615739826186121944761247817552750434560377107628651499815159107692041788060023481405030663810626543403548711037086813154286511295370660092319979975120216146711699932405158932970194671917844976267491022329638627459637387275664655944684799405240340690457581520306488210770070173326135428308948695166547252110264281814572897110465621775094386531558220174731788290911702285832696407120466369215182474340866298681541844688443847578492982216190720636720565182138490084713124187302489598620081299826866379102176494143625910858986852108495290212106163557383804489098041241874995014703047026590884561235579136148104915428072253742033764685617338727543274364392027384073115176143279545462512847066716194571632634095090631582988458146364098144031404748038601947126911399835603759885284789210404821671120060743235794652456567196548800923259691920564364770459213418129522282228721249005734373165304265941579299817217995271814244700671210989977086349370431409379497667227222548835878171658430170714090345329997984307076969526123078734068537369541094020915025322589632181085862454461341651533417908207460393433349514755317332788900727871604003734145333600218258477187838656037231152026763615947997635175363772055508378913787623550058854200470947090674180729610312487939248222773362370702774087674630427793395726320857509162493656412964803935246629289182505817695989327476068545111930104165681483453315699122628963002762688127984181736612677292389742412845037479273986620992579040836384905351671484448538343230502526902917482538861522601518803687825905039444634852263349909686979447200432262266139531777641630166285263313816440097308353222804586966893498788284929531205665599194443477951567548620696581786058613635304423645169431015504334650339893785277700522756397959577448903465278344272848899431286255878856369817907696182917303125901645113657039947269679355199835191519963031725404769812120071949152716816944600149641595109791911874387122273160790684960111108260521732085004101551351806725436643237718928274221778248315018712164000282001146070680745659486047681960382739290042238888547606827054902656877679497315212083798180048308479400772359234156497437131277818627856125088810804880175765218004508604781376083904115759076671026376534866017515813477965391765621611448292108893186732451764832957276362059534237810314428349210113768717046787883309539973893828331953938261155382086249745504915307391734830059008489737095036264576418366916850929923048129512083000164040557221374589092946808102365167616, - 3195676808310393157392320886337002897938436968941200397687673300685846202621427433433336740481731512169361365429756386238750646797327479797872351913265836912271006979554664321400415383925109329864406669657857131430748592668636608720504936985604191901211758491002502347966472375751286218963618480887963112030262218373395229303820045005894298573501893255471323621500000255668456628525502205530123953317083436149235710962851773353703664257948132783166975484307016463805511839388138269175664251203317929099624955156542346248465833748878416796167927950488499127544891863135975936082053261541482393740076085649445306571238445134650424652143000952485704952286873062379085731451627432067695732345398031134892794009981956209489362576258754485184504596199584562328598050463652237994715466366978677042548618548641241481150266606229698723973405936995296990141378006062067080609268406539296458175225195767413420720025515791670626352357331080907846641794036967641663267793240974782942585629556770120819949305319506368446956048859994761165634609301512856832618080156227654380924223739274804083609541022138441262330243930506290613795942725310295997684102644670706532989829409701415029583638810060217408965000803980039418500044031026167314680172340985167840233726875652895100981791983810800479926485309137190720226786530208129813597943867816990848169480504605878629688435563529065222061671245798935977920844773381119029012382925927830292651352554153414774097676762937796277868428782804275763248449297923765069854403488179519175171904473475966902843962316488172709958550633049262635840277805412111816108238142388410682001854116291772194290775483954441120533479750244191072867887792104873443142480107902314125665569090986335153474446936358560676461297822103726331079515667140358427458217885963423382732486207775444914352149544698290458837379449680948397729235979816836481851675506540080379407830794358074772604721475268491338711028116124380222732544837021205375364742238770000937824387616466009701543695343868671793663290658197172909451060550203473742891226128568393256064880176449884012613932128907037587336039662859139428870285273208949973808828461777369942177918626577095206490041395703917231111343368280113047433416199425657449811959375296600899685919803867149261426328269781939171228792852610269278275571002866357089234799720382229753406879709712311408716643608266641302153935919567236427237138526478993367704119895686942144668452448301682807423311575538311834266288391269024998187880398866740037936638761478202213373173540150407978355395064120968692923697228499848824997137009164178095568084475564228001226391604643490888048570544152936494974887208625789688298731656781196023743052246310483538358731013763356469204348099285239484002587036410186613619492099595696988403128409229178961518146444982165254117348264261119967992466438749231079626051497352118483007249448154270588869244419477268452412148418421928565802148210755241819959384178094078749390368352910732350140889870255327608191138124746143177357136218419229950599759359955621578286698343053889656430779445169463512522991401064131811231663961476407361241776789732449275876807391770057115815034432278111323198995344464459970826994545355870539033884373094806884607348961643619557811186562549411243117904137001329564632689812443453760516272404537170153212107514726202507610516892847384655774925041235447588354665595588861030939636791489717922419566635637483551514819392495105685307240837755028522160191337628124924948911869446063680064151810556251434183734876475463993991964138857471224315687151289835332685893121280342278937903351541722458700255023739696339641357155007447220349304944720143809652199180970770765940876509569638078148417450062966143543291108213202051849657211883452184857311418449513382831384264701029070139956815846551325524446648154204611230414959257740280324844874100386239023687402494387437843391507851010194320002476149544081250080525638884388861539744971628794324275024152513656813066129233141565095983376990471645613072287345049994025802696197987402319576316444295186548634368850045863332206045049769663915360792075394702142248829987418461473486800388779545372398137499725750091543818439970852031411269573210197830066993089659485567797329286186137272335802729356437603050689502571054928222550132547849382882479466381332934087408815026114388716495258970215356978258324600075223626156692121625907596847293556946220823010264041490078664456219595988032273506914278721215249890402734188300882926991630262232462895778258569446214190226882262136567309673157633420235129225789616704765699256742524332954285742732082267326144287545945070432362022747189106361549482753429021831924313036031892779093517020268383361492238003158241059043110434454376607806426058697142582946199923115045621020008713843519291352749441673191575447495154238550473948024009344562894718181658489047976870521354070225795108944783346438404798874567933665191972781359682266484629646837734252564263418883398145759635897999430363853259120940396026463628295548997837971215336839835391072262687973023651877128605210578639734569736704552715676339481444169849970153801398375590331325162239108174266391968862327386479758254021985081827179277685314006172185456113642471502780715062705601898656425482737666366473289044021670049927579419058424890854785508346726143847108409000507196004751794147097013301956560521129231184794761686987302911843568251851442398115698838385247518848676952756440893267032310398283646351961987504538049228536302406853890860700384318895036400972766067324267281597165613006313759113040796734472937540825532631875584, - -632649907249186876774353302176112493817822193424995743463189120752271041876790128301725831592427841874080518475196430417706526941643612101410344643202685260469118937177295298716190476865494432477431978189912051528874699767273603441224152226786670659105798942315628450259822058015322308525982011044283158080834095461989925209166099829402879178989441727220957739151101764555819223327874822025332433674442147996105997099355924124439118075177319857037299256600311220625214323904086433086115467875902312411628725614905586989929019173183570680783004134809622009814659296047900290757045476144363949305870945461830854366669881462914489881470706871566336216979158664773976243957103233711222155039506858969702407742689949887069945046164019171333405491083495266456319270300873836368527168115065378555174186761792671594050063371749456581901764462743297740379721390879672102221507226551731054484339248052130418919740531819224365165763751377744221380246296520525377089563511042484654754866958212761248057960130014289986871301434507435963844774893459273562263352288211901533159576761378348210017326118549253331387962526452226925662361738262640968136391523554370467042172415646548211408640106365773168696755075625737777839514108705218550665796845511425301276859129386233393074703762861804366866793362353040341542090299338351719408286255963694085975419146007651106479280267818091952621494372446249485558352122502784791806969563170536245642706045436027112185923277560093011615513884485886634165832657379090972493280002908326113643744494339338231138639653443998715275696841856175686263156437755732074563730303816076285080891659661664476440897297712015104794770592598542534645262948135878583590869486418710867758192882890264833540506498751161741712427058151779380560250931834192737172994191268009512190638733489450467150760395819881097554269958520936698543644809550474277561941048307683569932474686008023140803756668452242910944412326973313687519114128402606223263878323394202880978494245535983256200065582386722299017282497222241929139417872647327627742698335576425186114947380083605224259715512468571305700156606423952205807974398137627989100102363671138287893624943132050542886702924319295761692341710944321300310314451794491573267777479312982933054563719702556840215532937110649211477554708072198484021922792510916745283419687803640073495552867604270014691042739356727066697765702605847655474728238103569663478344981722522594588617096496683425300469074292993056376058044257583626053901872479209434607366117813071934389270820092481480301406550426107173806952817704396066566367742185953110183746389664165358354953271573763609313238359995126743508770564147100050886246673360068872558400964926915785478057092963303162657029130107668713706196174843594526976156147992150239719535140986270230321862324520569389867958309801257388046889162096322836901592825012900498962383081732050688875586524629266634191330243516026161345464068469096846612451107476502106277038358027276826035445051905797197919855315952137581052686250468172521266597364210286380405876185799092788287922712851629125850999563800123037993809760376126861018344998362918095933704396419271655862249658400542723760154296864740081671762367508816984664498344408603067002590339996144880415953080963102824294843708323951914465260203090490671970305675446583499722243296321258197345110010808123086471309332859798513505391345746125689649813116943558543056715002700132652862549383246043083228556861829024331366103208194967520068725913521214080648231547864787395659650963955287743224258049221304636393879624263073316797061265499603798888737707283167028976290169287123708704339637263994578629099186708183115124056462712565349089560946848619705281190801218636487142386487062689231838902532820400388989242500802802121842655226225613826353596499051618746353905699786514539826338011053602745174503065994971457339743243145776108875902199597228529662192890674528867606752727922862257761640423726497127045117883970360793788920997521569639015156553847612724560283147430072959001828934419514610497372966293555311839924810729856459298552145654983065224447116462418249219840307053618996157635684330621234002326363915334166592745659462707067239319960095835368233130894541310517002382499813226612437165115325628894492898987827190827548686168897746145165607250515081789366805682788300652558817167535710213985881026816036226711530249651120078022556147270338375724831943196159214730753140943151064812229134789565466555890223780444785497064949008715788959950681213336439623550543732239704219634115643637324709636356231883169281046522730046903276667682745223766535907690883892134759525055247439955022809387575809107665832833913829044648155424540504446247647811175338393366695020411475765055696528162906684787718006322599092794324784581557643727374296697740417057321954463067508317419563049699712073364670383931305025510915279427252690800336308992965418332558973241178932552282845030279940855749598939699391182739712509469593456704924398285954333702722546331557524235031585822468133070568111029301405730153631112913865252684209462321430854627859449140348306331324406986346531075392045514054266102133184912146317712743865886537865674572712075373232461083441054281385431311709965530971608624799722948903860470189462069177121234773642016783078040662096418503281431058848490750590783157329175062261213643261550860871583043867450561258672372134723708871761101021326562997695783299208775840128441696284886872128234956423414230267320024798808489968009759064582961613510345712885796058679835114764085954904997435610688301039616, - -8999310034323268795394862323992403941587731550864046521001941573655481479938928766234406659949993463524236770446223439140258833054896414259325094018260704118196501263050185483758232123703100777105372957693710033819604866914596769987181291845131714234029443312497724762170406175180200626659942373956624989923870968081416024477146375181753661333190134516161049450001107354671662704042797567256521792983764287995961396611338131699053615391750472452249200863836922146437939490132021509792498783699078571286243012419453724644037895186051295043867785900880696751943411520138480399322970611977547454504294165954883165570311429710795956841744138446222003422530757504379311226656749484916799903306860370321739707164698318458649957218039036408838561023659578290050105444085422096123194738108652994083005407887632248119052590153109532800742135435626862146881240159177986483793507572124317896769267346127898333331017558103054786069954334768368429013193278604134605051951082843160129324629143373886359636046041490908606948936276120110307346228273472099753688358457071407123431413822166910731415134478754019756938288539710475305515102957499029423468928746596278172970940837330952325726043030782312330995037668374831359556911934365051896691714086900023378349873883551520180059224462924356386320652999461230702787756980437034544873822676099357405656692032277202359320553125855916026941769807777938273612025162959377142711825512951665229301057935030408975135356884340028109087794242726668658781893693348540157502031878100311121628541624155608136452584393980025203350750906734668728281535157962682534173228484958797044859090955972518019194023712689207589198957721666247751174768671901742137924994389738607010045003293420709297523366884450375214328605186760335225204852275052193768577221131144046603905723605124596593502203036307367557737899325547499302102970396545507503546356876082643614868966406589321884915271465988356099724401461815203609236330389788823902620569841710087735357490955571593080183249284559390941646533646757413657057263817548382843908066927034653895583896900906147391566528341067149214434891405408353124086169552426044225664984644816641428216063818720927787221024048397421523615753571136204829235199870714953729801421313283785002783178354137401337880686343570116868674782518753634712607063336841900042188329923849564167902006019436877092630728626683960103760142958068017567858111444254303220368649112549048147988731791346654540624181862785566620568648483170409155151402007274141459261082109104765056876758664987424819266944494060712491073081260871015487968789846435055556235020147965039617442970957748671225333422610531034952978458351545358710770833473515646189652276224446836384542082380068794005032360011051543821303893293100136278908591374989858076183917548682577637388114654855529311905370095967094121578426113780993799261225576741494338362581217868127204679693862545869185646407091832776744753360914767174042402417624959530415253587832587245541463141039189205040480777420960034571124491292565015336906484431407612741079079950511335291098516148707777331564887920047163139863559612155148726026609691377509409573058176795850537590267747457967031552084434128429747356955203659160797671445981288920505602526845780840780678787684383905980781011396250249635162602394235337044203390916550019180572209406351409245375646993063567924342983545715106703006615093634114517807099068516365354983988367278422229845463434286788255885910599372536733232542977827820017908954875815646977483150166255672066271805566677393369901218201696795582295690456894951449221354648087008956004201256620310994683144457336740274432671396244181094450933630980251027216911323511554505370636497593590590890638427128817941569386190118145953529950945011057439319339724842235691933806001056151309783960333314234240859619061569568713974212112777451096941637887192917584273948762385164142603805227728274168450702309543844819646336858291587305059502118487322952168176396126005432420015843495716077842627050701795924024287899699794532565940508014986379027959438827133106066528507532324011962918029336864653710151507943177574290694875837448879873553584804716228635753034297918945130390417004004176115317517125433039921139627203838058394850592566074427720877049698442294710068157917491669279216707655071382868143664535401171372622257283159327297876340470812783915562909213892989931229611110631797892293756123996260678826748978339723350189141970344515275230698899522705380798954966886884115762843093599971318915132938117118182930710215852445595867286943056408531279316579333774731748706151096696786319809823074917652793064545050884188116527519445932939038954697542397524734184877311665016895484389159111380554227672597532598408893378508171088946631711831968457314194464078711021210470161483487927704523856114069210794770267628101874937787284333275014393451485116239378331870670926645542135503750141222579816308229853370919168090909316561575312067048466280347033041466322448888970403745967178489048009589603768844024308136734692122744801898768410184153086014320372376250453551058484166798012955488485714146016063288290702835974582689766436573305348344362164918995194793776876363763906701640350612064475997498493418572575080774433280838637466348419470053775225165603883473752997148330263149339328236514368348589936849596164663173014812181575879867072336789251937579570635315606130302975855198200535100134479837627538780146523366661571638702173123876864936213702771055819521889373980323413677723129844853818989390687284960553631140255239241728, - -88126491733467523682023518494561032323642977417563370713537125642833331833413539112715180096492374669733965241320908007874097822180607100825254415898344730538467050692614540180315481353135281665191211821212861618875139318612108650339866486920771255596673668198467558890259780285240664955731371111035592773077982603269966116204514399183234033457866015564216638418955299480115009412298100240690260646747218649381099947470985648155628213742593002581525252928384138623746302471260275319610657207968275961177427322252462353207463516287907155458171971991848757408334013273553103525225567718842848316168369721770210739520598212504328322079288261922125476255231351619653509131799558543648735970997788534570286902010410766378419715833216158633330805424175009449527077484337189548318530559933621805164802601699869202549856274224265769251087674505877783861256624369874994507574394590355951140218199939382951002590345426825566086788917864551039663042121130958529244862679207048516581253167105516530164239410129253121383708129578580781258984396383316786417145663907600132145775037582480826543431232141397429936773904603120839558894574930753877510633203773702279199735442111217704427145800474858734642119417881846935450930312722594065774827020536581245329899562091148600727289137073665002330997063403208456159346091471096941931313290434302571721305896373230355678315440691535530028320817181280537050129646176564847808154848509931725396071207717458703814081616870687717017953825409671228323758484573869602945952264376346821414163279512003767970801791749613055312581126346993408184622532586850092105554539701876993339738417614659277679156421300680185456304583529968253884757269408594552646071837369889969585060647199155918886769447685250425124129368460163408265208833908840879965515700395470467405829469353263989732573360316773553710254615736393681038560101379909038196798399633561332160216201986876468354404981381384699243793713630243034315118006184469336420478157566239157473242876264377810664297206993349558876826555719885472675622276680905623467038815001498421582300948040579875344759928076750237897706729110079402348471719268046958964887587230438841408214885776685323051445544539392711728130861340050572644795396720476479537660400208901855466718634098740434222336150975520778552338481114288503341702934592566918752731758117145692662313759705641611658946196469393188386535130404788634005315584636671979615192230279540459317975490439177387543938201136342362898479331991410190151972054879147247217336658805071882820365570981977422904502006185894938720824488099204756111596194053925626317548326176460596777364301096792326129853866793329939550773775400211625405185455825186524964625162304741483363976484532900822552923777889001042713777461714833291448725108708838947741088132291894462988911730529094075040166657344933856642369955559921945830101673017543115899666882048568474928483823071686939049218946570423511740691237377160813877094418974069786347603521589201088758396631224534096766298769187173231828303510105319717741737637835057988973704858983262899622941249218579157053576299466002070615838247799461261482800208073759256055082848934598334152777293725000417536864402788911905017184764711294160236788102091927628171118676222965643281606361254202906652201349955308620071773672772950168023333607393007324484767136844500950274354280873386806515487521521813010330603927425028747219960539612285369895751203625890311609943475307174200113808161688253075220401703252883894211706454893018821006766559402068365992307477333690387338091981032888374038030343065769781725281321769147454293840894948959580185236849398543023891023824154508883861153047969589018244163424314228941443104455121585736194429493699588830447918737104838057012244208125444121526417411299362297019092971363830581045605432297499036730644784950332834100624017713910563134859325398959656189478294414349391755226397730245207656048358874206571363490943447734540757063142060068682308716342329726072443486694153838902393634592989077011648096881398124720668581424277741925538506157554453086886263102132586655303450663753306563721053369617755766444374288090343528900359202348453419400713227422588404967091053774670014853157852492517960135084141891759584605260774997812557831770817988825951578504163943367618309990270208986394440927474300052739520429226749379194620061580638089019275346470612502695915749144848533051796336768260286554895088822665397422297745662172543625926722364798673098841315386407430061917439104702406327492571831889972594291073524661526999306907390857577970657329207052103216514611920663110766138631760457560873138681296566221980156205861051614144002743512137992098383579063136533004049209705213485731984640611564872612562430976227170045947975293406032456230722595149938832159496891186553887946184014561078263767799300567789081043831651143948157868964824397925827791646440805668757847597939856540573243370623573916425693425391275689900370570807040912182524321538814663496125601562917757410358667078952195186031528730209937727034468342945394075942128772844026148465234274425348784809652912557519875876905564988941183259942166614238820837654318881826817415662720595783023146714140501090033155001640821830368234317773024412167527286845147714989632791690253745346633044430210435163571203481146214832097825267466746847129416322446399255489967243927298910665271465482993006328484385115232145186780069000253583419091540844785478011610239716018721510081848415852965429710360291844912567888739505066028113113418261594112, - -714261389404184513094766617975753296582182343622273866933029495668442027606072566018350568815562821794453922435448152793515619937606550813677770212274604971554578724884380071169350806671181254054408077002494962087375793954517213467430323029625480262977445843109889003648592769267438415581196240370630823816514119261513181742068663246792591257720849178436587985223757126538592326017940676793994617384770380812438663694257367594430310082081771391774645659163073014167896116875439856473059517892391461265394286596875981841403587278852078585731834157379789337946620069385809587728693726218056212865584125867334849601074569265069993370386126422521632133880270282796201482470094226596542562126319186114952954017136857830399006621769116570677010254054239721098063203973514142142346368205959939800621022861348384019121932081440636907848667213456044461858518611491703598489519135580109492842549949824370902676812464206949892983612501877594195469700237149280213653980284270331939104050597504169321222086793919588733829419975188030778834120349321496237498398599688215786657558718508900544211168414820615411473454311273623747428919318254679957357258578534323788435548511994888557760757062147616760008596656203236566648299128220959130832945960123683744840914358673527043490439515115375859445726351386845795980470006122993624984736114732607824242262448012882665404159768434305577111387128997260546936905414185747562678255506104863064312816619354697633794876451859924387789800936291802331792095520104035559135430609485154000953171174091569294490460520155897928790920550696613540420960348906576100755207048718546080107573168556121588224979184211861933500854871864265445362754564359085295872963767658535813746501783450494328265480113399269914352677461950628258023565978717248269051946235661166090098726096879938005007293302977779469090967978247258733613786883147313291819755695587237271679327994382973692870329560490906609690762952617327007588873996484329651981520071091149585162654255545916503043962965164934662923172417202774509123537414525690271392291072749925388279607689221011331780302252880075557091657621503200028031733132131472748036326173088254382996665702965261143996102806467761716668375480781930272887119814136974015588242360747105178088214107209468991657312200299344920882734083224718444535547371218416784401866228428376569992775161743779031359581676219854610027945685706989866704783368468883483914667376294104024825958249030898494653048777373037651606127076675120131476403289284903261130827682083399374801730133576507593927344594345395987350673421719853824350024730167897699371514162355347755801433948868467819037914165381000725047945178780256065689226565656608702033586249239703283761657599345639464479521885593040665313804403836324196207397974040595576179556521896511854941852697673874184534140404231247363417032556872492497934227797163625352507854825901001794263369635561211846877787021089611129690322972065810259466280305876276852657831168967322940866996091582084523490560894966906599996230127680772865018027366280564963930669167030889954847216376157884787377896862335901964070526693909826874045631041855061869842648634810878515924759031962819149834159439469102494806470416534773333985088791429556931177332163596778122783299986172483503965341677643667611977346706566942791832653384848946942311447840986064129158516286818634489196368497086704371131225154655607922518105284347857784550451788731500604298474253951246724831860483487117160250773139404307696973349863034570421456802090356836998295266462001223773469787254324899064372035386988969273274356222429612171282867237562034232272996138775142746065475516875324117178272840698650776078876888511663651185089223716913313219320044165004265646672300636460342793462337984638546547807835624142513342269870152104761490116523570593053021828509368882046239925233546452530560651759885900008749825981245613470415015259014645069083482854189041533625015169350523210881015891904084658069656126091647824093339291789869716759615093569365869735768188993555471090673509671186145643192616991284668210009737508449870752111063776015124416981035255413350829761183017835359878285508736275694197178611997020186366323622924115148151648928945713427213779580408801565438081021362872320705925654373808412014685485732473340783486813668005514178701131987072481798255191907693938140852398228258263656554389839312416104765800926273324960137595756127542638927143610017608270782981256517349878449978080981019098016456936213352103109864797304824412868951444355446385160597894499004797473214388032270588313572526665513676562254403889123010560116097237697382508876839534010191507523274142244581207265541957467966472710321919056767967239341917250664841343275014962444274021773545057499999317264472647789817469214364700019832039178750758580539218179924008457830647800998569626228184861377030455221507372204060755481085333532116357274457044056393384639223478362477367280201363272135110410516334807083047584529736667238352601639869303338079489098099905769011482890535464441207575107133536213843655685980896856538856688938795399193241535849910213743046492250198356522184211548096615890093141369619491517413583641315495964727021728817003595628150794958791462888787050700052494064846098418408407777331638745036273185861762450855327278067782864158308533938780408552634427490614679503243047352944853313253326737146880842323578233648997663042369389979019593304864623752622793926037228574930301481966069511095600986485184696879056683008, - -5080820046782141757957794102039742619165030151778118140798604068406030706517446134562954044441964062070676107647179085512968641681061287970863120029639470386306424893663170093216823437956097030304264508030035411232237898010535248725348128899441324836519442160723842622001257590693489524288280170767205972531970243805440549435022919017834866252864934833057496180172878237470915496164929949158736699641693427682664096385281386855165107314560581749075840668260250257409555565981791535408519518635449973574574913126594933725970387606710367653845527240800685370996832069501259820175407672665452536705170843320948512895994032507809511821089876386724073716059807966551004829478398558008346685798005330411651952175846126646176597174305263021648883909628373323910088428964132012511357936787923499452001346715235358415172424247882943650283828423882414023011421004447219201083207466280569443788797325648117220670996599876679555127778032712790826514406150345595975686395384595252956373162951763003501377271911725631049089563397513330064901945311284043422430772324124698614876513102695212903755562678450580787373036355230327990216687644005983346341548317865645038567911200626389439426166505135308411662248447273181835512236755449123478715178658090747564984236218922233746369268359205745687950678900890137845725744526758537594945918394063087644617199808114820046608888019689823353005792475265207279992800211771796108216391369194995970607199304954138627756361708291360854489849822454010701936131410286215641067960195621573491201514086901780939071445001215072657104110153962163226621543769179893856620499206819731069342059310839976608099430343143016177685050668058123486483751732083693221431409604521516301353829726901030087548276454298030928445286924800294977496417120214625883279265973143509319876617509468654002921795622720721218676747918009470094631345337284567221294457762767713456472219133962780987467335965958557649381382757667281447845001635502167957534670066772746838221920643045297632262535599825687584049553322950633066899550093151900757600309488380876866068655163769153224844393805028664604000779450065251599287027183801502543712228880142008757685671145544323697806600371845961359105120600525116283278022348331182372570582094207056746104726591442829124102717868023022460679945456104672631030254994023084631309637046109309505884094151423662609308766655664433313122685650709797726691070632912675256768046009078657679808797040173837344978025141310511390394714389898530626197964776188172651253643064161029504894452547499454816320982564394127476752097066981974972467284192955194495582264886717174253304423656505176115051638243222423843486238472985902288825767862432430579877542010584720772047669063026074936994218028844585852822070714995056639060334227004138666344584954441223703511925846576240005264520269351314886710448105377714326290436812057169674833069827804336886852631576916445544654911317523079406385280637603130502669323164887517908852822307581947397521641166826441705829373711591756170069643741619531262396758465542717358741773353296938399218207847923932891889425845522340303566209970630261788749466596329688192253119173652504526373209473680480656032333076760392362655664548599864033669604170463986456801626626986028522990806007744976808722261750256641382923033276893063967395563103729531264986091791240043605267740706979652381885247229068350703434704642967027901022937194557826129864419972564389834096738559060572001352530686323515682351017781905305587260951771791350197120718737069598204594445077388293640365833209609873004573112510306858476882050554944637953679304553780781480835948013319961984341188943746855877864668257975816531639263829629269307912315519557509787701750823170781910438016500985229565674628772693917198641108353950406402787591449441414225081473000322227753666166520848518008109316964229785530969447554059687464223498777602453739567478145436411564450572562597771308724572321116698023869144917621972372861114011407951229606337637421215428617000453402196426542278256704653864276141183630530482065821066978226658820536419358717768730404179921703778489722984769835632588604083817940869587570092365312885110600368752731381701409014569570727301764955744594327773906583241180968393140887839978125386827366787861739521889100641063828268684721459096459130263480519422168413660923630177619441910258600955765806434405110099798919376893702086578422771512529691272474578649921041816535664471058086335535654528920565813026266206465078202326040806105186693417200258176484840010414382410601471783985572514714737758119368887481152430738882060184386545919736527820506233410700823106402361775030443300459664852375766016640505901836793245122359999347909947238636120009410404501722103623414243621139193297880696846266118798127385459713301427135102426263863402966754912071698623925622564626217420231166956069964935264003825031932817251193573594692024513004294962631075797440463184391132752093569924632595009949328813128433785884517890653335835527915027677057853802908261555158356015772811704352544761885619829281400173908164906813977353017777274455561132652920216911268215550189648884464144502241834216578004006272259372857755386644362893347359734927269482981882581064685063911052309028588651471752609759761026642043052175088134738503486901353151454740548813337717860660475166318333959867483521576402643622580046297167215659505437738606056013372862813531130799914718732184724167910185941146894368763909983174656, - -32589205414024649746662377365425712159437558982297207987080544926827395736202920604992186345645177519370453726342652903184573090993275723975475040551348650954929834993423465393368158030660417200970148459531291817630656588982763441032535717324550277062982883572412692611849554187353621723052932976404784818144083974437402253779395584917972767020986058147299717180755078750102773856398634648968364917155487190777537500146830043032026323320888455940722459550580249560906700975502204903312153012121137698725959589950913815015871605668546029797661500076812546170708460135266322375675394338897967750260000702585085179542303731437137176479828011301733347694822721055503368318046758761710028395680905352641308580192248764900211232552629057019072883699117709343601075319892425956551584461962747928659874709310733173523586644605617414275277595181320677169810495951608223952954753672780401581166444743445140337054563209372314655518814189581491458097714109696752189003847989089383432935159015933931851500127155741695975610007443376072083853408953978459454051182529108112250581108218285105387806459487065705518235612314578426149519771862269626532108544946956023874413093218577440081607811935515889322219217775206641458544626102698876160920558217794497512643793545928093025811114065538546500502805980176411314391356693339875556231475146871084198589672938200512791339852867871899674877725953556434933984910019951279036107301207408696496386019326780443993881334601242841455707084477774303946913952761427987688327494673361415734372538785228516084944917997669110013356858012913312642932981379266425623801092472566746179777793386302251053372228906597341028890133412354856219270525989423100734777764871645288569912609471759418631863538446071040633467649944197090015452564792283967831935821595170135441541461171617832844467445731776377929643069069359149356513778827256891452149474345622583305317909085252446874052658002757531095874096294709580956847808168816732591015468545525587494421283110355321966252058288225963426427778986315930303380212041927534199283459366824982999464887638919718089889244183205201139096207651574257980490089879920835653904820185141233836025746454477792834035860336487106933770111858271068834829482358422783449851305290998680146143662527630099347634980661338298686135813672674399497770835962834192277407558896306218795904416784539892953946450227456296820790607195184805484477883225538382788477162542550461912822613859268041038509333040608372475832341715600961690116577569976703814556023048292500859646950656089356785817218960811735278271690469476594442780005859049182919155904365368503781259165706337611238545366953447367493364056305000400317135675741510987427552092216434834932848484973433577174485488621684857942128147842197609794212637650699018560677412502527764853400272877537482178653236515804516282053619940039268956456976495470400647812972270391960940117143327410751578578464013236617747102804387869422099039804521875327616784723396080290297490083396183189353630962028832486112563240959908194958143205363928236770134722827820316357999862626023702465866477626989025552634377840153976797471762136823505212597915383668716379275321968584236308055496692547519697390848434234941820559004401010269210301247400198967514440691599401988349905119078697709095740875761611610988675197460152833059269635038522507427923942976325160834283077357068912282135662337694840654348184446354106883199380572344433928620026494945444703129369654245298631406147366300751901442197281449955703518728491256116594016316646138990211450118291572705634129689782838844801492441431379085666731651630380445806811735120507905040349405264576268903608155866958099446144168141486221041361962603330768533451895636475447723067309296524301834978116536823616105271800308647969219920872916561853131190972086978271752495029386955543208407868564091958328672409008635792888100083031254588652145533620246862110727710163768430557017663377183128655554870051106627873138495597958110770356218112767808238700637763490836225680575223916193566512022647062174979225284201705535926009307787169238757052236826068647376464035733152031102192918118228694517100980758824100275306608266772703468551485985545009301377060306896478184282075948552518831412837975438086346902540138182283715101847769616234594219645621319056221646128255801290860432469561358002536034824227781101382798654144041406310099464147559576257225761916377367662956208326411026511444298248191499509405847356686036289512621684939614709758001568019432593156918979520830941463263037779106661582698674484945722540027442297476569845086829766459211011468657745442337448587699990622284373937548523588752876347131435432999550085624325311050011215124383442654829571082669134142481494009196810241401944303941967451831286846874841238329443580423540151103800472017351977653697878378688640135607002395443782727637818695844312783889982375220887562890687659862786908559882872383242288927179571182243574462909368342446044479272417702771628602644748080684048054195092436327969391602317575143283424849088487462868161156941097111179469102303224943128259691108197218763067521760137997410295551689870143014073932993759163610306532498069389431687939185662554511612843467887273575573254048611211985849435452922252226250039099194960098761289117410973367690032779650188855044174160266682592952432303562965733664168202112534906075828047254707696889886269791227754682513029773205479123732762984448, - -191334645540532146747579465141903203274274129683110218609542870361775623492455789855113529271335368654540636074598265867973957860291320189053613605179304280614809755161744302661758430399929682162890331196859533689411362959924447161329712160476452682594524117005670194265781340644931942338218350598728994101205523200398769077091938251126841382963689727512593698933158772024084211189632100576164040789664997722453055050118170044139083675042794075160254947398289286137277617033522770583559412468090795153670550037588570502192001739582207770753800049467837769394918320978898858134143287266933504372259658487837055494558917773678507733909913440082638920265751683632014979303315288547590265691563898619979746166235783102387771569285354991330931171339463235260177295816615532982664845814599163458376778761233114655715688338824960912778725826082013187737544884723332785448342633521123713170172099786910434184860957083830875766822917031159419917420918588755844214450455687901982039439032279703776870399535912205571209106575574373579234500629712249103350015633569567497156802034066053380712342757277497570598386627710719599290297810864905381973231842959293081702935262855320558690974856987365235498543351977061327339707032739617002588317827038451648592308457611234696278676323011079850868674318596651960199069454420817563550623440122981290276475928312505787874907079946405022860937290504931172832938273048305492139838210070070639232839525393402329934760770909931952908043515307892334503370879879827522938791146876561342010784015400396038567388526095171345133758761504943751743651944629237135440082987669048887588656061744986573312590682201745515078220726355504579613083466525853733451034541069560553180468346887730820261199518378213173533078710946751799977112550754001220565799760588830629986005766163938906520759536701337163293161519390104766666480165690635525441750919627817792941541442170157826736085908788603014533144597975771155011028202935787085614573713024676501244343254379673536869511561614548062273634235035568573690978050828444273533119455951941732599867760944156948961075507392459161680511029039594864153661044141782720351644890495132525744361938644731650607933839016768882420474655159938590599793859836595827418173583406307673089088115325215506588775521860047105916705729780640917494375680095459908380649551956857974208018953527152761611163153887835082117202764437780664734384130988133683557654258685754252910970442033976197876294625177720447915172986799149244777724464087161453446447468666405394662042459538755783371594577800308401262717287461612491517237214410295365817480981939908798345336184349779977562301920868715107942859940073511035707864227161655685943953109225474950908856469503682801703411587867820874009927859137116322203954981803313030233456718279218897799121850322831025895968856836548042098763876466599817974824876158360494826888157806955247767644030163714356537645203622016529735972325077803369099269231390264171325090895361726496270779045644571916463349658641386126939007321920948993247630077239556971658367829520100449140714703563356281243146368637653754488757240496215022044049777709693973202166000453859265005590824300464367869511826832363978326672032010876188322823189268750528509284014417732940676596103167696478259904211529911480502648981061333358634267264776826548496533966040830422549426974845638815593373317473645149103632306721918403762023758673881550575958699544223870744749179004909070853168394018555581476802895804658886596528156764525067709469139028700405715413320388809968241481933100352973226648137629980771955620944824402734250551502056119273458582873474776873425846833530800355202538363004845886613671992757572990596337945073942091338441940562131876351793624996761262253472349890331132973181783027763768434112712413570758514618928520284435357851188115204889486053818871979940667619004904989915683619167139900222162667305429444711526928275195255148615170441942153066293287047893410550596237349905188289651767870863320439908193774385918255701919678925082301233567225073883008491760365629969038518909266668297439209755020638949579408444096545346591580338459724726838571444868149418363975645578206295395392815600861340052677965133752037565459307966737014029447968578133194084683537209030545925793522299936584782416334715049419508521016205187761298120407166520570071363260864020993825476615507079308184459945418212277542389612910284764383712017294078405150469306006745199646949520502956508337228359145193955549782084450949749084287518902440690232071139893012491492710461921592733591165150443980688128555056932053442142425320967344814536558271968810665399108769357786339830272499504194247213941575149339618582300393059101184298581466257744038088010975074787173838341743046685951792112219862390552255892265085752451918410996942039052765581298332996249083718967181913364429116962888259479447142973335129829438891391421611523623275100614259949520067015741153955236218167491684502184753255943682131245658701046418621379299300647395614133754162321315330366993463498781156917689772520892630413881347063598817273095720173352220071396298576225924062388447886909297605469625808977479969305473412785396836599926739891977690285337449122967799753376524377572123469140528780871796246793380509753809552501326218996779943802233660627130315074553107494886700012989046133792547161041630629177248195560105931227260905762949165394574704640, - -1037874910456692497973667491083059905331809898161226885924821886579789977053731856135424768388206916049841916111203219647890683234377511110661762112304423380222755579125931570710172937661346901466857860406080367296132904431976395339136582031126379751476319231341336514628529176779678033374047640424396415160344186720399130208084579706426393318068722667059436065829444579530505643139136924903010554205018941079384632794614698272594172284436668309303039801551417454476047998652729659445320454647314444231116493448219986648048248427755250265824794984029558414751542826096917079505357921323993975172171808436214844250848584945985845858670748585726377647087652905174750226654619157145235404820530066525791719152513847276667895011770260171650082738409444657790704964865728490356411495445763275946314248742029724935057825136920035579850994460357202083945716177995079156788131105319008134211223951442330032241903114122078217628823585523131147601999082791192462163090878155905791844076020710262550920541200196194645395465752786534513565144209440237044053036423688546254007272427749745962803180490507668083472655398492377520031563317557937751588388214374595033140667788379034857716750574648483722489064197370032461402226422854600736124573887387550506935286163178891850611989248589484674273218476492864237133156461687359736310488663430906748897971705492057414589865823835145891690945709296716468150833955990990691136226585857865504495193294336683995231916003615531884507169834797653249142060886444538816794516093674461145782966808702889276909103154755958936741392701638184416412658073286144471944384989685929842583895931600696345350327376988697028124193113960300178481138997852950361974571142854189973136891076372417627811690116741646259553651912307343700236974646134200700075643542647032195127506538036394928555668697647802332681792027320910172146080349035612568008122251017032064882632242292516277639251301437274855534019619443986473103107338216476591587404654338870414182718132865100827589266911870495975019871651856759230273953550893443810854061709702511279554902455837375333818074764687790487773349317623775311415589078112885071789709667825401560501863858317994589822384261794041247494122491290501740698691041574807008228432262007836949183937423944047132370112516747692574894374902792772001058899291491200356341885589150374914433748784063503132281793828554407222912453639738688567784591449688379209511769373870529574445376037455246932279078429498304158015854334400900768929825832905537489671607594392380231701814736909798812593026590144542737878841945260415959360356094276189784623194653675801147740869749661984956012279328104156047069055566983707129891485306782505742252935203341134105122399613057008700047486317917742906259870660255969834440848761474702664730190213263662651372324746555410532801602866472860082278392501890299428430520476836721671913482124811617552273982625539834082285238432392576979894820164297532485338940176373226688557832551542007645036132550745469481224431205149717904176178827108809969332507882249041269657095582669279839285497459093498281347770765450672471388322756830725654290107932550451550825720909023145757450419831841816714671157236285405777007953010643232257562458630442158818835067285221923416423733715144097012117175761008397298123863690560334086591536164417210335015744278494360764797838290602660987408187609756729034462613752030511968533214210367931740929839928889532299992701729206432585743804277053016057392948348827292013075153256688322517797697617615978897100188129371289731273265363157589718801558435582523982806938330501862662030552984730064469190657381587349527391282963341209897316063591161982974404643724144003870422832254369890189575923677902210211818535709091858421190530522581595868466270194999721272453652854945966892673552447868905434465522336001304348752455916100987690195745669776732785956497006049942300344235010791090617265712262599328207923631139255243122824212368603902946064387034956211236006344527857834510321484620325446310436181426673303325728291077240412718453441407702806337409735428388172164966145873834558410335537526469821300049800130152515549015276131482478188547783134449114177718847630369741337888261706198911658651605110302313281492904886321255938898501424828788521260001284885376586711637010599681247399517247498503969795439738815229455728585746524899284190013380876832246041237487876089080985581422462240307491668093071514807305727093179452982266252479794912341158862258022321844208057240011945516043061259197476513510312898998644407802036131203627191060667334256867238532155366732207284423451174276150083760018400656526443676474627979510224002989273029671823800448787933856502159565160301242613903008929509010415720791857342616058524183141843801939827781318581281103569692726457167107709207071097550538076145207015879113091713104218990539007720218469400323789474826899817832081618466187102419168328288674603035286951522305735084589805543677035494452138138629541078609411758381724716718314444154729593388067453192249183120677383356896703748777515665088326571535126181964911598395019102454789953492732683547221250053113559036877164164247278462294597876281818096904333505664695327215961630217299826352028437747425391142031286970762436243304991795517471311873059333596637260940359977284427605432868272198290900359838956648895446024847708077417973041202653560832, - -5234114438552959533120273549430920274239820693928014425080534905214556634442146352716540413048872464966005673738833751098822322158200029695032991923255951922659450448156794355162784938993340780941450044843068586824635217279114190651740222781999752934269748353914216957634551647511946868291256874902557516946657072416764043116738257302447321082282616133307231179589075048194867323817085424418364556531685425242326735820490658158655640781508500487028955644490183122105099652438518862933489297208560777562512284791900754444836010628807431837263551974532816216796308691941543945597872143542790240936450286110669842653649834986615128295397053003646099302872026561624420667611973668844139010430187242028934913805782722384529640782758883313289891097528231490919648534724579862796148382268156674882950718466159063559842251729116736569446657195765400085021816980459567046743655650189690363951956578165998050442063990383145713081462076957610852694981725192346867326062504716048129871702171975697837460879416325753567674529391278537859206290063028085627738444160819814157405277746710154281085539757327320999171002389430970243638770493957796763470470434196542042746790249848530443788527999928356595442926026330090378141074453968697405966677666445623424391061471448209898230309481697296667346734611835470871954976522687469070229287867317006949128828393330728179038670010113818530723988093788261973417653412805141938653379452341378107230958368698693779534538263618425066494383063873582369869153047635371552583470696119947379474038390026892173072475583019419275415452749995857921879361362942262650096671027631011477096862843271419358043275656505402040760120152518910765170181916175642580751035906937049086882098951124828748831862701254503447346559169974710449926422749259283768550626507276449673609920322486522068567139962670013274112884004939293376567210805998123212302366458319282133149172712652093916069521000951286708565428118143302031933909296046608385131216470791606044495988213087352474129444222646532293088589441545834843202823195935343908538578539584009346516492472412660379666345549854851460557787272033300908483385721766766347065021740907698211298768946522343401067262233700617005558547282630690739932676276488729973012134930753587489812716844210782851237368169617887486401788069389594368544519287780465197738658888075676116456567900337698530757705457248262513653875948962017687868933937356406293128358682004100269484993022053034928434222231374815257407650161689959638854076072070248034131343965249690725615067171174048480342042705478090762702551449488276361786829552234969789303774846429867816416765960365747411304673139600504621168267155120518367281922335397754278973393742134583326250922145437998265004645144308206183721218373576356125087022880146833045730339039392029123350448148548329688165302577239782025077156190788770544998786381978916222553865603036851911962524691840919757903926206380976750912499211672932364940388323981922589183787205851978908907318576105904732825076375809128433465735713580345028246227350980769443681060561605103752495126469451423070719799033178158744075101512285525283633619129462355734226528719502148991824804069346402078570968892524331832607432290844183109324508399670740171972132747094583405071568442069004625714601772581489109080731342766261648731359027733661755842472661576176445392541683143548367229128925277842203724057759666848950280359447870071388116662582296985118966147300931036990315752024362242245561894017390802675780034345740661206184746714517584298499397944995041301139097537611669375272533401469391858176022135587235061516582195093267395897634706124235301149758866268413329768214617664257195687929059918080229794675126051974766980468566492855482945239098469157801348654982357887465201440465563912811540673155313944142462090317471385483290189650774981048324896889693756101602634165880245582286438595141500002766025891044655266765455505713970680613854815538799907192818406948875145759256210540959010424701721230229388948861209465994574850053213387248911387379782905259190205206775508823223761220510515179940383970420335046196888761704135229981692553950337847635467004453702004920820927995236477117142597007822801933342900283714422971967403810179580235932058994713527689041138435116345904229917198168759320486710860076708033940042529809933425426154207623922134570235211356463382182821595662024789306010096953781944778868659440610503670001675352243554027407306563745637928227491984094650243273500936891388750548684190514480013796094492899900283392291559072863442091127806326878282618091753748471387984746050034021299021072773855916499256863096443177412439570330691684537651332267845111359633302795298223394516560468081323136748044205868763039308897570931219605339286025917532482924665013628118251538836131145902883976362096258752269927998137579017748968853066778913155120651104028673040644102835432615656622109662720818915949442419815589042043925578377182654008949340112601393471800422229543757381956483681187867697060062384622093701611060326681773359244984119629890629697760483486142500862425629986372338176578204001747800692134029325045497113487525384487397024998178931135201644257138924674668473753316095159007880863408044927965861201545269909882148399662326242705383344538109083856743775868433992552264345912189298639756846352815307872681002222485504, - -24649322547235413385269565110115281375866432213856206897078276231916755254011868808676609300362141807791431592576328182715724791272856872107196398497961758776023623932049952976780881758716590596705128233791031198861418750955994221358370505056835668106841042695775496577386385561036586927843650623922563838745820985623584951772949013181915873623941775963824002723134674487834497500686398912192700297138573108492204407964253723128690966620430872968317367445006142602092931925395658361934944667737362037407010101703851649209412729897203964673317438045719756006755037151802466009458157457796033387140144853195182577773063906142991771973484179559223596364015118531628307306578568431490185353035753223850158040010835442491282494778893093416515536326947882332551192654554234195536961262378237302977553549006651275426820049819551797292509469519064636034165054304438576289340709266826992294068745674195741453552524513294892966526819726938840725814726467835761851021615511352362811279627642912826526788200201352443612128456896626567586557036386873453276983887163446549961844310114266126621347003266594321962169517116309153239375539347050999414971248595263507826555505241108625852695881860197525223930483227051940598007217655428684461703973216795849748193049144329644576977562073888409114455317095069812122558542709325133471563681793818399826508754902620030673479060935822875651023563250503240497927838578101928539764381252550239714366474476975307900698077340587582272377170366460981355471745316576639776205828822371555522201106242650018563489297929954400836777732290555412825219486476278092336514027805358628002251460679001285032828353835935565613802590782088405377234516616648161794619930955579005026523038074375726404529456488535441123696243677044767605232919216477244332524612603447048274908752299204621058966620377607990642005738182512620363225450905053638621829904885395697973236076592294901418510645686907541154620368811814526661655132337761549367682332406476303545678644249296720542445400406101872205532547759093895351877687683724956809750106034364803544883383833286357516049415382164070091965543444027317867712547123176647783219061254360890495259677991691394452696098580732780245272036995960495712913753886493744261089243451398948520989445935713026910750436613547443702844872712133358273173422524115481618730060531123213966775315066478066879977723619257965413782445948618022688060193419835502376902884723587444605993580526961667450315824432651232208192465858878439817576061668195459435540852059366050208200418272380813118727626079696756013287516769041963490841918930019048475754473665973949648138178816531304374350954202314875118577053424865816514267211554412546438487259221748305880549740976166841443858855082938445162689434182412464758774933591469102496982142819845041821974130863347018811881513908171013621390387790116058774499562842130463389253256599447454074765474638982962165131113882788336492297790298110361588733356369220916152725196757604041583608950979122919450878675519764872484541230280209093053766944613564232330380520889875566120341429965406395432944346225120099649170635373199475006603071365258968307589240173274102771522425425687340343413862025794054461144864706826023568785160148315194257719494470105348661621454759806290014528023102415070513418274033470287623094553692709808996837666232124187517631956770921186883043496924697254397271684303758800819131422340325439544517050174630169306053621410014224148998393671229107464285936086531546428381330906268544331079189042294612879564881741175446641694524125958432417721943247838113014000453334971461575835436489611648439112565273413444080159684217948399270780332973148452132164586911364256139787856687704147123898790395168153265510822483748220229143275790067631693928293828293004390593850954715843312488845943988894373065205143798016621260312551618167126893580068474815709053353283122068934105034103593502120056339638073847401268272677137852987128398485001354127838791920137330127465817716416192250184047022390434824262665635484262556141599158138214818498631440004313996730560555704969818409435451272387391279937883464480482133661810990752118579376877941408616579424502477017084172297609010855525759660287053402912673429564276533208346040065290433423102126798259464215616285091144540656464577208675550544503917167307953960755665995826238546224290369699922407433549667902931511622518108310900914396511166124514090746885620393266503121826971651379957152132708357633070040966335433058256058991522473476576218428940766974747090774418393164481134988876395480867677237271865257380857699116811151497855238488593956133677331949959349676403116445086861793340570166237063448804372207675540913869508229141650417452812754027491899669683214949214070316913705530577040562372394736023590027788405972561913569223477953531935826677297625712003169334869552107790556968823574614831492141241632236157776145346605655968586885618498436294821463559102838739636721607328889719314387170181509912940077213691577674882177478444702587656579467703084201412766801722508707508804794722037091552845762883726687212425284374835768159456031026683863015652418857629514011195342492754760697458978792214525160854221082936441878345380161396234752557063505936394055903926959919896831437791764275341788829277315395107751087082402050817833041920, - -108751237938832300967207329290439778736084829844065039330295523907091810149046236816833626618890192233433662693142733837697600823108667998643900171822994869050426841017431242673879266806609719094865487192338673787475348446619020973620493413988622405793434799947760712618993574609886381090891799563915748796751329612215395872766094177860172955363136738105515882084358776043643216004506775117043263264707744761480089604281401809313787500404734080253357952565738063458168516219595802850342732138768987911019830658149303915035626908160874202207995017434505735253847768395324086118806604077289124283175782006795233273797157484206513093050097538530591816603625917321004853252434462749292575178198499957719994197832630348217338720581467973262328248657774520992863211263032282898848683723776094324968209874593400360882757857525875124802675789148467380090810593613597493274363801679388457426392104165834384393257916419339678301291804122054439211269088776784779687336323426324358687520054633802880632228625090236705816234161208282361480026791310467511495249839770090153647903451115924619513057418273008565235665247268514262715211722035348580323557123627641121183830491081257365140982303702774576918539016857169807098305031965633219145263951810545300726813210033760690115366337705329479907296989353158944102923064508801797616109895760988527088097320821959463455592025616045769355227405263593824868032564585705104511431878145731230916953290258793098048392372103023742945059248719890928501040540191619199052990394193334926693648876673305890899274824407709341432446684760817377910742099807348897050968479163552082491062838520936327205222122826677047311340187364993291581928095480166884925607614847706096791781142595884246273334740381115022491351409088906397398551427772019899351928343590657422377631650874498017121783161919230348412528121073499386588330522955435030055396189809866745357971522648167601452726587777520724902027645878428442028136846680354719395545518219876018870006773789348512964285320689446679449938769392698639796266763760641679150239329329121123320147689935960067279057540958989405033697947907821337423828020497331048617664494042645015532910993285613317366740337541901890311541967884859286246354909338045379454599834285952471683750741073819647079898401890715452193279297930657026141048731111749955654969608223563283580408592146067884235360251651771989424732789781225839746934800685529408586270531453367148919149991354340061078857216316358920771166231942831709629520801659178454469304447434089332270290581519295919811031615400548042772378707426875946516749431090526962877289712236058980844660313550449000726795026791443721182072839843841552661256862071911786702174476062004271261904169290009205611368249021382857387469125202499677918824300291065924935518202110191772580337687536579405507789246401075516463160955807702620847879632105421715789111536244697766886482212011708542164532468847361732956249816484381026230142744068028002383643725385286356372897885022897598537007362769711706957354997078960517124775618073502566855849534229764278652322506615296689007491673115632575762204080834929927645732561247081210623438803225912145990645359293125746667223568491675323183384270050497506221259179699320751133738396727616785207293971685728061848013851761857494722151637185686518277624934314885884863086715329527076092327489551014285418633350535479709888797943834440005315460752353833756064144883073583204427037755758417769149464925604804757445219733136715671279118196595350171969388691087181634623273195554367590294681613372581971990824267319365777026782858746576027048638826196494765177061087524591208198614857791346093403535164656796856167695134460899176537988412003324100832849639148571120579212023495719914651001074883955155534204115068591735939058540487873383933704386455839085248814540222733077967987472164333294710211459710717764559025447062060159258646107615906159336919209961314862767746961270671081637499878641652938327888022077046197587574089821361205593761599441224729765456598337317146265534783502513625156165216051679234911787137472589557183459156998222657872706471103770952744870683321941457186389504965606480999500562625490069546393743500383704786342255409307915858117714841875380783650586203187631717285172528421205686204787496505970921065740170896438497203019305474694079114486152988952051372082531967051571785602642302887855400768427923065197080872196771610449961971370657065754173270804535457822867083980614948411847233394661994148335920185912036861810685522274977724713791513170892234613605040406042118588329397889155114600117739867469750234717723313079544116367186983905906366316591729818820698409457605416344537072214104335429814642036876289670159874774242585565202273415800003658535781563929721094596771963544422902109603520606847476699933034366970825655874439694061340449871615627490499010736593299697336118533814714228376715487667165349496959389914341682117204536699094886847716570323088521869953763065701930308041812280570341049419610845046607081861597437664270337018153311507697394378309353409534092787702211459743361551036491317400989045509440533619323241602549948133686675286039530839996134924791038951727251455406306289224490288444075696427833907934677983061257651266896263204924494748166814928568022187638784, - -450594827899145767465946023656260056797744870908884079128444414551931750498605869579160084458547602303755551508381170818645009761421288490134224915408892653353704224910353492313058555053837759010922564518701504518293274148186142508348711759301735252212843048718163467243361426356841176583228774967062759226664893194811415548870353773007034397126923986100552983724421739109424745923299049293284933166221683257819487299048688780942504728357252010046011860298753301679193308154707506396916027984173212581986605186290753117590922964472544176740232765537106475000921755815745374530933941661861773717143139644902120802595516919286379068058232610971939828774137633969160268891400645406918270801962305298405755160895969292242792581697645223407006421883676958782243713145226846738794890921409198736064946142092953161482689207859914690161840848690618825926531091930778949461689514741650123875611713111803976254372030574758449088547635255887281964697837334722253101962599530025706636273738215167822403454588504762377927817623637087439180143251478860526862309557790996599909571783227365213528642447762898256098088535998584212926020346209294438774892123295815636220679628569203180457073529454910085827178207713622270084444331512303230793397735241480474158045229283053157155875906798325349239814030175492392838787726177572233272504171408438300423085240203301106753997066195072712257192734135456346295831436833462301310871377146317619039421622138299285629368054269892890157258224020136790426775530104782784574955922583670059469154843407645304074476120064496338115797437196142677451676088234207801711452964744174319605879227489821000459231390561866777148967151101959603632491073972718707183765062518140823025630484932830627943804620829256548151420515412438220502420407870950733440429710755707434204599004274353867122116039544191297773063430745661021970421451195938823917428287054894876222262467126700284198148854286518135288504903965897999608471018908223291705110573094383990481293830230592922801715978244927697009349849962149415652281752992080358684641972281622787656865882439472030324186188817830459771304011213027675170612611973245644565840552598029584235225484219458180782142349968154070356615402286643270754874268054662253222854735148785028165365657897032388375276920590147938451253126928733268511082934056422159718795091392260636851861298368740473698249868350259948759388625323394148049781277233640187934059632169099939207181206700144375679565535908792175137658751920546766937140884226637523470198071971196690802888341491158196181892836610184947765329082428017911267248205036393661746195146361049231187058208389630675742216352898598287173560748955544391479220453793425126142884316873938452035709325211253999069252252573023773208506426303440486966618089924963768707700281470563701511488453301135798994349948685238249337060027457935891622295725049813302035599122978128563275723993243759405805636589241449667577927594169940055302020400995354976741459459360701389227686682831343962154751883135473793735974485765252688381926803883168346121599159435944622699966501833189195749679580354022086405361057863406372480028691458579854292510033587871658014419511762437035039189326962927894653994838698041620908381351284200962163373486410842625467904120363003047915759051969455515651872385749156669408987735381693537987156216223494907745493726972972157323288251066684427867137287821496113792044319433848539679705542144516626520035877543518599287347667939463902902829305802903076097099480505277729754479496003358721693640925344881081974736441663830880370598597031980934364756860431106472632701286366648436321967712851381716949260827495747430452069553050615504098813059101384600906667137805348128664382273855891555337690529950491825509246849741922631750149878906049398942253393406174303801724723088015738989027319673136569553720687737024154305132085593437998983347549504082998383322446722749992580322532550342082105331487197776599821598092579006471982068082459857855936027939459090762043799351774974707345422885513125369424400579075643261980484014860212928069338756814132618336264371143765676004287744998864107526550872538005831048991336577580072312367061305534987518724936918740100198235863083218168106641076106623010150741492976685781188491945984190730505399189686351087374432121770177916504322602309490835377313663536609196701016219077129891489881947486562612703659937250568175226342790779277979810387612991714948813665465516423715836829327623508133304604660912527347546660145297839212539917978894902568762102282682279763761126472027423686358574365335754422561961934731786407602079334040033670730434202320676018860611426917725501569560650047239325034152812038929486811980132179369682854690604373971572911226575032894029998412340751788231620706300543359589784622313065286405505395219862041615480832072741071396168679637583594726634983465953572414970568498525908736458966333968618671372462658327632582277861048235010464730730792354810069000946669723019482270029692661907657093079719924931046025141670649951732155247159268759432472686356960205571180752576811671218306900784752443192187489807531806088352116145540141938006540583314760237545892561812381943478451804709371517310805296256097052478833617858155559683537841098037246558208, - -1756582048970930360182404584336692946631801906958381092506166233841599206617604044098895483408990632313560539506647437961358565739265295864287602770656372676849801847833107219421432455088452951810143077367698883956637133293858528359191913070716135632767169520345047789204737433701330088725402634581794801270947120339130029660190394035116453183752179938687254392247658121430064080155901891412327210041896254904455251302579580652362289448562805682932403989924918772920915019219787922780096582362578645473158373888345418895378032895754597737410220256435693139736233565994440952094385458910822938193949079466581316130367890321252817222977252463414141271943898586665748285437677702518476674291598523156901174846482357387891051734699174026810935652235844767944125033787484127882533291448367436101304311336971224077179404217069675458090790020119991881452928475515083052203057082523392858819732046320970135097461714961739515408742222355373687310897616559546987297445638406285066813336239969290120137789168528103681722779866767510992617077160471154978896789737793331791884751998825140104515365258209767831944911107882306392150146852265651932392579938788259494893581986300888269924135660748338340051292245772845226809460825617291326802837532364392363277250782894667275314270787010639941757803871701043225735751638089454208034813990495895776668497888994131311578434002491099883120712219633587649058609423992213209230090928393967729516941963221107587950985923783593432001153010551653736980628726249211949437883607404720549533986587749746817620526472435745229500494878500197494456027448072993985153663614144057260600398655993126927364827572628621006258500138161543163343060771638799508092410593277301066235540848253948769762399514681795286128076707198903757746824308311411251286773032341151491927633033010421741608819723926656259459077048081641569684429034480203411038022029636414724372617205212626685688067895477610212375756308238806347883694487248285172160079381791746540306727320864185758538210486487587662410153408701902957335615908576634776129712077824911479938266047327566428041898092527043555077601796244115370510992592877586458869689575072779784918941003806291002352660851803445379713324427001365845179743008869068127561676834796259640544276023788244032765187081357280400955918302086862288796791043761574167326501329993022509090854555452469510753926634749900998612535847196084394653584408375032094093753242863995076531483581352536674918469922618907430713676629443929890076723139681800552967486740000699015349188038694429016266470554030336770559313551252004502885913134227763873411855757386110642868877283812109233384906076077828996150034050378797090149469200966112602346199245873782330287785768375446535269315261398113515943679063795579812246282114544562781212293376786062290313558225394147771856395472010762339005177003425795720255652204089663610640370811567322770410174903108380098431946725462153582314842576064880409423958433938677901562204324707615910348127611418230302513922534398773630556749586622799936269902502889774702219174965979092644819793445788043719533729985836841333417242246908513743940674065201142898241375507585936630786085475399092328050619875684104091263643561281406101912088962480544079966827286871216945885443219392043637175410270129355250109140506777607438056754315448355757348178538591902828570061377152426898913149939968871882914068332560598267804571127595238075286756436716934572251849691549761962767748435603642837772288808703832337983194349745069875646953164045860896485739400608457314616234794962287557072402023821071464091907257565859907942699223210334595020733830624630559325753858979537030661701992004063299510911848130506624360688422056026344022778007634887766757835490880979994207150188173159675532706228471123919102519668568097206744392055286387159176566347451567019917338986540578657493688530004521131642479564655977459166772681388171231645450167927120550005734253737533724478555360438920728519025035499565529561042968619149019738036906219602925475487376036478531182773426948789424653669673636462394913812617745550180154744467561570803451912407190714806391578995779507112524713408754188410498965006886897897527591905953478058698937501427446220100521519903191326915833270169885282739710774416213477197199430385605713550768484321092622146742683113457418219623858236746313480935473303464882401600853491584006850389284085132195132663177801864477590499645769384819542372852652100219972892337691069376719558327996959945367630415228633131854125460285772031928062088971046287940762716178420845874406237400724283014658698086143077499110052475669585261116109892232969154562853067014131384105686943660245208193211458248060290790858908592260090107760757307192839043831340564883338936674174842645055901932247564437244412119591651521876579661722133482338988294260960732857820797037865272366100118054133177826995255167264271588585083555823700793999862520906165234374383521037514254955109017227081867537402283249078783258395199014744177021239443964159506793210486123801205704646493650328457337310339345584264669314505239141414249541070266742582690591535304815759803546768426760470711581610638600349450995457805723247072239674289306000020953161716352642740912128, - -6452164244183627286004599442647449396655969267000154286684655068517658932270212698377977107193246850586967362236369009546428886332748881385498150177479604437463596332857939740085196628890925081188446746003402510239864340256562562015043232599018470741566774827095076158421764316421247840798894670413075559173506080141826776320015523620079457322400911696712400682530207294944706419580313347543266704954128821429736266428510117446442217980720317891486291932236044309345495324245338814111448927320638102751528179862741216683440652889924858915064789520515880901134567401476684884474865433453539044814580195613859344784507967889924907764979170188887823690956961569840978302133281251953157464204676747678171983843843295557279817054806211224549714914199018406410352515411063709383968112525770731967990301860463723129900647782737509914456131122012835850305571072325267898591135035436210616021305586143868483710746795297608115910055183258388620449708821758299112255065538429399126017999546788694052374346572406368153896234542082469173148433690658380501716917618650085844851463234678788744430497754448625364938887930521942361879448504042791872042734766206998815399116257120565456300183589694437141457864501467867336426312347352482500471127411435226936636608826866772120541249354336915228220500617356644898190646459560074133537799372531004981913648736490586564531480563767947800192009310600231065554823833558051051686079203513270105246506311985901990127468078105492406190143281386169854166215476612571479774300538655465163135333024481722406915498051438010123498150857341146684241089365960774486230729444566790432459727618232456916793729030139975374697938233169163439970624517909662090730256597157997598735363023706162482188794633506044939551074432471642849800335402183797922626822159016663344248969888499937507623128247560219527915678670370271851583311383126291188950604102067296331521476874987811722617746136797487887040213385083211972556131044531956684182052694650540228379429256324512065573784638073846261478057911662122288387758741549614307623098729518495386042731816587742119881090726088976511494529936480566042072659940766884074437792088485859810721627295580910737595786086687049528970685437132502548119975668650237542945826465050473803219389211542604253034701436542442364102498035867401810019531528503494484622561789041311276536872928817050299570633120589724206563608113679560872407575707807740616017268663960305494364011203548638902571621339012395603424676632319834144396068302849112664160646454759817352373412589739084835964351884858650558532165636434232071400168694979823646308484099022700227632327647674892616596306403922111050725326363536000166781914176288374000774208476296779599696645870001447106862478426365022799355564343013283060534338419746998676494515488710681531888834018242279501171769533854364945209800298868961120141966902184470867058815768735675174401805604962683548873777003474076762244013136166464700446981489007220653105341470072072314489955014141661735185717503274104243419341764732544824581652425394831777939168478543654547485805426668507187035873141287545705277399730290601412587137148554943642439459446418305191861586718336800581046115818742912885146072064387586332181824726492714582862138545123219538263516622641733197008316770294866152559782602933953282331413439988374922638737476125908488006849564550476396297235123027003171312561330369855436151883908324134922629307971802868013672870166644385952633463665087825755152835820126733437429248301033723603035541474116931734139860947677558738663981524366923426328065557372129645045224663859985181937321554198574213419139174475413158980107008781130746762799635739893571926327258444533754646510589279611286544104224297423078826537856845487420147213127322303633221365398909635743061539670124046241096628973747889773560473701074357858291801234642204333328849101564168805357537790904137375410678192915462975622122803178520928514119128366800575593709758546251796741799129883458347517613504473680020396234226007305708834742109770622144089201030298402282277636321882359688294067128500555582595419635069189429741338473235802736289255873629665957199562281067117106700204359432795072429607912091169675444737060930466767868755829762259138353625419925502150340013860522694140859364036627302448147991140263356552924851837932899005538925752994935069805117644151830563025050961671407875260503438183344810651340948915514760743702336861503993120796663555922508279074585208765233564531840383573191641280296635736499712939882912507692310790231255242213273225119429247780214932845435910228475208835912071001428455628919436285273274940651932827133906408908166359535254281351241646195364951876366446136149894507283541496217144021825577165331577440014378807531531160834617751938181003572000154671618327884929991410315068854436135371796479600674740850305956358846476038950170112891315579247368819247134647961042739595614243424425145507343776558066360561684174182122149051831846846324782341530025225464522030027329714901465827366354087929875596475359458795904395033558781857642836206810703633340559241006838720884227585880422086055711721464119031215335625041598320077089773121120116597234154352899210084352, - -22355385300557611014974246714343661715373966469898681209219161681099461928274863528640348420907762333174165989483522653252126498222936980091552386722100026277058593014890026633867271888253598325923650928109206067426147211501485588932573129508416182157597364995697320295933302837490388732977909802537662462762589754662848873184326944449053022971896876638752624939485337512107248999310537113640634218689927487626136680780509224872324024678828190599944421563784712241611981841608173419486091661998640420624691896487441948768369890416404053147367983274512887547151413246963141245578556012233646194914898385968318361334051686208298120309143928852683062554612624984206885102991123638461877900770448488232371927354984392231352392260786556427416277678457938953641680205643975795825879312234052673203581166062920308271077953840923969857842902837376014109309816363850648677282633341855792285739505267149344186209001826408335407470459153025995646979320937215521610870718515171033033514260131105918580805109472784646910744867767916817831362309335713701289771033927112490711460265281716252410899496273973645378653654662871319837611266992675098084914824000886839333772339149222055793072360745935377885984885092776408277774684966304332464561834297306671839388419394460031226775401284312673064774579295987686720221285529836484947188340283214659731748452545713192510251732689874306236380401608432368164328243212218744525766017704730633112638679627120722326579410464424375458046001653347702134841727915769531745361362835133751170866906515492409794413793080373772751613874349925849389841142667694927365787659540983398672658004855099545039959042591844650962525861073694491248013710809446073053072992706442100729586533390520285329167424263624464351001371634650923948154690442094870054068116669425478929022171218244842917704924369483626275751993754327652352071340049917323196611677910364602877775370487707280932614341591102520259079133587349185997630501501038976576322270093576441277014948709113356789251052786889840772539443593918223664356554399972948629709346088461014323497215373222198933096216247089084224234646290865091794015087986610371261636524283174860124108831686989552294111664024842389341825261047791291112408226887848964270348418404578401489326980655237489894790999539985333993968738887685787066324145016936952673590256252305795980666695687869065214963723418565435487556554524464587105895836336452570245401613509882885803500611638869418532698761243270891788660487468572393317111197459830450293507886524569669806663282131771476056060908390804895433727890881281190445006271248116484613265613095280482673554834166960440330321507950433501780099022283017926654700395279919073784019320906626169023318862622989958382232406004446231163795417870732424652198887357914461413485219779198643181731766997769378332350658758014769328136700292601926562567886450219503455472152855820553201543705040901954710773645046119445750133701891437808219731119160609261963349407172576182045932298819604072432069242525797256054075255546230100627362574836370109101613770210181685541776598975383836872311866612777273333538972161981452966086185482246379898769095519903377604343989518149369036393227292435062295001597980324025106506227582354125762574339297851692054054066980279356530414212637809480643338669205922552390326531534866123219132786998616931965789756610876363711615203919794418508836442665533249065196981619740872297377156229878915030260081124005562097447298031193931869054495005907291720645880150795128211543109628974044512514557000203811225232852242866806203494570587632028411625930979628121595451752878927493372279826883589965417175835063708032095773675175408933927498970208958080038853212183660176538193491756111375787827368913423835567146538036795390140646763720247536442396252447385370148714607459370550059631971801610220687916084703760556147978350336089238274301488751370576523988494082199633130668514529042215895939582565780981517956395602486727513720714450460918392656728823140359677986364854471063818603708732702358966026747409423092185790680420345905087283991221967924835406710807592216733652647596710830328036570954469398992472101180390586356989666272649963739521472264485251202177872931874599104497957571538126483062893512190485186665933534811823289480020187657404173175820543355091406710323794492438251470946880361179835405179982621657573485321924110381223846450736367499872033980515949636960492693358316030220070362221922497580640596368715178113111301838376024694592267083614501739885172452579827489833155981201176084286070342635670469335141236682715721880031254987457177479537912328044508428039846080530128806115351393007846673551584237302763826437158587076314491168065981445630441778866433673599896501798246096855856936238520676439582915974532521172306894047012989457977255653035456361759309787361090412968612025000037491889331630934707034443131009620221798410390276302666851122785624437162878772584044064819516079620067395396891279003892611812247385563599390330929374789602188639088989411879841262889073158906978870677294968432755046275857200601348323507723326775560640701493417691604093052144080754041512239217616773841068000018432, - -73126444885501102383181431185770135222206925097581669499701951645266513329894782459586059441307458535067906276317950503582394823543874996388852970839716553744103772616273207029319171280018244305425679658174170761225474007565723712658832129560518450786279034403917925050314198534582356911289516144252089233822282756923951800931037376146226999283946801855802257915048363088037010373298899597619816132869510722981581853131206288374596465362767030603024134354278024282498614987652386805748702850890806167551952672479770026507039844159189504091972432322055385866035301371643399502393155907626540285969207859170926477074821564358983585587065268848322823913998700566901350035191749648312577288631362424025743144110158049514076491067320893685999783124935728586352621047715393390348365877884961209479625287734461571312876912161037165505101910666706747923051849649110104027115509338455481746984755561912799813807335686036213020806806664715515279678971758031225685186727293341768795072128458628734076611444837510585102185253854522113867773316786728814348518067268758785189031805808113478203803532711707607107937277173534270715847399359775056915919026611315221889855788116005194663503250017963366987928870285920199021528894333753604423068846462566820531096929288945596828230906732791578093815342141634241610396829968203498794539182399166765727966162498469210301832489689540483057510313398720923744362301153217457870313398806071769371289699545310566197958252592815450437487646574403201279272479078068204472327673536497408299045667968308987596406340453741285491797820202371207931233931887189149905238847875469507902705715309025842683676731527159314922308419124627814129350722881990881913895905274247990569779968208708566577433308847763494941880671712655030827954871152612766117779805126560754925587757883789794848238211794456170479713472051905452428742723676227149493701174231376590434460280885682975736408530734790982712083538606585465398786516043234729445441353006060176939843128150117480061701622888340792926965357460682264682116851329466288212179591087495306861887659707196596274622521278976121781485602990693257428581954276371226418363468044460319426493140194009316930692243126176429671893412635268920149063615178406303232270312292819289636838951645604073323344760542968042627523427506309884633771360423749742859166357913442075168487368240835947430350728872405720885210338036591222882235968362102037111061001254773968352993414376996294268514966818197371305532216675749915636577492682930368931489615555135447270122385148505156161196055013842856660899967825905068406969225827751727826286974776917587059288569646662677888874914953946239185080471833900740232702174910208322969362088374767756698888475185715582001134238874754872170055871124591371088844073390146611841184713810459125507201936040461909521707093660700046259152140242823607819201863548568495490798080165316321060744288851429151619368821846580051091189502535634131384682049490868421192429222339856644045785604926771498651115730257758154569397739932849898725429220203274167466229342086828638258151923608846350275490197532240777340138566881058649432244007229799376063701085045013910539519199559566913526661409653426577542624465995322405981539250701845746234175845103983600389204465341014019612224267191419843387685709536373147421332960381866952839382233562303187509816364416096166090275820933657893197016723220331198575969004231591722959210618732167079440494338061523521909682857170533128067329663440435349106187945939907111973872597157535362957907175828913456012251531287593210268247857940394564049756097804861135643015903449400316982754389586723534224487300511736903563244638560584787379570292337017833866335561672157310757848813146707803510745407814027618611729227731924574405856487527286859658802535628119494232189829199522247370830912491540352251306146591054516604734573867210289307797008440486219482812944883744618368772743425548906085832879411792682669354100315116889787091183711496002694588248630712095050620302295309851874529609447287155133937542413641228451692416656060169438497230979398005268424874148353746859592898845591879044255226386483185983463573802372742788902209608870148517200678970600445391023958886328240646493607773487772574963488511981803284591561125231236578228023445216530734881837363870014706828762185101190750463129039666316188166068614364415701940512233237520167161867754726823768185813256910853271594391383283489953042516587464796124157730430054867470176681798905705044874901992561640449768861197536279303234085052509861910604969636350308028181370623319487996362896232268276373654867088521961364069910326160960644566399666602246395159204469004815236816936792791408476174806560537135875130483258679009776047283160859206446693664968401466125608238615908879544750803322341185498801579471446478472553374178464141702618984272522223079826174839251683031231290405702434698204671685195332824169391430071209982123380850289288900900714558207424685842371444600723045941195680946770971456900650392191074647919916182359371737744542985036661742441679511016205452764176052527548871422265542860761231764448505475578237410082816, - -225980208386915597425054837526840600200886907242384246498012498131668083889201774308825453122940009319992870865480959254794448316521326153549062007253027110623205300803325981633025673419162901422960767079308619448394859135787190375493078492869663378498821440447089867064775499234234108544908173677685962775301502065743061192665804419340922039099294365842231198947420102743382945244411236508456255953665505704223055465339070756250486367967651861535569046822414413153929984489708765006656055846973727576140587175466770771017023727927651353878508502764450112291923592018813970656345284780240633636576481334453333111187524355439455350007395963320022764242454879680471429680225300038739725084436167454390484523309443993420047698326800223285155180813083306836621916925491788736662544285469370977188588151583845101587812982148034019168929125654837319261172291602734242621304710782896567322406357429578288567975512932018569076074141200568787775476880063339530538226090924367541823661798036409827198954575477944282723643517333610688621995742906803075676311652012888186952648402082735133737762198037922936129976193197537017763390641652626143920283065184203303697695765436408291183775852967089575863023640557516606742936515020761205922156100702720835739776868047016054492391110648880155324233100255760553475546730530439048143533409938823449047502853001693140122956078221261444278146352205929981357621824309612404871872705636537655196619615772003104544505139837947843002301654738039709035788641030061278583435580956488585978028625376494999180892526562588284882379495664683116088060560801464348463555130542528549173785536392131936993734908532202685528397686654299367163479037065585338606941383564302194088999578445749989608399922399388905309574853611123376062946698975976762056482621574811382163331190689962903693782898738681840637276560043637551180366759183897152614468868632633643767236870463215951449928749115036752409635587053106898747531945995204317676359559282523655687102971072797642845915104195381640549315522975087252712927211219508571333661356552012296743475605685823420804126449342325439507868665208034142472225015093039721159059003456078300275556843641900038392395379821016072185499885043613915235009855578621025716537428196261963971011362707903609054506379854230377216313208600221225849071740387732456767473003355319288446493137070505179683525591233294640006287611913567111511912732805853702547761446870874739799787702017707188495740515218726069032470417378614823687540306613933288902920898007332359286240302589477770059077232376334055265671354264878224089589459901388709030056106687157393227550671158173594545765436442229679740028528252722072093768387009622752845677013503373203764296942468498269827742696735242379181592806867715833361632910026878596835968432321472358341410740706446626984941962627828937645406829491653607173737278946690007384929446326490903016964866712093356123726591181007400617379366840140461550942651009454770954798525383048471847344585836062750274407471986300403037610107893057151468867069969428595916665255422835650709881183691244130016798244385907732744433826296708461299867403876030448488580352118978621745553360134331857746884681684558810757299657624632766566239870078196906833568221983739991810119159615126890733115850349666437699219891067623483033094666602409531013515943259511935413436256289900577326951839334352351183432187012045103557325776944654567095976692420813677712947282285592573811907314665096131629195989234113633188007573212863923364163149681337221739291855525766104567359279843109062889346218192420772347044119136253416692971018388169628590747127665487200887372824141793143373709664963485733955417104157304088586101028509440649029443980097000748943454821374240127520701078609646431651572910543345274920662637348394079895614186632148303855069181323752730651542996075760734053222279276029512540461669574955743050601412509054840616158652903042890342154987889222993266668059130904412496751420969636744131046374345942646231644865482120500348266232587958326603003201289423013338501233501577647163424815396299852982146592236834611043793793595571031314428555265298613178225093569939960827224032991541280450881197640455453347158223945779651236587363290907208614936769703673173953102242205579093148892374397818097264112774366687944559555966270074148515892191927598450220931977202788810698266007625749564128908228113225374609873853064789171042307387704205933603564390234663447294907241939169295461970342600718989323484162605576604723585539929352276428145040007617048479663745568919390744895622320153672816439401709493186224032678095659585514548341845751032934463744791457690698745072847580435751291469444636367255370292225410872030760159147840838710135396140655038872269734427696261960591199999147376964250332957929522607913069691544369645179028057495473869505361269577568528629027090460050084855239064695445558188283287949703871199099377244852772613928356215295799455048358897113723182165577602152500739949793090767293888501842804644637203446786059929463486060884558146195621068458642411193255892801529492894867449790181933056, - -660064130939967090788138238250379967323953570797250794565014957546759325579858361551567517856702570491725391757003861280281065643466287848115827944462509917697945788132257140258704607877658798633976765925315003515772673815883420104302377226109118404327104442868438995790657029471260148948515015428352059641122513318589830465168459936534610626238781559154563872045865551024885971057830927762552375933395284648365456825380857146640593812314620600086092590240578656255237827868520844121515494059943390195430007386140152096991113409467658575122567571427403505027707286172200027767537064301799744908995066718426829875095029564189479288525156888700583848002995210301471912616737936267828967875425337818237604766930237215674537997556265665113979592591979128784406544121826641369491759163353185836715297081683819252007234291099014000959856852366392129134746014363405836992034619540386676371889846590432866648301335309013290661885713843042260746932511502469932285851240169329502558829971872965362480639517960022229067102159615086322774940430901351445809028636593505824664681055466801138234810390228350869014446068360897866297658576139262003914806407007795430288902743169867813736382121290157214832713582924870822641460847773913470218364550849695121921900844805849302611587917601133485944633685256709828762544147164615669150001358486732208827887406137485852159526858383318249396729011811358718288217090496253976504641921518111255585058490516797928922116762617247208092714384568184349433238785909369064588547586322089001809290468781794589525343409547966420241184892677660558521953189110395893111864660207146051293488208176788854362104389608629292560138282484055624563652195881071356533298467275959576858916713132915983001931451585453413458348995853845416933017845040873447087234113785247096116386418147521788074582361646033243299755872806923516547641342804258732523877375553041701038798985992145605705556180146272807598958918066284028151423178341490137929035966811590486614201420622764403215197554831519017454716863946905448826014255043328973269191128198822711764982056023787352007032603921198786541803875743405574579015215483059236894864355765524289017461864771412183169609675127879894192136280820916793173075737698057942950999801660368926692043012829392131600380840683853261841315810904777948843730949363635930236189291889806196745722462319738829977813634560134789059191235438564630652793709448222551035237154261821371259497340570443736534964282190846162275524093227530013387005285224440497167214808683691572711325783474890633029538924643426578762400780710947128011214681644349512147010512260123330403386687557364393323489175380584841635410612834133353591465967074115977391530485756533014920213712054445268062210872022434477204661365297323864626185428764975122106741376678849444598829286421282878398224877089731575628133822385792931325355087111357987313066078138141588096238191217100386131198677456812636934929625528280493635093287949660294511972833794177950075368599135009353222504895922170457215247070465948533827398525682045592269850482173638410980122546213349497933434503127984373615960903883297192306934557823319927374022900228143881407166455534899272038496449708043097461411718121262178421816640335167816853526934216301971019579951876067237638461475384717600224064319107870354713753522801935291969048266823426844978047223501294910614970982901829491399517042044599854480929961543583868514970289908977159506459198992057986788541212892062839682006656624004707928825752515903365867298213264173203901974434468549379716145047225116235600680835891173391551804960479030253748853882593818597055626753683074169595464881437503607377715648462518408944756698954376090448452214887612701130863519681037983124606266910992458594184393118728383880250893598745396561114735864442938439237792673682932644483036553467822718770391410484940615590241240042767956987685338912318503076694702729293847126072906825442833896261892647305084027713192353424172274734116681767761372438350714295477727238799677104480745984703553778203194707268994555655083014017620302362048600252671213856988189627049220823772793608531777786318217403560778387369223617514552503138457290130325817231561366745480678800490558609284134587548010370852515224566639432726582421731696815133968349880113968608504409257588484504099924505341951694380253504836757517449186171370576559157575491512850008143956635766208767189123507040460514492860876251237027901092572754810560980939530545548561856551618440637490185849394189803645464695746097939043014172281229399181681217346333190416818858624747560294381965542975466403827691845515918462288608383429214230445182156670715639959606309933284223489034319009618975150739796780638953727182910713003023643143994930264394563281538325719784213031262953762117505220057406577110664795360042041792373906910254310459026536150065659149569247789468189069704051767236599514945685197001991940348085468086434930204853223060264413311031759374805660889661484118632172143623362447642960337973047386694337329477983471269389290855219141363351447148553377556065475887104, - -1822961805930666084861541173564030791436693861560343624235543928545547639983131148552728449207164879596367668061183484923408384282328377365831607343020647041989297294376080905954553149534790153226536427019925309716035591398038443782136368532197865815474329907070906187234569398257555958486230058286832486979877877233032714063905573771158645166347504634287760711569307015830505979185329866857574076249329064651718134536176697979284751577295438808876210752333934102016184646074649097537733090385595884589226779825063412647534664016270305243808571622690394244648074456363148449823870935536511318552184532522782532824396725276630728554806734311447825535930410565330402420163982815048710705765479611646387924703740786594188822563329978099913000706506101939102189758581647387560213898947697607554608701569747626987578703338555656569066415743527328682698877725457856719247777511161890683480042649334463660126597921438670219690603925861747000747229453995445981918039252903921891067964122112061283554515545258483515794502172662192286228748696887698077223203525730612686921445677015540155710143501937341845565193757532112816761824808409100126180473497077969077715757745309589750771819016035636270783024428401109915229439025192182159423098031283216923777477618671459615127003866374199180762191615876856636410034475570486955846998096972907506854044494719766733235406615042862522355595222226679688608843614347159863032996034593999174849308156800842072577291003111242196288252097582272579721579159172131612551743446881468162694333550698580130703784536728417188214621977172801655565228042453504081981272534510083958745047147091989210330512668740257289082332614536327661067021506564447625685648319885658153007189466341324234143780010045319670735722689459596169989013150711117490929050547017922112847853252001135743759703429431943002539003586677552886563832533170349280597749518136516934258790342983029563807962448323446907645641503485720734721124666354132406668383943142542929178664201158365260825338386909208308189711255273285790380068852768232496579075762082646644944100605094072100350643739475709963916593997575410958870995325479008820258006429828330191757069906596685035721374313004382828728869972605148488196730841581282864419558441419026436747772940254232411790589210342401772197961572226703135903382327135859762140849662580250008863886075778740821327569732313976987892880232375011507913099122557648044054781376588854518029379773474834903967818801429000134503869640481617376812549818914143989894522703857094766647620816765246698419077954575444380945651064641037411359437967009915307300358979476658080049039965443688792647136283655717581611865928640656137123560830927710614627033272458054609517930382343596538422655986464627244928457612983449728523297815828451265752397102004180001959554627220288227571927690982379845373223541310044194657621352742704790198068473224984707257095594002847978311831907310661108436764423835762227087746897643499499880571211159458054745338276178411882558637447886030247970527696858660680262588449181136249880081303285360314095598559111894098382723135740598838603540951729629801403712765905174484872527382546200515791763389954969805580774633245273074454239956187844943985884371915289133101569475096417153328543853912697765816321702419141321243880179309321080702977964433766361862962184696237680125076057034905588310634943730364332874752603865911088552808460054126124422698839278444922154045718000571368564423922104348611457212758661772281555508925209524471661254396174831891686154211070039237355089933974545492347620540659107072878139859475606959883586227472111759541377957588443015544990940904656698843595322471451685858417001758503463016306807399355114962790810272252300866868366560798986184680973425301064484813504369458300016076709357026011137705736574644065030313011906314507283580396497240526899907689384275444026107552830343492617969523435048676660178935560245599598266453267400082075801750315649124439372855894923109557954466121165867525737688453645071655254913272645047713172565359046968947033401401387137212309763848598473152187975085966395564127367057210378996907771437433969080327873641921561189245220187012785807585921667882137961341649938984340166924099034741296074048728065417984803410929068906482596443190550378362050042439025776371073882682016462110554716886606657369523794810814391235614838361678900758804043809061674245256462162278926018483052546310714344928249499682442001343432191653188493941200899344201583068904127088669263327329583603519532038339455298902684009523991069703275675286593256709482052899387483688502765529093678512380213444412046367781626167555906734173673781088453069491058845681904169162134661751897968330008544814282625743517472155247048114799118097815208973162502497305021706992732458153307132574368534294349388272720488247812120436458122902245065928404973907706244570427143591467697802536524470099348919217481650699330254701383999104910728734156248139226619135797779794950648586318587232764174767123621284938176894869806357791588134827327488, - -4761560504351899171103847529012017350216963752175443372906907458411523504203935466497379033993411341658036904231820820758816020801231226191370897426375524219682862114586721131111863081436194710561948262810116555426603349171157913975251527952867120627810112757359217190906958228713604978014450495028756889769763267268229064698420289556366405072273277515210883947090743327245016896562962254733048172652636840603261302143180165027408266339921386041199734728451660219073099684712278674679525648485391179510292583482146881964290172271640853701045959757401979024490497657320192604299125798569423110455142901516756916078499786724513937025412487023622480416095363242535390087819846062646768202753489652442741634683345250395625667483950088686290024341018673878540281741596140176252095541906113921917327245112861500286338085226796551394657939783500700059265690963040446580298618501993511042041224657174493025334420837714887629253819439351457889617946403589605697287086521271482614941288671364314790636701276439346337914234488925900479762960418848249764030000778338862218467114478334935431460715157383123849484388969973060723844291719431312585709818566773721000107677147206465544900838107575285784072152508404276042820537751613915049091281988285726319442809688272512690123871327735837074318341673611647602345041975766666755262618604049704253038645107593984627861809181180583153252605802649247629033877677562163957248180434191879772098126975827089539201470494479649417328986788691327691135259292499407933032718493770859209553998082549003267123078836006776257028041800291912109559513699045739937987006686450898529552817158805786477916169901413319264598686890020463303735694022104672725445594362322807422412245558333891916197727205759272913721421101127665470159184430841068689184881662918609221223966348581513886307834590260389803121456534339344804812657941797040823247026350491891942348590792467434903973577951514946599912691241280530416563011400819473388820030466073912142791453677152136447352137649278523591674569276477767161121506743441705938098135314355716404386578548097256958163304702019489152843956362300661491251704334952501930243520945738974475398769341460596099410692629672644942556200868064374403417760490901420450506194025023899537282351502262089931855710564870885168600293604742083345390425474297307560345943329857210763274812540211955963190076027707667286728433175970398185972261810102267947943709594026576639184542798408402829139604642111689549214036075153115635651640084890134477874157020982838975173554227917176243222906776620557076825423694122046628464432450675499469264285838913889639840288424543706622299318078364725046042274511064011677713363897144810299331489267791254975490932626992513167637381799848230874714928686506480033311150218338827604235650401541556530328504429507172769161822855969764717529417371102382868826290481425359112555643278019374102545324810354882290159830100843097924890677660449129493042247135671560854775936415507801920387552786605958827980274942305728030633394427621306016630640291237639138702119258847234674601094467901715770115928064069064106423892415426246199270319047652694898562716674541042517841100861374502392835965175428151277954192419953369817213740446731791368329839020590158845199377023036412610150765022869648914578485897653202803734552292435031730459884042879206381397921020335390959470514719157414296914428129763744201706711948461614694262571437842759544381682507219316428800583769038015773467308665895692106067135095667803143413513410366965392411082324042382049575775016598176205220466297571694492915563356854646785534345732659947796582049135154927801019836768407203055836333210080761334531080158202217210346040796524847735517883241117342290764888482391982930036973230291418611047656183326370811023259501299925637311953779091309075641196598882978091245384420256521673975703368035016058033358380400352147563017983406481540882339392592012506518798429110309585964563913632052223308220118380270643532716166794478566695714948129198507174430221920944249559466787013384571241258280011467060762659591828670245520821011591049178480582122346612996840277812486957601793197202122230959271768371392655946818235440331363713970358656438792222090348402680354907110678973938485471003189480135074959794001267144902192058173960952217986018914591938173033415197343901606365964242382272892967832148957492912126580940681449022896264193649370720928912950692521682202607281240676942594077788431444806137880135732024428948396464375250424782417168888369966158609638239431901010442282059795699570393107752610578035815197818486991097672201453072655605066486633241439079874096015895427268636117329554110317588705816462221824401416576772531519169526895315918144214605684163103330583259100626670605095575565883512930664960850343318213280497956096890833435056970792461193247043110745428379995394767655437854728011631502071236477921733308183707077977075122583448622067700402932851119815776223332162587493707332599932028581614306788955998689861029593088000, - -11764173586697560445575293961208632127747286839461437234327109090013974454025550755922872713824862633624932737613459254264791458240147173315162768829269600559865527854753012816336804252578864602812781222439641039272099596498272955468122871078556635128972477635355213436074540479771461511567159481564644036914537041349922670032738945868420131555422169670077080316484777033797185632251420576113110876630786180827349490220096827015209024998892098976718324525243994637165724673124032907119937409069775007283851618962043821753730510120471409971159592245165707469326283731027753326244082130530601346300685633174838968240253645117844881874579457478028883890293206629548853911507644459068240059765221184202123416465029631089763056772403702703338234676768222241405202488873399118202738836363835888407268961395345147224281936467572600077179008304985538832634769754209525528322939422792472952199788643454126525376999829156631737034617143198880057729246416831435998880387908322635621198351467510003756289608098748628710169702214080191996896801544697380913243936387642648293888396252228201059393360328339788955501980534747630752777383291217022057972585118405813998819068350563233130160959588442869317314420767309339010229721916388232688243729303827513446697150316625768046289553346086597221126564251129659272908460220290703398409418063753617345852420431480094043555914505689579802883722350411073569616757303243723143014444182328182252289624890024604734165262942076012296110271409475048915428345554338753373918899528097992813155236755590027635034628405032985762973602679491569088094966619110504521024385863593152893585810536791792706020773034657772536595118361449425208580987002380636518543144744076944701415542760922911678853596539084491117131699413288494244050213922507920933089334690874733777005647747147474953207815807437225763829009213258519511657620962358900600246557133746391779607143672202913171059130911018073568226072372133539203571653523657242585785037967951418471549373093500932757311652958163534750510385050036030734837920056451570189443192259622772569693159417632835152912192355789798414624932119688508425958685521703877888602849164791716429484081599198578942809237284840076222434253167682687035931273636469417570628672009688641076828619896538672639310571984357806084834703710121198825431911744343199297150672093690121118718492540611171154168727379157060298219694905445128609941850508600201900920157911771899728278911114850346083307058907335251712140329759172520366676454928544755541636596214985634772884982335178481745177698656420966717085179034028350198744368122599347371254588173686284985763379743459976369536790655767921322543902763282306265189284181462036948216850190242623320253794161573853224176048477340027454585417511227841097859601221766357909044836154092452483355412844231581523401994471366874319330922526499807984860977842280059134396486572855579443134470512647853780054197909520168685312587308715357567912303821134194781630227187107637792068677624163532005509400943530356193780400144796540299413025600767273089806630355613297070055209426858703506071306997360499878123454886654705525885748285814783249923476610525768893406003765018056961847563398321247153512205440412734033132593767630783586561012961079610127941143189586843811374927330046885443788242596856274883649194477204957706976412795167489690159744711718679720189232657432602844065326187215654427691384495861626418627803858176490395032524186438047136675481124617555916698749900345368918084637899534032845311529923486295711891511719486241904563832723580063511008292172320393520713662646669968896970704206440550870211504547107561099797575036952430084947637436997186704693161725641977572568834249849227788487431641765474944497614564324860050394963026311653148842915947027251883556737993583888808059263010386813817663387052170078549428953517431468620084028765173212798662300985384782569895843550727139349646776335183573194516881176703309537663130411400733222366336297971619021923012054721603175487179707957337336068583343303116707382587842454801570742482529720212446672485050059271488461333441275179927261801528428012143290772749808290293747071190421673690994015196083338208264091872670076270794051460552918271548458758497438439367072242890791038308214002264426864008197320433782999291137439544269177853668173141598341170771623641311850721790634050915737668276079015693912702352776962660867587364284651700121887714765959653162550000111255278689699350173782171629571232716563067383429227911142660179744049647408515456989661101693958893692336535984596603732546537693152220512647817068071966799027813441274116972919663086751304145628406132851018344957203107642894704654554731565000348983515769990683984795912919775865933925330318650980677815075751318656322845995846901088018421090960387505669912986387184694515398049658893638001333503900808872431191903821000881800133477059634799821602824395134678458851241308241559081134497031601873805571549231894097361153105250517130965680128, - -27493799994360287456159323187697626483501361935612644737064929162375459846475470948724066809381291767137584651725008527865600662406964771639922951968732961413283996838711100290199728303616147388655789372636048080291448633610592427006896462844342413994867732754231442775069072609777841828489372527562415476784013318867374391908870336926883419562230797467687888448046908272017630906165326309567170908632791898102633617172146004196577160385349829853947771747458554956201114190928701324872896651658618297529131784398755280005595374385270604659768966365703597593830622274034122262045936446876207491212619439588634680985452024188693269166862568881383481151954653043700679404864807396298879408269584080468373143271743075528281162864197124401442237392214866466352768567835203830416425860883781701357662080314547897773857823366548798926162117243749779481085433658974233787027301412667056058794828306714932384268182347354105858848438043909407866101746980392663930571682669815246903782162629110952334465804988149971959923057826621826194343105248006604016196337329121467062320839063488641634515494484598648826110490534765727061729603156457816572379849792534158777189763822377299630359146497226915913961093678883592252574294885797843986497110084509799340125044330325357153857481140680005713452754161371340587517232534058704441644078031243269345149383057652355730124766072178661428359642969139077486062372642524327825274034812429503761048776537546705092924615325065773275917055895313297774825272201054808481388108307389537654250162156948860946741196828428407161512744467239299795129893789728133572707333164691681249077736812164711270741804122410347053586025477288756109949948182934842219849280687121636591592040467626707695743837737087850995981744015540219510456455353244558307538076492708907613612001477825659087959748279000515842575851487444000450130223819766279105996948954804464607245843097031980256889099995675322700152083829394981132470099188067297344520493458082429544370268100825625913644142516422396475173972443597243743951588598141271939761977804490072202761009363446274300088806317439721764129272691084693886384919333285511044908942707771948232064780111879423351610267984430936284680071437501016058735124489119582206864938565174281624340330319991569424187886314047884947463840599438774211446070609321091022721116911675612073634487612412127519239044494478235610567325358395933301563267912081267960439454952929170286867987784335198889054520574109347281513733932634224491967410941921917458232613808047379076620659344416165841510056108724679168684104056805017095801975426252970110641870834863820350404492122336470921634631195085465179117794680358800107296503509379125589388465179628115059425589527494180594214084961092078907133116722616716066964437924306110528550924086844739817289792043249637015240458641513931724069989831048950017606572002313950809403384841339487912996291029003856208370057960217988009126583627600436908836346265992466023378664082193212745091955789487553890738002341089789506285381627217361550251935416470855482678897995092831855821434166018676895369200035756638222023853073377633500985610778605185402440353429957584949620444322530236556688561655477616950393439517175449279929453774730337904105052056886410968283007235513746545938902277386059608975945225938930711394995625935644519501466653853476919877664866618199932626050571924115230728808625024496245695340987322155227022236269137134416245592480788822130218507922867191373616919170596126951945928298917502974115431306126299886465838166692059992197134537879355647981246463433355789186938691244435092558974628100832623742464210635233304901260288827995771490298932871361547428657599278694098846306164289004875057118152395444812154765324353117541479666079826756964431488254405950010797482635342182775080071937284801109866573789451588058028298530511819647224740999419713029861190355205917563977583021498054474366035065687507769499459522514943049877537574956069594331930702519716973337500899658399354473812369611257130787406145527719441866485282889868726736272019306809378868175269767815177144451197239608718812054811282351000689811907879876752137969415087916848191068856840601849800769971961367587724715730534266129667805331831667167459569394968553047319372692826879527764654671607599847977238368314319995487923880853557086324221955822389373983634929427933889094450258742114219176819728193815352766887211524493002208112330914996979445528396178988294404575822150902488825451435609987698844873223062511931989895703576603496142613160553364025759711121971783600478179703387205251072467465059920577845865339693517906196751206084072578476719024162998911104144158402343342325344820757170376383942234589093127434792441659691156616972402728756321315943066459254791058884236148300244170058338788880253008487384359044549355091101411662837118447698410649497594028518869369910990528842810063710762956356274843421514251981334705121173453612116485358602454617292800, - -60779215560422499643476403660689402105560515290664599087826440901602009927226320305873806309829979905687086215965038065906951677990465266022115793421376828326150098335840714801555244867676274214475822786038798422026652616161793556710139781285135328629961283451912641413345984856542407898405401532255572984045374595312390598771802560790542523304344272863029219746073732740150581744226725827362774352151970780558384077648663574142416096915110190085431193738684846191877701302151780783007173165364189376796602934908432849473468449763128407057211055637652120517689463913401961126858045667929929426158216812196963978011141589978995320690897671878519287232538681577929820873955572602827408879362169435874357950504421255222103757143880117490072207023279199450125059930346585875520109601749819283801648906824316340059027603575914605526171470156203646798301035654961487132553847097111784953980763519588974736117829022530512765385716244149840482866344068813082920460179325073125555755468601401009880177279075769299649567425900889218997664266587901166445545748837750334541773838618605459636664252947460496775739675263296409553731435172537644657916030658007900304723886165386848953843653466110313444483299865626775393065874931989382683886585628361583392896323312780712016957137279560812856174188122921623549777939928419827550228884615653416992471995033947297585996291385117708902636378953993422942665232308044063652147899321000717348716408807349166767829756449854997299264673785067091812943740483229633605570587709403454845604333682618015224946933670687132602815348540046811610340711545441097707893640632250240847473425325138930183610387346646727249767987087033375763345414631201763821968434619317182299326175300024778471593697094013428000502795137514471082591370418873129900460353031714884066361622472340661392340450209209565241464984164008161366209287935518229820763286918047812734195944362619355179859314429801926466128701108604456152700297236375123668728033509487814479159949913696977165178849088569761959342832418626360649643368387699879858085048340329210973813514974390625876982317186038146410193470431790774877475599642763905425040498015792840480659390420078927564477858282520446235038518273722818704933209235486200142027707996042074525476336418809370965483821678398437432178472218314761331901962592188426435275698402690272817031863697801447236858339506195114914809010471120435935545005476791124088976091634731938852324950079628683773952909708080613633645527576902748306531750398907135141482919934959837764197798277683923672207859340563372379254389981424406732849562259419459208504788246780339752602715477275302031042446033825615492587531144133973930580395140660474013550464214524670800973632788492031639462133788478261120774132451343778811731313786529616281104157212174746900382970843511318212304351446453077070800694585792147446712833766836092352750370737479292825756118744364666971064218101089511041539929652109076881464732942441196559114511301060315410811329256065449862856471401166138957436525271065334816317409886948534324938356362656727853020039293710509012074597608366875382506709004257570590623094620750765807361329127987402620319516591338404296617989094740631814474605251074390095353602900561058211833954752743451686433425584006887217924782634704958221325680541310111466232393287942487840717909522164824870184036918238373493498811346949077073056368898190521656294836088222379673831551323187547384420029887405851734007435648917573421402030280741348958389078449924672083920866965669267469836355673833043136482640478864391841608178882307925683601316475843593399690206100015064931343126494587390733336621202818448515021830264114173204850467307955653094556254353159978780134336352480566702027248348827070475753385604614213619581805479145194256481711120383046368391750889594235533995801200738225803747955012122535613190540319591238610237725452060182593719602391116527854052872981688456054352051976909803439808966242311945202470358882466290625292267632555594641340777728843064265263027000775011049076140095638355495214825366273862391940319138315143304042030231426639225056792650460831038235762611621599464292761855992591961419321816924058726788579196800305970487315044640889482186276410555861257728124199066253933370022211454690322311028683225905469452513051238130602656797360664104139986409680799358514035982110900431961150375209769889429361505121958377880349755281196611990005202369921028850193471083731239231429658825725154094919918889773112019345951636454228427164774981476865837884835028926282692222522786063766383249050045415117964393883719216491491367590638939077585634473072970138895546769745694272186684661460623545356797050769128956553407157416146288778916023481524411333456844578012552742942644979846181650468763009309764202700120334230640993776768555643121568669544194977160515574772504565466913735423268997696643792780328933244027756722225604496329673816165798853476352, - -127079728763831355311843418946677378693416172192611068620379217832195841149953758971670465725913631630741491124972760548786487228545248589283382372651488248231882028411356717027711634511988526139975155248270933862994173482979112570423463711416665292013666482409537300316191677145742696922849146290893654557021226618055664571881616905836877354486863693479345895188573638819776078210170446989470896390610640203318891108888697740909855721936594427538926191552339699532241001798505570770991993031609227972741961819083728180508381077009862472351224254936590089649865176800635919898391861944364313288381236891647247419814090554257693506234808819501225083248294525009284933783985464486765686000859471423114992364386841836647024669050218205404889196787646045022560718884678856690828557980360646557105285002350801686381995664438410589361351566247636841134522266100535613442794589939182806911304812509789100501474942862607385240820198947048217613913189287770389864022937655785412526541598318818874120980173435353002792795131093487137505651953676214144853153459468505678171774540457931415991093506356117797825819903501906585558136284193161729672466719004976613002188088599469422955831237091628551453883740646076369340722540517065519151517477223822518158044539283141875401879739642200941098551349874901414314664125304789105393990270684436563019589500488057221155053071798773861134586531142302870578275234736602004300402444109821976948475122545609030834591756394454704750328197095254393987353047395109034864502351006088010900731525695000905230339456002255440897411123804749100327668692749775967118826903785514111867595281655958882213215461241629789447227841784597975131184616827605715312538243237098518444060913078742845093155690010110199253375256179606505210000631620631389668771666817067245142761411282947945424557537132997749317286796755369647846199515563278187497786721024127859931362737378310487002403155972441318851051318700217242886481130727350427924223513134583809390526648198781654098758435898746068233741191740414044021902504744145553581016282008067132635337927693030854268232870269451467984328837065293250791025595400281687369758472582954091768503815294160221344514700158353355556038361618519716762087416695295232549500070210137727538672603682792277658336171528378638489229817448435971655888378555939039630355004283308741947539914742198100288740382946582021355954105747185761754640656707782624726109945459596741202714288405570985930197869728066781151561545114383562988287886999643736438435215691211318984631338262677443533499217017609972801973579349798860114415879800800154933194315562026698056405326527804898465913812373345458079907590046118489508205081066331779633238437387471886841873323937858782204949740398238231620787966695991439408814219083532197757446857509826709065472300560224013358964178117475032197091752333686713884833849417011423851471396297751171804683117867690755084976271655524822421254166187326997927252981891864364307847645221826107159918601461998565886988035756923076144587851141381254929916259707798354561952435120493962732786993704000373587180536499077199947203353574960801651496572703600357433875081877784701118645221321764414056080724029431037217698967409582821604488190608543031532510333887695854053777656127099425265375975608801598240549940302893279493872984389109936387907901938682770060175560760339981884215473945249175958504978295195898250915782989540332668698412466216425874166199455108435891056884307993566513544502439846555488148365348756371921384623560409512499977996014971072002548616709062328904754611453414766730408527098796404842034744715419452879878500027254680940963856649536245507261576978930841220472859983307221883356552756770557692701904656399781863722524079317279250525298678013141200695237845013213550236718945672635049536358433654333506934738141008191069674808986009365747962974750246771883713850280314332243939920655342362155350148851236188064684237995378507749409410102709035724915530267365537207957150248595333401360316129391932677462806073131820421235473981667153178393292062616450482241962202255262262066426513433514074986345278692531829448483576491097470599930347385379460021084995055586452194855967768182242049024535914245732564327584316023857481765895747094658575451753339569398419540980285875840828915329826631621264235043614351678615950111771719447906635452352006780828960369130203749458274970011872770239675986648223761409695432919473869836017373980274076242008594119068992201401584043278424028925977221375794486686112740604959279203977448942752409783484360928902106489234003883684405145311957819977235126011832044241653234616507153302419742694692101993845044609321205733448814133148613267994188915953884580831957272726713877234544937546829251905847594002642823074343491670479477856650205855120995526952433966472765409321744727431991867131205414505467320424066244991647069706755354853122362048512, - -251259745652242117338558413557740662415332459080409791331392696152161253425808067832172688245812309455284132299316380497239488092449635124896867663899793739216223962042453681599653476913699522473259892262634513174358090118165464137524899882831884281804153556424123497699419533160168267019001155792626290926533918714334847414597301207254092922532801307961532894934547840667714644187997300928098641445351598702527347569652888929872844960986341271134561285865314040479731268077463198145634132101381561610036075087571019486937124702801458092566737539074768618436074740678180902537714282621345456445531812416461760732339414888812436468396639243514622629109336962027439816542684670054405585875175360933956304257918456092709750042690809873931545973766668132146889330980332509738349798077639566113522053010906915848499987152990238928754444192327187579138852499859754241008145903451613975505706309567629463115609474145860110465691289451892227632050721178611881190379965389588976902242226248095197066423306329322882706806601081782947278693520808971321990468299189826284327774207052988886500562205262878413824131896139937714645726501212656701977059602709911941893874363672341499151845763959228247402100186765812288807038152203438549935793869448468699624038688339897638487919804601504421540235600787980414083650487994243940707368521871103199278925547700876854556393397275464950579671306166927591363311403421835042245609018987250330346790501976393773509286764745146336259788337528430436727523514764439933422984513782204695909842604717807758112436559006047714912417027983147537092398568956283358050808558993244558530896905426636404196097902812159746178499888388159431544858965176216388904578955017908363142368422683255576324748525517243623719554228752149431153783521955780537923200070104841172365472230852891309628567428052336645019832662354734820815002458796242319969158617665650928486952041676180170692113946195582408165595460728152398286595788816399298265552323567813169831660110494352871508988114962053215209382097679222760533851049654320611418906964219408732659993650068736107395898577190021667082339050566971701419378859512163676990887423833583006970036082810482809211212098592428358706087430984124407153031892592075387929280579748769335938911317591698080833315646963497397504990443747713511978628944769022045633976786280498768506533279440065893699234832898953889424941808610924354883571072356001667858176725286272094384102800658664840386263712991328797998413122148361305263190542671365932557553439640272339178714624999971286632818541330171136036396423986115513177311873894164648729813651160277962729529839930595490477053044452765724746698481143738504277251245224806249498686949697491459930058342635893021059709500360407447384122079482368074770693838858210047846556964115032832686467840397043481993498195312323918942236940594759961665815926840247343081283987076069298259821113345659822490873085292038671843618738371714822571877263592856145162571357596894216875653554191261613405041347370309016420593279381990840726978825604485155510585745805656327992665038917336748659537484826240239625482251662529458372441421732148986953153547558936824404509933591603558633142850074410081971849006795751542153678796256360539870610116482519436189982648943398250083116251869378492046808718983347381683387777865326116149625574683122855857911217900342492221971934402148854934047316001311472569274557874771797890461109032142780110353135171519312707854724139806756213754307899277952430792487129660521600857685466768234472005999755917685247645129252223305803141519707882399084178383218225089673606054588710814783582217153386034692107006020714039957949038217144057074697601661709259554905304183097113793109680710981348263126103962373579622333839461060057374772609031629151357941057138329783508332129784810135760543309672055620660614431984564255432808415672640569581569549271138933309291993871604308983398046209374273115217292899997990309171376086136606922313821919353663414938053410684861412723820542828981889946606258102233239335952678551534699262308580928409048538728399806644250107673666899036165468986029347148468745677919803897258731441023088646090586909430419286387403473886515765644235551819048721804709191169602025780509503245112015007951759042029309666751397307604929402945947627354416157081180573773361573786857795602936031572089302460536801459509017796710585628504701412903158866651833411740413220630853572892799393403840911877330050180816422672081322859195402342397622560825898517867522955544102705685753546389133953410842006385558298579586115910342400183112775827719775025774857015472270640828359165936108500534202602701245983690577523095268193712968430989627983504429694969392936047530578248029937238778518876861208927102921010359611766261925125767546536662217338915447610222058463345661214463414401690765785678523433387501782084884627456, - -469669406753474234477859802909573048404812029479089286492709093461063280560943163883057247526824390271526927358387807870172985805833261996122432307517178935926277574892154461940602426030280145797973176961638967332684182328013669720281555946164534205427366946902903545124596288949375697690853043044567953098749693297091312134662940698328175257741148405016745237222948109062870564966387226021044502395395885892406559925747438866004570365354282425741671910427996193894868577128358507726398830397726575618919391509081654048994022668150129550116353023032279934941419546056226404362957480964868328242713641612397246192013032661067086512922803610707285071178865617676756167613583677246223700523996856332154578310720796111673548646847918204438664862362560748117158681106950751437127117135418864783122561300748556036769730747245768738098867077697567839769553895230163498758057837890288088145742944036772770836601092293281441570506329297919027398752630680039350659785564474062712949974818753174307680966352849004798543513110938324096711111689645405837544363903780586966964958652599676549484906883062612065090027415757733265077248986629392305800605678708412236404905201430274270524620461179837883987702166051896873164546747421670474604507636846442756086855816250031497873252006821010535980162120955647697761567713607411919091186333479082299026966219005522314606602630751087145055856000597103502901014278443761946494202180006183770528719159767478528830657302728426986299421583784248015820261550515213767256947954253792271307404835427453412464914687207009238289038375812221894224888723759512930243678210809713377778444942891606601935277951676745600267833458370183254624145741200225947120416778686833930910028140242056819386359134577010512003463738278543942829710403738031393563218697791212798480100788657732390769503462911500420078140173830775022399985608147434544484883551656659616087602704984404825633908488788965241336180319828339357949084225188903838082914520088066013408056962289948783995071232525225743124622955541209530136669679420265156085059924253517002529176845128979036521149933889968540053696229212044380016762793149088530323909860167165074663063502554991512166911565774239957310157987142086911779718357565815311339707712494644501145140100132030062705860092677928810084102820490106930186142620225585329704415931235024923079740493311489257398378790859112888576614354480962748705820928433174935625339290253960900408115791221078067678809983374064208674167459754393843167563133846870204227109155524511770192427848661620169170499467739594229340603563229574224101994922195513038693084203201054641755559760760919949923798134137263128311905619008028080867261596687776144919232061135708303897357157175570429865884873410469681471850844852385840389694600432951461892981791071784523261136906034649938750400225240227379173981215578616711143192344541744695468034826483354530929733079170801904888582775754471520664333699081106264216227266580377683392850751866941477498908188964874771292202571594880567938422688038623820244486376341082112419777594689608703929443391398515112504973403259921688596037599978261224713493872246213843006156076074394950877949492424885934028374285925248832869315878845702197065094747686052785610738535260838670196304565317879622306956233092682932470162029434732136031552966503102854965967567748385262053819941757453436273952167889355003909294408115721480718373321253947063595538052045492650629285207415765989337778397951033821730098856566669624251290001688725002932399464229080047746642198306897171761116979811221975094865324794206486968660244854599852682034294991934134428025164218503495217112917880685007204577063970839739822308808872548954394932431595122691958576213313734007520500559954966698825102709221808355956527653076086778408210540436580432569334595289645348908249299619227313438785243140175099478737725038250486542071559597730831450630192880906710055580059686848335971476106403427691252716816156130197026703581459211220890097984479752043182220396167364663987625689626929003309517694847429186082688421812742913004339380739919493405240152722657103841505643308278376020860519545842135258268689827995010351509235670348682335503714356468908558633322084639328683381496481660688854134951835758275214403708006334239997389300210607333631114672133681659196783875803758957327131520461971340277340909554930284667947145844948273805663959518270435376203622586410872497809066086890790801521143312688752123297614861961343352105347667988594762186719102927472228728271766141627895437728646490701657300483669411252007716078154696887924434263688019874583041588668481623708477186955967164796704269081736658082762869325760182395915322793568174955747094703265723175481196305507551150401462814773464226403596353128671753576441278527071679037472945737383516771126590667828129116228120772387799040, - -829766447058279001795422015562806494007214894199814716347138139977156891793857073940546623528582700031796235648105124186561706537145027319308373154605628194876617880657964615833629043286529326004954281714726892565285636097499323615175790823392722618861263337278071283683107970646336985940313601286465110929958711083441271339400736444974090389254389570193532745180054647112500234126324296053290201593241667598349791588316120002532982346108229301781244346241512804488880974816864108507073680417602550218550046399636303934647399029000945477697895101021659727585046238048364221244324561705034959784409402442842911133112511819856588170403450851643803230009959909945850922273438691029081196971741018928825852739744129991326453812755871644358578977142531205638252987613602674164379360582224188268487451162683984650900180629259127625438723287164390689366078025651935716701617114452294452984662037354457829595732704028788126787314960196381736847820823668643718104334736332141759831384187973882416060282636046469305724458259488389555867344676675108763606949942367590912714738124377576471614570455653004764420550715585160602406847203997340255438245570683953325060706570978463940577176896966620526291375963639773334871663818413970807637712339258750285191938230883759789528371141955085150128517711382418992662877554472097649642501247710492506852378776521188592581190254099763792645117700306657891511722327585329466194149282888152442063409114974330787474399356263785229812448614401281468836879868681906295991537868885911244877915669709921824039509926342754699674362280624034979700509284463884966353579901538578837393130764281745745237353456803561113523924270593420414975464367557171453363646549653705324472343503409817555438452116564395105513020544634675976130315637832604273206302790520285091077194662314779515450180815761625919832343140868108738723030626594393771238539640445758878088442311592678803806773838488634129125716110678831352616773635836313929281810633111562313428368216385687668417253942132023438523951983496095695948793155801918697336981473416024238635643357966145765109613685625833139509783045186116861626260240509820776333966344437960641612041730830567464480803326874200210488637733334708772436354290939351347592907518756711539544753556827883075951370716895643088070487272591857805851593708216716811080499818782652754324260255725556677072443560834693728151274572772827689892938748653293897631087248971694315138375225909743974859535527636985370197600157304565958332015808433338974112992305864619410408020307659265254694209659731111807700678926965346311301012827306706091567407318321815323643919593999893074548592034172028844616615848595232558067332742708736233753478695207978689073949468699518967032070932035649431115349387666732087955275094706256166708490734678549682817849851932685049984016400936608044899031412459941824283202922537606065045213279711961467331636025512676526111171184112618740090106520393226785561040451303927712159387370106893929140511124992980374299809270955651578549044285656173131539445123760824197482796335650212656315849305062663062416696964357301426706429249645887485649240351978832183639407295442990793970061348212624483437909497384679409680827971865753670018699951628597963696624162896596204602235020151987185559343590214079120865769344930864088747524881087190248346308624063421168669438139644941297087175496785699726469740120359320579408201309708019601556516899130164964766961009544950858621331161085444659280375569785231131226722954420583115038770633999536918612170192962389514676229967703798546007278990722547926710768574024686417686208695911712792033945940750702919912895253622359823628808398412185131985829273222879004450910925391741681814474355001255633850008616638815935006340700422210174573050954160639702543617673076694478605732357388570650367031480141722127037196402541018679330372004363936260967550473183815153416469057494382825435489531756396107428849765887904682013078653456450936009206298884000279555599245415261479016477766527099959899941955277430587334380708734901628304109809487485973400859945389480282727359336254296146300888490798003124144930835736717925262334408664997049273276165904712949225181305008161248711544575613120794920192035071765793166683409848413534120192753797516235878156667512535697010398526807565542493687089857066815716560398557746997194010373967209054036520534844872989901630105204374439280806400166839206491147768543776492472221499314343969112455377484195192488474395386209069676940392540992934221875829243868779316442530022491958465677887711701090277981127256360993196480734957230474961432530263415699915262378701331272686771135609047859601403244369387370016178671196563414989094068695278849969788572563496447367251664908028235204639128727591789678770809595403721854537996884329719326090199040, - -1385034776754160104264615143563618296762557032448654026721422145825571895657227688226867828103565702158932402426265343200609625387045393999906569329054138986408138584869260574256133976756070103612493082136455710049496391932235426181663491387430750609139618935585944211236477779699280327025466248316653539636634814088770240651558379930583346760093889114143705563271604034648116146117396796972216381186226976612680821338129208649601558708021271020283920076727624843959328105642629632302667081057929406246135141642121840843342450005441293681228738132052626455439518380518117050006724354526538523348984327207056578208686628199003437569479526840314525308297414296601078841014906143528078428247524782669026002103162160374324117169312485783076861994884810479805451414322857210862523057001669290147970035014949519293203656885881798451374131470878176778232291510037158364469971473433781076849675279221909402823564647404727204966570061294600097927024781234255123633104784654725642424544499985136322262978039313133389498355364674005114511566768692022010204426697096516960195045498312491593957879017401398136955382585837300718876164288702279239321059697104588343956749790341486246762551631016051472015258400306836137449752467248949486850221595028433710013063829043918215213615621034337103704706002540970310306950077670819536629773311149578176918811250794169970139936667727847972662132981554968405359770007453030045591595013769762439812615383919486365780964937652784471847900071482313067528994860151999760343584001220501677620412319335457552606604134429040246115584329034136421504119358334607928028897672367311607187004038575998334240337986324526435020701299111537278783799181275664164835815230683235888232184621967789510097817495102560971655835920067665616114804001165463476477153685848399873495775014267353765470226001299954751225235503003084969023607850093643779628543715809514442571332713359932301409349954206268177892402715845133558192248711814458196469965643695553820171693524264333593015810819839402992396959785096543292017174122801649073425321559943408678585124321051773680701070476926794579655117744960221878191113921446395790253164537455910242371431944177684437967479917691086829846513093891947403958660504453659170336504423447333143662186826880093937181790037687730703124282678556197906128413364231980560588710929043837675739639150894469612139441755101214985065154575263168764951063060970937249405729088275046919017449630229420252702161357031661855205223953502808337271001339486235823622845099030251708761325107003325270924729623592035234226692217453758344143176521006655475837757138639862826711770500973744746298291129401995910334173155931680893833148592529208111584872404540708086697207633802519339569934321164215916242309354703023315645235814567509873330107883362509899227424070453942203979165665995684955369957766445622147871607739704689511325903908147306350604734849886202490487552012380704330517064891403868826232851434652706154530197202409253473630650298680146227954332230501038650267105425807585827499142909387057751651747241472338238958158052315882023685104782076825066773725919445231371153418035346986941819064922893987206483337480556434036533552556746360371165019791541314783003736830116399495047121062613608229537493994206446957549109390554265746172350467532586938523294608877419534291049016683720993750918870708059946543172718003857613997882259362969912395327911622303125695253642645648156981172324665711298661114972997453156674026344349630840181803635446378656126931224188268580618769006425328443395298557958393744986691652307778281803740326392875218345123721211799698613647020792003704177581523805736670499741771780368436915700149373220901925918175159856535699628209468646116913084242404491816514071936498699941185044262438137886720384175102477009756451985109623501988198915808903496274429263556514840767195621669263857507568149541530650089994833714124966493882928807717698668668637247530595571044111048159761423209035845334243653676064051266136583799662231948316895422712599561962217114301526769122659755329717651914358240232959127650763556347614095173750740825731208226329321236921005079459473643641376134660973709634105731370961335794414353137408673001831944652893418798111170017531826754024078556728907630137794753244144796055650146688368139251477440903136943597853298678835066966084577238046512955606018243198574994383848353121055378488806263956124657762643609026943146750593297713378175662526818535959835566578484376053135101577396347687707327834330945052194496712010117795866165620144887065956565997105820087891625043006649837627526479830241240050629897077270123423332785674457266451921941153569107218386879927041389448716524128020993928092522824366526390563445823398399634229181905388435964978183810829504217088, - -2183383480472918019038458054022957026437032717729289921221431557617666850562987633699136717439679056592185603289721962364492344556210540617870465322026873391504308438060451428127134241093613736723720051657838642778453265778209498184134219415865589617040976547730286403952818218513217841709756165477838029463559169022633111262983879126908749545303852145755461396307996338487912939912174748606090544784654063364824992580774569659035824554806322304875396669166510992607864192735629283604115436920580625622269773922857610396467295908968105357813798734385935829952192148171532311303555964071306192984789949953572332512450730588419575993739994937801371706819045406284693441556787542441160313794880080531643779723236725821342622569620276960039950838405846299957437729045504164714426628451836250503830293267206661370217432376179991836409838158402340188581634002710372254666482844300405794981624454567377663880123752542775286947102829943315020847845617813796263500232224500384502741724888914535219206551431634523258118218244414394620515708873661423461117880890489494362809480071450438217950371682065186962107808631645738966171595704821142729164089749840202535401912491520971032907807223241622847345629360480859576559151326754231143647283533053571851975890502535317016748089403694455399268449268920499321653229057842232245580042828813718845833742765275470763298849247822575567499233601009968530234501716414844900207480003608331179051917031083926687398769083081073037104039049902696108698931895624644437508936874955129025436020334220084724873570098889190823882320569814413800146913940106870117830654069941679686575822226285927697680891584883640207406438301491451371129301241423749845052806457066933920919112671497108810241671728492147102095309173675428395736449932131172345958176677618234287721291100399002549881247690348426222716583285988640998248210023177614014775432413334125311242174087513620905305797229369873065426706285835391454692763522517911478639258775332599369387642981289259163411866440216262423658655430606315499520418019063277078926596849076234923906125450536280437804236090175148164504367771764815592067142143894091433133104702986974830731767127549427259655095227762585460984111858971282143952427487017207447757133006358271503792318712293559502716264117449407443049153102244637615017317983877316993663534655603804138719823995302010429748605865228459356378098589284309391568502386135417376101095503547899570328543627134169955067554965684234103452551528296868069663844036357544910656581949136120537618190450204746440305722904113278981900674869085875918067695532090276963703261612232434114390657215833159828239107249074535763823480175517200036425142568121606650880766753188042629637981156005073736874638547546489198167275924690690550919446273364123584974604126902951823268517703242658107584664493020223827896482353647902215713409872928830887101619151268446203888639140833673853817502634929165185615030489248644388440516753735865556602739065477885919944617188642596673380404729181124826601239056175257430682947147500959189834997879224503979886056805001770647739002621094109445424678199733796968205149552777475800427228415722929418194545558739527812705580056419795599265308355871557034436514163604212297856698419203624685868963561892348480733826780186923049144639069239821265943658923707388883942747737561864763986486991936424738815801613863893429719159906732537814920382434676128163289929249629360992507870541111840749567114258792319718084525163937873351796437911458992202005343700280117158311885108725339461820038247249918696693559410925273222354094770600382019667733920018435336365734569510431341561289831222795407690770721588545577497441690310357054914428406708667192118615792541191298182294801115816314159358267899020988588656824167131043848329525218893096485596066065628519368790476852223292462041285688848095049721940103061064892000044966502161266349530969502822769457196915383284160552568357966004317884166641018357829620079119241734087054177317165978284567935834408144015663575303748045004491563412852412348151142856583132953780971497227742330102246184450751864004122324048949127049094269853172738425123454880955710782594603532678492004007573799972147095021331799384493980535173301623428588437522749762036240255471462076971042041688354582314999902973091871087093621822339936894720571659099061636050021245326436083840593829366753115160601773143290206311716430117291919268560533421112944303854186947224281446203128287651456124958770543941362769135352188957658917498475109908012326134865817805740952813456823086836469413199132402181014495361032733715567390023670009055073406549057734501829967010380051709141462630448285238747780595794626150188329308084834726014329041546907301908010613676141707264, - -3249108556714122411898875049774918867082533018217001090643720804543570979247211643375214401657915909606712719133207652381437820098588509700512356792680078300289787855045444907024528011247776506683621914446181526407620660209946981276598868232386514667989466946173729222336329999652186934825856812438317955521602388146779026760869794187489351214095394142044398796933403546788434983768197460804864385647967988371492526759797302357220907160019765217498300493962078958122600093228948141367532592287853855693962678916567528446520071943626114234956757448241443932753913389303284457700050940765463481290034451879136849429463324998729744936750337468849326775631120729772397446311990998766793112216459038455296197706977024482422570116948646995171962847857954578906572229594618179114581464014127041005551879986377806247214458400319423620069765719139883313137300166238381783729702377235162956278538604376510953282043837076909132179862214399161369354541758888981788816501367514590963649833653528292039317248918148629705483337937803803251289576570315084915146575318430320813817481641542088209033347021864931535293486307545323346251122662930680907894011636839772757674966091919474699658532920119788113782220977653624552825625158122570261208698269739844686757886540000290522779705656881885216747436680559292011563261041420450387605651386678531808877449421385132885808062176557442817641837154221729348568667536893055006061439419883364638022158563052904661797469374645613717502983075258439653801962178044374580582686677903975337092637929355027873248084107105882243917361489422999587469880967234971981031428467184846803522696319250494657287101404017341598715152520873858897765124600111434347098512379465969817068378952120306334962445912204858151724053349166136974224122879327278768429224865830329304413743327550616284883714504803624842104175139866063301282861185387001547563972792069796393800410709082620411474472966913299057699989615343147530490042612669391202221355259803232883983900000131168029395970988628976227094005463719236438291049208737071928419528875639820063923217561685736050326330056839252704270158620891032022845248552531698780325609460836112705167291336405096935352285811191417172798624424498277306664517811830962004627825483593350926747062306318620922916637010093268005455467293827658349931803604506695807814301221727911614592565950767877449293247686741277324760963840435683126541959276429719964437687790785981824197636041997291807468315460709080263044588118588207839457334275585233149548814070684563055841434905317799728033334757467151397727155163512898381065627399210449229224470688360135360717015032433647386415284784922007295237334190187382082139131403143072943117887187021415169668686868506041191642100236798809003241128476218704631214439531850899818591921098609948588023625258896062430873497754445575577103543064088605857343162479796265644874177359446346297618870580607085972444028624655002155488904561760181767341322602751730474706925035986573292708069679497496844711721184404657421598572887732755217306100419343481745679374291089213175474730846240384224456026396389806323566422725654558681138782572094878285818107142938057956307187051929319916302894667538671084361710489627139850338185561484728754073379885016621779259796024319585396452300245206827438634216087056363732394225924390059806864249033977447794080198047687485944273061298148813809280112255045941176871880790931598727517308080865049014729666471683845712485209863091544616830244790085348226384957231295614887024814998891290859763154111601993816042726195573943176312443589668865287790132515186135368344260857535446572426976521537636420536846128658777171620840844482711215837297928007964092517928397056404117709365342285840147213228080284874225789829745789329899809844965883959946233121216764680175843809646689797201134629062009465355949611886782019000709036130066686962210397481559437685363940701832365414175837424071376297657615466020045615938612121528688529324371357262868657099753603319942652544107794961005811253891529135484889455876547649916387909582618003694063863565968653796284525621595126052330922268708734543173222847551964785690629465740659980799861926693987716051705624398412011708902743405884780120465494348461562971610139562156630106453470555098943760674584902542996443302590146955925279553530965670325055989435910781186545550045975748752915309032623855100449411456037500036030839245840545460852055342467546351076759146084564132767810633314607412075299396200869028197648209718616388485122826926397074492620890542403802128781508114879637925671136696431482635482471511009219830403154491891804345223017937451618633255302484734504730360395079862339999012742402577359834018391669326150243515170291712, - -4561850601670261622798364992944844462353106104652486619183684786286249290051071406605434993091608974478253231700974632885987855119247423834577969087145909997068002971523976875593547316747537990475021333841751534807848347248855250000431013933445699660475023712316725802991985264859199714783146320711793638144098907658996008678533574049585542663531645521101274755153713449965650466474673488094750370047638256292474028577847481333855449187667454871976986212842031081275262189434798507115860113779691203231813156572337606455820552216989056196661373606653952792997971845511138163882924583132178930331992908941157097881375919745061993230992511087798826619014490167288224994691623754704081043150729233202553529526345873904551126635221568705906117168720029625118811618979543491785844277566318150429009481866203468934741266104300046337946786582957157015860139990173581698439963306280456448529464293257308445606478325726840019219821589108768160297674908737247623749396909561432473204770886588179199159490911840223057374443320810627270244536358590046571232683027344814060642888464734211664325453445035753546114966433488261793799084667921276755026780892807109214363879319061913676366474309730749975148327134109504418755652088922419594149025412100437087819572094760185598663533939862092970532735306761477863972123081824052723106125201884901418341617323744421721518626247965540962117263641569544076737057322853921973651742267767777564473233163208865768874004117874939073744489765413549669859212205295834766359001772339486156000365105501038752805672185367150293562323864908525147215438785313439218161077423594716646236077291280622767089082007988622179559987387718427626510963368407610082222318334562546637419053384635882353688751078712998554134399707967881725336395848328560593444754312999180891771424729436804138534422768761617758669225535307335633505053981622791730245119939046233206020577902258876848660395418600285800680705662157059392389004008613251220424990927562066212358676743662701156807295976777719855384039205110091978566914513480689133098369169320811282594521072914423603918154346823364808186379497558062995946307895440462419593583031673263664096484337679382482037091429256867027132241538173589747010876715333208264301099708758424292031704890128486299807987901285013368085228462799367345990572310258162021756144844220974230780413454813266398361919460366384186837344286319156706706033633077361343675679537279196899268342415600133139092844194491548617208669681604066627894013554935707810677269248001489335132273831395739761036764863839411334311873319106483448219425608355391456008233785537175025322449943666184535755993055173651087493185315868900976661509727006095183754541375345284310333779688348540545802813454469205471483580983665889120505814657881866414595634868889668120431779149740515927630908640359774518907274950766046642876005158537452953291514525979335595991639399452186992347127618538866568378519378850904841544381536077429172036228233776811462804134332286299114863290481790242537581792585641708877088187975196686686842821010483917145590410576398722691274800116120066031292001312359451540667580402129862402327034146930999763538680490685742989047183026820084444562960084919700595755878601511768537858732012878312757791628572505987668346876784909791304392114545601518891790045634903492878102590826307192633676138361049203157812432550018217603952434048088003090242609769830130054876974130012450850170675389618466252618870607999108634353833722824439959174122894740286618464546353340303516002259903303330652170590612637825482590275191914105381460498615255889267091520348065210520763088396303006959526150383324787332811119043321222284311989341126525278778648900659025843820870893416808147464527341854914774839508563986924719243083370362439353205581449051709656087758802122886892602479365750936604892134422151422154638290630695557172457518890417632954869365884121739984875667652806013973448983801687450668011508388478194425178298100596342844053457669665711271704725371265010181161105528878348931872296418496234155010867621092515182328143391494267273257893522218405882262356523047333398003757710690268115796077732823699665352996728121099396423011395327639325543006319098882135448051344542324436729555263937662120182158320965372755803909240753944768732346071492904854008970292628032848330492231811585869564790908582136118986562830303855407775276800551485357627916658211562369577433174811269221461635475383893388492197539600767141694383020408083183555720492608197179782056915072225569001964734284232985970187504022814524365366080543217538898271342084435156900174885445912176917720815155590270917043649523158893347177389327178119626580336129867776, - -6039708982365597184914414579580355736628133638220872658238233126212420333920185207325811960932513770245914419818128529301251740224272757767747277133481902848948950669849238515911005822853343325002497809276355258300953384511889555848838236297379279000523908416115784596027574109527506961650472983369506725622818336109713359890730792518272461168160077802886524411501574900367468729260966759255090373781995715954262929197326061572884366066045828930372375728011238914263280521893405568916689346121133668857671147723181904275208662751382703363533011594204980105781252602763427733281578135778166768830627774170420001541816668782335553336361265159390426391505347862221772517029490636510605110144409650118624961011090524313315026981883213849947950242414087861872745266500915650000866156347537529328459628700281830118821519930977565020344118318258528582832071367241209511067797091988092963357188720007687847780244882508466707713210445966940384496371395111840018956884566307454689000214639127031242474593420779464255366650652386450254650254732810994311760918661247382792050914296858533687824751003317343028982823926347112925668459517539752190703515299817390540267083953132846093683867476529938500614740891172470626707535841330776599903045081118034482749260805167990358782502381539887904470353625804240157566624746148928723250136492030595558041239653786910374851465253633736004730253372696899066944568556932240412959650275265821668985057253340053076267754828675185799461846349983079294127485190232070879160851714183574662494666081445186675892138377023715586406754454183677481949645318713046758172112057831039403577640536054800134571511681185749449779035478642962295140168504938312150693361752615872667723570331930419334678164679432797437173410078140033104295557991835481313382207097689234880124079694954319633467929565558949876133718347391278764388036235090903509426558227056434411923549296018772954242460738084033990447884623028812982234860814822315139957436386690858162562107747403819896118714173582141573664968491755215116175933196780537224340248404193025756502511771037716752556806738577528209092491407491789234072463847409742742820486657191176805146225946773230663178661342869645809823554930279174344490935645217721507046680635623946610518047500984213661919265350282702592711309057635459026636870074177043287053214569270706302356626156215638823865293356430873325091201858856355162353545598530185811486461328091074502390894249188253279354678651140533421984678429766512887632593626309131651373364623188269962769569466101212207339888610828248585408341072233560410606471675625010233597694556676326266771981598336016706961189451811079247320070702478435011880492221592221968709921795479543130132240081441978316427322555632470834136791753480155050999769689887722808812061194675591596564043951510926734797891695093689217552188237664702931939406459343323793996059482800767319309919949988444014087875528835098898135405041618348130159372719707902746783232747708092430005936790949884098746666299864687522909577796144223600713374306506508076532654425783755959983885021742079577984573119533911726300112102129371412690296519752048563306593910975224061491836533614727075712168916107167657012027543824199479643059833808732918282449400752290352768172015244811904500533713203398811579050057606024871340512125685280062604127560843858830704010045801558040926158217053616150338042777538609952856135600759896987614847718335683878138447276355598161193095055626732233659945293501138050687355946559556528701022391531131570798771577734747812883367073025246846935869278352973209593912538860870343482701885556127260395762157095067188802547359558109519203887000143209406593477644144048418216100727361397858955088979534188456630633100050359534024298202425461892944867128376991364825296763687700001902288210841119120172744103431068659307038467185329543004852341880654253093414063308389402559457513939218904217544236286229652347608713341295447483062795772286264983832964451755557730701418736880839016424322208836536316816482497574151389861814209739165372219356125242839217309743058770187157007753425775537176650556483621536635207627074295124701281947702770777495687090666529652739873821625154040714321561379157298585100349491914690773598026283928459235230872230242394895008637994451918789090564056780167103776022608043704751465134823351105201626765247220330719487051593589042842884658288249602650476990887341888641095025837406175380605292671661339690100204733992870587156830475162393777085389349833855166369828441688555760851915964138987629222923809783544408587739328368548746335968737343890619515267041882926922543947300507768401901693990636875677696, - -7535678867048116958613673397113117292902991800857588229433949504170895359905654141463946638329161314156937736799601133850174809871434887738666426404972350543330405866994325651259423480579331026046377358523616669898085599812802072115360076774734648525706517290443326240129416716259010172175414727317425364475573984441600416217461858734324094486110137655267847253218646640649535544789998362979773336379883899956076375592513751263224847886500993286591225529540680183926042063943461815113150930896957166297188546144038531250604473796868195422118659143912993124587962209946005572644661381935060752886023065427529078029253673409092127839707844917338607801477955498262175944345198304834884014965414003493558119163238146765514288176900927362323958321727847002552192007188321809100720454991314488114867737934346666378466154830316494092368171047467458599995675141895365230396158470857075315353103381581014885476647040365187981928522759249109708387850157351999519521939848700225423480511273519036949565341217050971914508761925345097498809778687721327589953970485261788456787503452159563778369131576021662800870606644203942071457998012386544194257644591253621491683715791111182959450279873443176971379843230203609746330414985856931784044940168871429793784369811830157968755787225628371758080439893693485118405844536023204722986055093811594289625269090017877299182256086387200884652045587941866277310687422496896961131898857194819127656077613892164697308961750911130391643343356859695949675089005710511457202126723970825939527095563316809831709269736677026785979902578770646082963468575865759139103032647979681590639967529753522829045352384614478669803143049867155801341115378836380671125421648288262634046997473468618102832212764949532298397988253360564198490433826262369115914097776460878877562585943646079633122680210607986474708640029529767480099578443657226538429084291461352968871455994012657823632913615953557161205957995017582410007433513545038585467108761366480744508589097818420872377695725201961698069801887454786999590855754527170173272566195599197374124231505249745681389184395633106503127398459289646188538461727957626616017858611023648197219507628841724513727626264811092474181520878358475392586497148790341446908708453211163017724171875659379202361873389490994312763074159603504898205932280834590499534209455700889261678695787893240877948594200132755801344043853888990716771537841981612990555044612369508785500753763109962986149246141896584385170785474999858149805926985484906830127588442065555675495920278257639401405619546778679063440390142948406156332982081724106782507845686520306130065475897745131874767890890826714498452295984666451039843904256131628639845251147765857567900056280336476609548528474417342697231644967436743912824379162538659901088511090873269572217314267442650567583866167402765870297466590584094559396631859578502534866624091757884694661453246804013946359344307304417775567652320690119672663893433806830134197752799486495639970374865711561969725780800980939786131300008891679945190145293398634389599296153191259082730267414552665358350767216954122574105251901177739256453040817785288012684929926461831990828902493385131175524225620764011899231683356762293982707252299059189222992362716205221881007330420602735914203779272063465134750998037784242740003639676614845143427872668415457247816020618783736829034077977960107936709860187183691806833984993224724513109573863985847036119063742007962646678975892154494482297834824237165971561583954051190163884212540426283541690453958491420816234668135665996597748340475808703366020663466473276060127286947680215833583558943803131985453217557546381790067506426097174704525513568736216501436058490686974334802111942866825681907784196048046798296997939577960262243855898227622594030128979876857557007141262827042161165213390451930894116015853642967024278841129355474059922152047461034849879354331609281034002864263056221088486265142069260535053869576797508753708032711473344371766616746099774663758335297884109594760615121547693882119909527694773757308569248745127298252576766336922029955596848192542091581625093473415691329387257889113647301272765441861611672550832155189341020145637013004344070739040872941725570287622370540587689395845720955991256666935011750792571744266202562254075041089142826545082553359306702446775048642007481075457287715719250936506877467032820398131168832276837016462868259813971164872116418125939608354166972977147801788123474152253205744603423796261915959055545037545655399638240758772298657136128165839790900800035892770488170118717296100804336804766093317136275780361743473369951410061312, - -8854646727651796178162536295939193987134350732317210087565933035361565320505607520895547268874339136311065742305084583363686407909124749476072875430450160648873786043550961697916454071467553314215615233500223198464167740399123272240217673773825676221638650127691063953819635276654112269933668394930143815811465673024855214041206238739937098893167501999481929845140761814444796448955896504580738407049533947728779074942035558119814280469232660720708733839940742401855292910466205209316638034408738576929193193392606934551120327086139759338082036550061865542777594304587143684127875035285786637654690970394320729799943926841918599725429090362696533066162343563598551968748137162532229054877921256185151495421396389152005612747280950881358253867137995491760779392986068018803475664521864233288636916807333411985126270313114700104086270031974602414015512329595871760660234773311337871368381972237478426549132010856791537168729338691672821833036533249743623416453004040915414419801138399073630125539436200698854834789944230983626253022388330982040430116766392544465229268294967076110854714240535522154956958282165857038020917947605425066569135494289741268176377639096297840109409465510442149090379050032617022695460416706436461139145585046102762435369434060286939859438262132044449324007768075722110648296902637914817352910960964125917891353016325972263360549747145851559478941571417176912742424830747737740406264073058142237788469263097662464835132170654575629806532679652912803512011002208985838708184560195715400769450723961008185384983201040816461637965108755352328038130314511814196099558095243265388548565984662285031893106612679704006362310474854746088687107909174819636564666044556291109585650891763506125322441561268602248135485955212868598607872324449484238684540118259095529944726850010815265870558009944091558295183380931290879942422569309038309837893358912104803567204344753462355587021437178338537925840733842411112344755733086485280272603724589063288761920641731846674864620823932959743708155121755053516422358962011410194824013236192792129069771838142336196363745688611902988436351375349870368674283735691363718627428202768593712807744156979373010835788866926569259335160803727678806623887823259779457857795187977252758353177714431196136002571790663157566533664952391147241404981998202665839061524890361004677499899306649715470163286360014953154569248627548977183972056575044434454982067920437619655592623319738873727740952364996820738131724031899792718299268511096534017114359778492121186890368722531041226171933756741355093281645973968240584214390180046953509661349140426847526208546273069561510894485133239532583884990287354503606977493465178927830826036340035528315749495973275827053141498914023699789418947377138269246281362396736732139289726377854312344780611090375933761284020432338213184242877770715673007857888291509896817328059312336512183651727965686468548277945737150120041262389391104392129142188503910465016333804770977289078485598311984750918314138935772478937882880425663274574569174193856091168700674761943016641660410513600722148315781334165622485703789425508151570108284667712119220559548776067307613441922710222864154738021262150507248830563683102428439439100592203225544061559314405952812657549726350505630865827661633309785327145634166398525826886355924647592271845214255927801375512180921677081129487269185422538873963544878770210050116259765955091379356463395645370379072718207990949035628908247420109314002941602803186066384619140312907945115604504931222816629488518533653901675988883226245408779845195817012931211765767722495127602671462553204475147967161428850089884264719051285909559541825730695843589306673169897444381895453589468527769337602958937726304537165003723711635976666153312953525163566090030774832476674442510966129680735012202793750479953089420566837997292835546598975426595240272870887468525529696853629954323376128112614687842988622872588629124158711523359729124064253264418318543858350951256923782265591406981308099140688216467693268541178959618031617464489749705835151921484297361439061705043926455686705665875049738448255302840524055723499696842077234330658845185071678570394663614317011176739848513670021237881451216248208800996811984253942022453438618274355183045949465632300159880139754916576435969950766645217898150632020717434797524155227319138662662910680116292707892270314436062443041741641546011454391880670626022879791327417184925597170250156268003207465651917009838122214813027184172440507247252021574529807671156746093615259926940405477355484348591226337659499589052248040084363804672, - -9791545908453782573308267725408654041607587162071504117463884404264923301227230891956271046766551316122542325993532315330070892198576094220627269533043467555262198561938081657851703384347527484452479223530397307189145424568983060789002970400766048546696397809718396848169532600027053467654268912286345186851566234165729939601102979467968635086457822454744599369683974036370200304659121510154569900013316253642061705685874470685749498302844015770791583319507314165997025104936100915246985048298954511605625512627961165132688297687722322873098079615891408512940123281252075748189532281711682621847616355981671050447909539322502588867722186907611263517781957593860080170287433403265634056495675489274672811637491877550806666546488671898675558664154663381317009282133465165414157155761413416489868997113693156499501481521926834794495105312791586996848525231962143725413358520410021296733756325669384697645486126900206885421216948025628840876834255689277571986093959278806458887934179767915400857768300282897430239140671352748598552130091234608499580871075876730226484816113522726614415504878524805203269264732707001844897983133439215717398356152130009715591075501789196014675848527035290024340150950926857260837493735707105371819493013891310672615381552560927857891846089908224371460226246411759776920369556183121753268074583686880693955815051643978522793410942411843814754882358128700492010590703179806042252195001784258112668322627870458894319707682673380080132336305430951220950286187282063372440233477598425306839458371397602700741691774095649140302625644252297990490863877470985839191983400914514570354029177005338002021180028017772552061630997257583427690730954396532790823041304010969032976727405932369700542416294116837854719787181993477875240436990180208295740707119063209165181239750558896978068972670891424594618805435347891035136183495450551568989607117483747032851644411633453558650126839360498930760816619520871903264612735323924028819335927614115324502469634094959741764150473154227149735677022703098754812880717159792666915886186110745842331589411741834071826396467133356896962885102284854305079856186074269036929097058514336013411661362284157204504365826660562372733858446391401246428785545250010184082760984041389604283042480908495039144596409598012156646153454430786660301947970601009159108515877325682269647656458853541721706092987599296104841699639994164390651705493592875591078610437604600032454632744377712695019487651306881813071852072879729471292085166103006740966704548072583221972305679070296158320006830655223704605293330420161311267930794596645871396677267256803703546580820360791112605967313158840550858520734675119388547304624476024189645145353326640874826783525990655085850267772012648271161333794560613511942863165139236346442851647067498718964684487541260357538609867049622933037667695820685895431541411783231607226047304978650305887813637131512876460196279745104243622183686313514756445208106057736712111489011261065065706358375870323374472551460880521738030624641333310251016521988649750313655229562938579794905102681938405487222335776982012983612278207864876050867798695287625599893014991373921768189950580661805440686036920932643147963810364218113332829012174842320715305434241685509132258580329012645339841157533423978071362687082133522883448408671452484457001858425819477779008240765220699355219389600484088817136651366598335989435260804532771903035875660371981743715067094913079230112809415863885252546772802391798443115770044662279888085075742443101419152822000868355433128365435221382583792592632607735264729433210263019066749468632999897742498739231659425855148591429667337712896733456302591280581766099651201516642662264066312254878021866671015317010743773168728563911893940214563340944031525211370305194995106961656965149618410684649790261601256165554186615101022066338022554398967743294371785212844307361921997367452658061670894665420049322579151835180912109581024328705357894814249380783690716504798814700401317418309556232519116123396354162424161290254328758207191291497332737611073497995519905823527259990640921406181774728864994692348609719172946828269363229834215148827419969446425294766552854598858220045164984759375750915321395484299831861705850696851728477714682000083877229331573280690732759726517498515824402051178449234121885804808547270415323470512920334317860170018057826962381792027359336597424669740199147368932653461694471325099119660223165336435227800107372082408050615952103910091354730677092872193536858276542770198931430005871909994679217770824679946367008768, - -10181891670176181276141767454323786588742380092859163088011236988038478255224073264195239125156163078587713400659004550864660045274778353368684103068057520525002684156722400265254618909992122601829458509910544873298420675120146222638266222294403373308232592729549222711176322276108140155726829280608688217104592315836752365677842069875601756312173289018993077871761735081243589750162777921686696708865159480100961960368252843435184528020499736672537357827347948946209335644653142667455651579942678971848916459658424211770808786960939333286503250604737062222896883060489231277231225298640447533327587850738281422251831346177165173175626588770715045607803118638610499094077244688528867678035558167782747603587287564909587917051874425955123459964670483889397942856819766290752987676417600910947362049629130175942728553908061270481472453443603281001808907694832212456480782319487223081935984079968143452239841409309968816253231697537113965243548833704834466816704847161709834789251389834643853135790107202464315967675740524555659350694164999490820686626846725542227434944862751920777049493375578954739936564697242185089898773067673925440058994701942312634890995049034587585833597791897517572417988189693185339699570483245834237144030910227739418030217187060003203718694585151154184518419900538348565672193998307572780372262335442381712256591021509296737715882368315254766885969625482580648676822691171599925697597965204164237411446732552687731364034972160359699196417487216817282489633429675765109647893250635375344508575367790202240466856048143761877017026823462139410471630872281951001811784667016897054313199399809684999313920605599278840850157270903256749560237677836457952782836668298669465646629556756264474618975231140633678204312412275976987596339554865831267467148007801754965812968712458250217081427958507637719868867098841331357096103610291549794809785271372300566792088208121464807131633865897810594293412607934719097941890680819553534571906139538665654115788514680678219452898642289236623691910065732214234223635075651855723683238415269825756417371611383618646129808502625522551472430006665571349388679029189483468977424868434585662067658035366032852475422303211002283168260199605407876768521776809877981699473585848676690900508704879998651092484258068434039960439425627826060230517449640694138986549816951240728400972905934007503715643404551192147228625104559855760595209679548382680116750914465432881910818046009499444236855009841464292800389333582678938764908781185617662701939861082339129279761966342992601915237908224974220602377754455634470130223658325857897841489311080120688204535064171804130358100108682505856115303353294647100856532565722650731797484884039119370926032287530644094548248968706269809401514345104290417600634200377241435280812735490083241701779198905332532881288466296280934037590882074807383814275972894746325294675166615233152955346786349604612044113337521069511623433977213807323857778378060860819730948557976730238286059197378749821011500497577143727127128486433919733883408538575273430292866092281223811582270498124871159012678686577022153695406647928168793701857274385924144248701694006434645275768392538413873649820321116263190977191483697919372535450902287509475394954961262078649820488817421817206969107619130915846556677039330727387828661071333275967184739510972924643245589026210149586536617464133552050286829412728851082048754638892885130393329412631532230858448747354354386745853796389616091490404606137712086774437856567783074357686321512416235211386619394018024306101213865981305564168821482123640796258569708683460896669321346939974954512678857767146859013592504470677362870343918192555915564691121986379957262225223305434571744515346816551216113175308874115285230533956584447323663140580895801026960662527139705379501005695831811093608333324168991552958869051011509087826708930442346909351157028674236202058735056356799954726021092410254035986272596324507138461072026160228708780841390430813520335043068371394877007193976040024762048044841950654466984659280146143833864608476296409466367453782870376052664838561290409290083532635376507740730569513869493560191807666205974311287004485258028025298536972333780940937674858698615469377219809933992689670717920458552222138375201762682940218833019816958653047584777977588548803057562654768927266423548607499908823792345535445294889194042319278275925687331534090394692714267169462199755243551941295484394997211158558063118655900071824694345957463421108653417202388329170490732583251599222326467493888, - -9948229841849819921629154267535364019557120090992286292132680253060165880599628690215552702226436125984567607837470747699939389051064322357302546291918854862989061846925742764920042566496938365862875186198624288024935894109900872867194836874557603792946168839039758062495964276458683784847987709460940578051532062465414437673453547264984306835966815354398281176378415033213766241731801270623124421938645112043779484859254967446811641607861133243909125505276260855422757733933367314055414167149462498521191225388732883611421665771762139491764347144145227033060028975644419638058798767794743824147770996429746135902826680623514296457783240718193491852795424657320835025130277180409909129967975984488313152031505843926565637208089805027784675909247106835064001930086887888923996179035302148434834084442454562098684651080076353804347221238185045688523263417188348724772547722821655326266708953890199279412871121629235922400127271051661036861568569536377947664262193937600486198396100182510037041614798424805858418677437694552778022889095716351612001222266690418586592641944319634449276293369378727995427338603828162783580459691406505892332192645229961200242036088714719045162310734024782953236420738977842471214875347155211769035800335801241512826161309028321251311562976974592014407673664214489620288667719605954824034558935868037833973536584141343029677221254646622589873053851402201816143533215555461945107856427309096507148923696917502392938740999763010674451966177426120065540822767239144566837233564354867267027819839115427818899658263429518071415707577537736289409936275374554375114709671550855277869891981473855092320125742892804780868989554919721940387120638161091843881346746147374598016560313536273745936127498508261562985130946160812371848384348913358635692960055930307062356984376650921306656920874822806122057631591833484664574084174860161812711043531994753211254721958969357479616996339122171155256911852470625766616431303270118914300522317989731575678706135455144398777477967654284915826569603113140761968729817429354679067340846104967834437105916624351018629167520020779190354567545027643492088994419692905647437029094741919069108218558576076233593292507222293146127390549853366029446359072398418977286883726907284892808899042704647825491040467807590215184113954846800967230993754546464315331477795632725119817261165775224808656500251809074973145932993228468034979685152722607208422366160184126857635450766098468719948720608063558932013896284323954858482773396054822757402704991189428865310438080837599932573412684209791271948308957662872064383623458629154026904218110844208869158410332916311093792684575132832108891316289203256005920226229308698541190375889356458693800938821326585028475610203774907135491356059705526742354773719113422901125332392516709830029242045638724247521997762025443529202066732147972691611326302178892326134861578722418039013316058473582850404791457162914133127873597034063341485309906976289428712369362649451072864060218342883611048896810691788587217885408673153200384244436570335632455705195341914763588638171238036486574875779501779416838396524646714012495300101293494990446987361563374834361235129799325195097724265087147190834538294668630967611722663862680906418176614006413119034375220695112590819595797629027166809616441643726852751010112163292415437203652619945380194011701169444476801201151172137634970113120126161492513787880830265226360253124841624751135072270352122448831100116068855824406361950415942992896093906596359325958455492975370719113536360043879423797603629888250386637517029753211322278305060450925045214954713089616576055486225749635320217738505028619984504504859204936790468453651051774001640563738992557545072341120491622606788046821691213718720834710990156805700412617153079858275833382551778004328242835630396478702060026310273174968672541207256009711787490585048733863608766914023812982966940577386985010137454206932421336791451524606667508705101362082356694752762457780534001843317076212877797435211450697395993378031426765069326824989296005784693922517454069681927194486599738215533629251436023890260089009093896181521657546134578640009450917112033904025595251352207811544188933939497532431363744124883200755712861389554927895197156718650830696709204323991240934012052364542220121145901523636296452398081016933365014202780781134485670270893354500509770622990073474091071480722959308704648136679887827373266153483863169085812838886567013404081501507527152656377966190700452434005601398535749632, - -9124785440701256420997698060900805653272636799229320949241212982363696603682608767404570987466897282249005495690463164731271991958648081544928582677371083974491481428883034443067293576479090217801941364658952616581751347171804830550991786104066056467988178745771131631059111827166324290606185007242101052002178579761747589767330042330978343250681144270376243780707826388735547736852440000936075648100409674621017936922383871168311798148345359891395562193821252808310439265298794507740553624365935743126716385594182292475718154523094935306425790459661229393763437013712148592050102157070303545566973681785894630278720751576589302864054259840874805292028111994471297035310626009317147174753023136441820247762306969816953625277194804595751752539696139254090302264223214158425804218306550864352167454578542249300430765825941864249213610866994682673603354994658431512165875970084278800777026102157571806701078632248506019184486865131098806239698215708620476559814536377614667185492591565944075264292536464082659458623904472104203787858705521314892792104479835275849107241175357310795312401195262869726809644102006193731433490943460159302292534514536379875219657032891481473709162306261865711750547188220301862322884670735381787402733867177062501624322776033360189601949911888043674638344570470902899374657713369844968184918713808909570506007802436989441372763084286156711968650613622969115882774617827081007458214257996056431742582063706566883948411200335554386031253920788708957212257071280129406355879473837068181583185090735131019238074251266696253367485793130351210214239172472713180475998690140173839902575352692893858702247335779498265386111702425911970584047235787440575615490052598523377409887696255710383563055018740130303813181986386121854380345131622772000483319642039795388642191202057111552993095650329872657973131902938166546661251049825803278174994148016090610725781690567041557605932095547616235298037955439278960538777348930638989581184873827160898720693964036447926277153449407580786858818159471978088417784763721238613151628886793003073929867734651062767053781063029663569603053656216826527373174215530513678924769111420245474432518483252201483980380082232369179452455104333239687333090146296765570038173363795985128687617111296374583856442939428273086679850195750786313063042206031656877144362068175126967769728868168140366327326282543209974865940411064427212791469317270731785623719658257798718073973604696394680523423541329174884499884741861223664393613597817354382169538538750842724074736066080936782101035750703269009407013995599098298535457922175612299658666415643516390179333184351028345069172668105066847057109616326894815488647325833860549589910444187139001803422020242787680487581646049619719504069603386308952745979204622642363995057236822320595038475169222621146221810842924064173619513930570183772127636365382755046908056426215064023476475122431152341337605332967274955424404186192397370655792814120604072538177221113304274047813198945228361367037166523188213550267847244789325086521744871620855118417154146941651694901385913595660699848112316315793168185225941442808007849225341075043860664942631354118432514280253074097567028569925867498398166605549094181354763055828526033965394488866352985147541342123845551573683179744949114395419180679382208249096432735936831029864962900931891369156331559256277209618939233751192330299283648581037196339634622479286294822765844518360139044895464233860310673670564451395916973844740176410711759090558006266513281085401562902737452541615792269828794514089504832526844628561922076886657974522826495395698011226147809222181037039597859934267985887527009207987676674689436279518376834260183290841738895234443405493016776643722972925729621243217072054185002776107430234074847842028893850167894556480778571536673633179624541346981767279457454257989280426139906706830755465379485933475119790766468427001995269564364590835642278075721531058617218614175263052218317105564696624764977638082927340802961804746003349408764653312715035442922246696113985642960031081182715131294335631895290633421766369609292749125796078414283254692553361571208607511327745676324438050021731773425571497092072943930522804249055712915333511699097915518829057931123666809335439326911622485937913429445221019348337996247839647741022088808270133106108529315211168838513367308911099508253161263832777887736938576495207797760418971507522536879321749024338928063466035524983225243640911580671638234988544, - -7849720988693106376935104791951681884117943753859938338362356419335465998727741129018784887738775430887028495066049778109039918450193984890319037530328372919924412099746853308529917260790601116371443914772030627702557458203321080169653971501996715653836446249468851483600477142692225998706796638735610786876496281340937760195392792052192066721381681145002824258340177491021074207653680256863454622854038644612136512587228458308007395248757516456481555108619143642618982860317028827548903345950556374967226661190915596783074833886003251133384043201052458445603834840057663090948422075216647878308195776842370505164645756409143157550100885450998103219588828902865257793834694167198408934000285210608773609815698004922571699758105763006653321579043338458283697782525198825646042349266379862089500593522797454032950876483296454735812738145435434769296858290904872448581588253107893588445118994371110229894200458791628302893931096021853310812800784853266900250585557785844839564245434904017569037077346557710089139987197580657713036757975410426817661603414310149348544978027408185760048445992419159524931123593194024880227155174964900605170080620783400306017066497322052770746009066454790419655744545726089810254535652473090312095494208143546280828860571861623478459778750111786748153150958542562777786529195093947777700480178168670774393005147169385570998952133029310314995178010119062741670225511349341423838621972231976725093100448873873576816993817490316552299037260425047860193773892431470849975804706150613140103780701438456961470223793741593852040166734650494824467979154707841812722920466942020383773396669381674706263444664065078351558267734614766514519824555519630712139502276205462649636650852185460462301298346577078835990122346027399451777973700513035038627498620481842095638033372723607050442182731138573148630557834754187275267727727913990002962027870590637047421005274605601845218213454183936770250928230648117553455610956141732169070864852332407338479244844559047211698427906208683818454687817042166811413797246073396153632938107716372721943160430509789685791518525621878454470531507393381030152770567685447078565733503129549661902893135675932784328273375083997610649819704309968354706853037925243664344002137637316563714757681458318837289848392975191298172601064503491082512455517696017515499529854501323107847403791604166814808129273983822644180346862442106164498645766794506940978734664147334942810190206523586977234193153057999514528534482338989496339235026066698123642276079864170659754148531548216249569452399701765277433437602713467230840094753671046336316304869865933560392209919615274859036804395358137315183388679146642193848380873208240166652598925569412458443928740991118965683981625354746526723972437341628351539647713114972816588837543913035412638972129628918885890304851891946027955015465446507917115099623477992157429670705618147321816511690397314297942605052581355075274507683743863509036776278971390555383111507793023110456373620833403874537806620900690438151008425184039320156478193776611612242078019115366332866613884188283106746185536301536964870580097931296332400077794005764163049325303499322327582914174441935189814449384750301578221293942396681748026094641853401873446817075960437716740511447470636265838431827270023588616677538778559312047887232372423951874220367319858807701930829130623716841941471699276372924951523161940500096865495483645537974572353713593040773071939796537702640606718776575996782629827598501020141496665396245163013756606191592811791823506874718874179775002717431122008400488517629590878900108952458288305769996667598882262380894716287360283813629254774083174640770064663785459867002225718352229178602369243438595856512946275833301239431573158102634789995961736188392288426960958000064869595818128529998067469671905633627257797986030775299361727778336134300202514248608808481943073377232535801845086000166489391553075426898530726950089103674866038939976439484566472616472702772402951595140617572476526953746062950142241176703289770860911427028288953522128085345550941275872329886905198030659771893888645145768088233472185272705052520659005150053045382540110082857877462266353878211800292276376988975592384623901176746556235988254589890074172430488454606619217512715078462119674610943762800199006394474802183193315245537185840103619152224250166203846657489539119346018027843782994848970020686015514116672795341694791284615271923723482662174720, - -6327188292847776192420412723278165051019304424876774116503230714273593717352991385986935206938125866516677516114233494012348040976700534529863301508333431462312232286418534528038917471138968384091139074725274865845360344309530208411349214808096284701598425697547103297829266062851728763198936442081805225904734885790430482645073388705338672753327353252718074773647248903690100530019271949362746653715066061193389642640525842860614337603479718564965563837625954231478344296980445903672306224049242890084080007449457579674260960337012118934465655988774560762895774942757882613908579798485346877817230120944997228501053421808184003079489962240851832333540730914482836522494292033980812415561584786527342061191365137591499562250352355809631840061242500329477902148671107953945127125208441500711745404214834039808728960809302376984273151688340527528144536647952032483763421362989817966838286493182461197974276820108575191993761305650296091208548995421439822724213343856818594208478355813527854864813964001554028831196917852737739048361959072833654719622853702776904326889758583416979736098228297203233567280651402129500047086122888195974522800341783651409350503060132983481694479752057021058568667847798646221903080562935351345060910938569782777053034417420869076384515446266403859518618116150310121266912283231433519323609085443184984875589329202599182490176712806362278262955684826793601965542040219342385500375308532305960864482225294191222458931381705999017461645463393085127071874678565441652172919598938406739045442599327889113948630733278776756485523431558186542154262717461412022826365092361558702358301251069052578710073088533442820720954703739089477839815837540841919204193137590102507364458694383952512029161968209822565036305248166675837668469059890507070049707190005425555841181899540071529377954618644382834557180845978026079801335522290573408683656186263027713977909565118179214491999679516258916162893668006426673108887329555558125396085247182162464445797151253706747182096759033863465706718574521049754623921502569928442417311493236415828901566201493108681896144701472251779330684665491691544776106468630351612592245994691111577165415714499107393899666903531870001915568156234973202890459548912187566216359868647878193107826585225404012820362807278295681985348332374201677588176755473495371613247557811448863553942262254405407466967024189995070584425293307279535811610113701106402801618654152724982277185191978868891327563696608602034716209101941732408895165598732855812617454960509793953760894949218670951776282821569976677696385267056234910656689545067899936867790492516505105695122392923894520846927799880313585559210865948142800955464939920542996894666812484656384193240531258751009196199942232859342515573155384972385780327656555920106780188593462996475424783088611117723931445089203439987587756557394794236606165008381590706800659513344399795001939246133287424327451504715087765632827123390418496081000872921904427534738300065135867146690048164288190826065687528778265402193505207018241035999124662016542654681779028083880434604141406974780052314700274087301011737229125463987552669999546868917382634757265597032533815368012816039220733644673315323896932373834135505113658204275239734756581374949732735498756206049840392153059324022138709256919025919787707696864916831263648996641863469527484445785613883082724644590764738017342313279136660457398983041018409920297301002441358006600759108994541249969034446642102533325409814108788123401120865768067735995259616449221464490546246105396180935388583992543122765957336345425952353744161105181395027007625213213850416751130909199725172890015330098278237118976050161720908066071411469545733643328466369778141965231725873111657539349588541200672693814646420365453302855139747266495455257245886358700156366318633505666153559262349752916619970621151511204183199802633915522597153120642576888682784617056917045864139336448308686774376264227413135181702979627981346776472501829109688473441667665235597594825650039523881051467793832451781598138675192734493924842623224233702518807823487239339744882378383658265467807259937561159570711734593226016200269815082416730640896627436816717305157325761228877180202293005020133464866395397578670587164575351646064845554028358191683675988918658787937054138369460677339159992891140895772367446249839037086886747876281248930040093294570367854265337282531109667440843785452388352, - -4773498001879790061336779492576148974757100294874651263237572616440440427153014173930801026585863136062448032547464444735827527654048707439168757577256166200189941814622230535380256543528599378856138257239091137621836526557629045330765966559042090727667194574924033258671077520612279303342382134473546851156849464105575755139386445332805796909698016357941110247028513148090710320508618555790955132173625686920055047054666392397725132679448232709204141174214465963651365866078039324175199445776466414122679115516578330377064769077714782667964183655048069061914511820457691676808863216719842567665119110453478050431835650271982840278636716920534745657955812354545733965610349049382962096675983277282422392244604166366707752099335890404583683192519917549492342302469422064163929185977590629632428800696351893338441598081662617311137041400859831734166130607638872348032017616929881129498869245238592819029572708138893474281210494822809113724661568109217204077428741817045654753176646621851045168683788129301883512398327271466390790264065309223580255953941846333686043615947144954534480751002923535239621275778397497200249472542492316476041806111470283532204689229328669072266964874533395942750234733837195751605127092377385732337586304778493880385960851204962244712836294629637803034073513363905972190858559606723529260479299000628897585354896348149848010359469068172877039812948998220133163255928803730944737694284307164296276156205954561975686506234940682794275459177421737724499904631639095303472457434588275787697094835725770065055910816025974235494963238384445177150109027201998574574819824440419507997786847693154298299758995934196718765049150004980192903317271715658714306209697618271653190234663055264632275040834445703203181488540822081994744609112243747870867069016538352523966511210396208795399478018304463184796913163638663894780201487758944165483736029252947122468105011938792437637972938858081267537566591460642137891620676081068375805080753897968725654740539292769158329970647141100035407729345166756435464545712163313045248836181322648658729861655743956575214595133913460018168527450447861305829278474113150103158467180307055102688945587274248452434215354134614157019777048215756678453264444507320834902129614217179224156795791756227226877705765814917912484783170199872666966999394482474875093902185752398703018515696518042374867000447551816459412931144695852895834996252670437689156653552775804145002591864142073599442643779849121349256899123095452290144621028343994014842618139084659491073849251195529578814338522218850590585728001517660101154725455547866271380618514930314979390586442839123300911883230095874738432419887576364636262480561776094627232427071590684596131855096531590368102719861848828452853636256393522415466597101077718441063427865225802236902825865223072783213521540479408625740831335222047187288409749521636646267720290464334202815958445665340313580757368020383751614420715536744166246271898261827207388276683465325541950997368217745852355204061811738436610418879704180539863033882293898247361228897258351832228958205559227523222592204616271828344829951907271075105197717670613271080496725374513707843257684884978640658127110279129758448691908776628796021957035975504097459561234439036305312382616539425490721017463061542775275849011405341510585065573030354128451508708635425896645003765070909437956323091234094234750199014657474899304784008060256559064545485110596510578904837637921424993819404312733257385544600855415850962516670454449798238072139337725017593662795407732128763025967813303033952889302151465549054352159779451127218442347735725268110319559204984657165917428947276480114002924978907537911183409717585845788086282610708430472583684090064647842434162755140881761618593484868706006281580459417631609588847113991561388652957977056569064090601287736478785677849017552647151277487970689928945070751706098952356908102937212144921275903091401031907074572191620640439689858841824169367181460179972573298837397913536209296662399765519130282185790216733487128928651707511023657332525548339567828994688152287074857134115728525676497832952717416715719855625244049082552469328825570390769593278483488954645053266758040105452847251223819773364312127044088231261242305778752028600935312151475135316527762462883478466858855783564888362241938562830538438071154155977073862512054442115383043090431325407136448512, - -3367051855183861002701070389482246545218128475937187543727967833459232312665893094693979984648525368207062692824363563346667581747149429984933621810134010115380070691799425978078772621434705241780324274064801366266775424050428092093957218276577101918436949275154849193921880199773945055827249107069060656243822296954873484283685211398148711250360419242909105219151429855452172168824817995713291658516038573369029033103055121139618192504376566167808231811901708735513641869149756304648867943728174709044965563428078148169824778923423240207879659395385486857029045324629225557632159825945216867780804127697621249883400365366394185823039002006691270266440556824790894027887470563038576177201394037239742322152118244648890977955615065953042057684476167637402314556580720307707126602067015616233657795062625044313974271056329984251278887711490708999085401698467738084406623903340881104249104060154831509070695840916701646129638995316420121120780870778652003471450348125625245628550036200882551730037710658918224810595429445538321580817064684692228074871472641570441201938794816114840876922023318917532718002782273049449478668490813818991996269008048921167828139010439081099520760884875490636231048191367824810337818454662507845695547529443571559425922496961541504004719200777035910812937519174774655938752314901591813393861997158055519445074110818516424135453717711539486374885006550114821698070948534687970711524219665422481893446786878378931142022902238803487941315258206662958352582501384498355062912956302987324010238774682256949456740514560911994906758034428634159205838306902174747256721185311511831351415515054540367815999987385835057321319048977589607727239201605366442104229353867746798417981555525560272972210073969827345937170177085397205163435820475879235859550456375498190475975920429401271986569648946610947358122183774278002721142894148335394676399373030461256205169849270300022241774891310287367932108942459464487064407158189959245593019200498302701925597357912225917988539499070138241097391579178561131266178029241958812501051540821478151311807380294473296555919204152955603147272855044222974178744075102515765178756485205325137010029620290088048017672957591296531273026718841811117290111365787616340845969197106863197133196251288640362820253086539213094691224082597750587588428401289404159585623858481406011054328730169215819459249350301841909843485587222319269376655309496017045338535876994218119136788977712962172209204325446023416765493808727509895301651876536131446655555582358132558328176127783455172206237623760896299063540728122831856297940749062671954690500523847620743700571130938981279794565783763138637412388900706733229408003395804359436925921375312416521755391832588418333800169089876807041958349510104389607712119616571314758198902407987698820772385638291091415452931202386775055355127971273696897755710889316452362589937446488149511587270091639210723177817213999025691146280257258637791687773548455998413683942350134112820121122110135487047972426697723435633602069594960659758208002133947370272920914378492335797300059769913403653486999441251822715088767323322564609012527031442269749194049269354335314057540250869309509623868222834887147971344468373855431531101801356913596406706170596617629756709466096895295286984931035027726623319078155625807926968602123222497809091473434547301654624768491143745790041699341410345856313244272937061231841897917710409245926220186726485404924830351696050135166380163326554839275107758152673873041291237692371882122987766955275118833391166083390772461812359931951048613361460809199903716863538391149174417855526140444932188211152214883354402581862706225119368479337448173835498905764471281845232181996834678902422053467129033213850804481979637836834859597571695100324620663525459406497681823920421641639055446256805661091928587911708103285826992631099518922165923351877812993127103410646547254847284426237131169114609643713618073512514625935189680809924438412531319188401073649786955602367719583753182194685283715915203037265112583911697558241921337036126557554022715435382731152147736559444726890747856708039195307494038004956237963776611760640990537568969302506689677339826937971444633332847874561164803688436993076049718692527627954638536655900890785068208758015558321365971559119071424660221758812979772016061461918191778514064299241286227984384, - -2217887368301055676660413285206398366377374638488984046837730438719630461644525521924084031491275177367988701341261561636891870709157648139640722843308121208451661160227620220751484669422468467613388856667972271652698435388352281101642199714405635476351994310637973231870524045041544431113448260510109034456082184200927110570241886715960696035104410727760783681741668436564394115536505964497673112563108176448607571941374072754918210837777201925031615041479606845504292725374074745864049871957635219012621117021079806968240011152070142453845517916859888698604458390404633687001133053231823862728753780552673367544785356979071979666421263368696858037569163968869674930715163007352033451748034816429750917938292364271060068115822438207696441976269484156292280545596875321227474618992301486049738787075640529815839143556756801179542828413209115678923706584893947735098256098409628574943771386615468583421634486727373100333104025043660040216428665314534068535435644093125633740160984046916474388049285654679947407475015560335020354192472918170146914596522179222320247980663580591983685051552373535037976672948786426955561169172802546443072294380744128621590443911730168628899515612813549137867808835793736499611853698220499918578637744015589784922043858778503243931947429416492302269453055596111852990572167296289651073311291154530228162030473437560061985677777210136563349980061279674646784644363230873882612499102868145632736767165312115396977008446332021175039259148548947974514439413521195936503706559267823488221508548201911501693205640658228132501584354222223764957087109510058918046939964278109506291265814510043689019448081897470855837358441016818596420706311388839250837047261074614083145988720080725859350688268704029809054218491300071252133177719057099881181379083099329992609577454507208102013899898681853878737950188623974455933877069048437910491129561670577961491491170968040382725487219441221376015608197027001976877995358952002737384366322192237794933792685715594525856447086085166852508431023062639117970874017833677956533975804313805639272345141136407405365135058488899914199047146759765687098121740861051726946202111426384924569633818666178684018052185683447856742512135253779049163906486032207662274998816323956266485014469086302153955804980116086573764792209978714026121685580089599565674580794159189127630387304473067740967075193045758631411070207919219466387051406748059820234389490438836305726409068135681392949747983472125196467464308263817895061967649580233457316708182355579834118708085123910589166052163268820823917693007585782009367189441317520660964358708559825978483506444733288071792454460275890238596952512289733619404827694460228050884537977881624708040959950929025563476510758650037474212913291806650411671990740704078348254709730898323107336509972083984065492280692235464862930419739740482954962893961290208520250862421972347718348606254406947549763656539765332092243542322394506917300307458782008658766989280165902564935186793876691667257385407494304009238603737841705221676590399169859048054789920951047200667187118300358649458639843196659360167921582485411165776857864452887880132264007895951492855108495613888817925016426303740632935429337730185856120456322255692547170658438292378785633924579785910627709001598479207313212904355174693525334008344166162753663497445320668248172653338242850345333924967026928653564896627822081760419527827118388821597048438206606178763372296347221333834134191932399364495293268340942351579003322947349825694756230275077444960645838052166901421498225658625451857282774910531609932690425737653684217637939510040217646985501203541560016469523521752524463089495993887107226641701971174140047285630114760812661476772784054745086745348557486501072598880417400110504973497883296954107236453908610632422828689154221760175712151988574192405530758778460853902559570207313989476079209629671391569268697593168850951074547584633468834753517737892516315221757339263127979659360388943976272727479735577105818416316223753790236062216228156038092903744027467559661036226569818574188243916763457022458367787744405739073222564655870212366006519571601506219773078374232932911664768988054156018740468695188689482250087453102980628918408051212454438239797075905966880314920006356472771534891618239825260497188096848997764155146653138944, - -1362591851696453327061782946780205622528853612348574164348118163182606520075900508825794023697167236593644395011726891466480371101113493499049715759435257428524432493151215719643853738814024309691976562749873980269143891240573769758628012211467439252420044755920182449566253550990065197755693491168945551586233133454351790256264461162510199287275507160554091318304013760222902091731437325987207333039506694399594268832108327631326169331275718208608015144006866867679116045370206067515469408107534595978664491324883814803497258821444967508706163923692131435435164851046263815258908076867144369235716509216313219136324967673751009200360103084300358340565027224493531915735440008745894256392303126693993381892166555783008347307152777673786642259792572779076880849515084374232425867410819261311935279330472719147425847046364260269348173839923544713942613256260549245115309703525640027586948760254920808331828503857515920583365568051010468965389293488314102123897143877310261064560986448927686593495028344161397636925622110802050890812118037809588533015222708154449237651881588053679105936758040921982391757107717024552954907942045063683912470416047828484198405109012574054787452516592254310753587052467512323191205436876248150736915087393964321429942144783105823218266879585839258866870713614287818193530132732572949943328759333659139593193641361037300196003366089108567657918835635879176396754224710838694168051127408371227112178049315047142504536243552891344263070103719913539458882340355525450120797459175610595155158193475652717109143098654253032480433149755175701699748229614347792776460763268797452613624444262486743023040205545393739648196626413108152324942368572318419582402989423909742082064683033338227209992734736660988405347070331577071482401165962918655227316117258625255666962365409196957982009151766646472094079445705535638541438293354664698979058674495887109201496185371724016714844276353347894898463326211313695466404099835176571834079934592292094102564949195381216056047867293933938032027729705962917190221256572763277519001697752044907934045366872326739147635179945451353455154621951657824935391573633922313523198580172331590134382537747049413780850937514389293314071016023585131968182416121489303645901796937048312846581711026360967407390063251032760891741636541562014596568984675643743369604052535192447864565852080261417315173824531031757340817604946592637477527108868040337142692919142461246595944394128864235495135094731607335780697757228714658354533052607436738744651524938753335263684274442328206119506787103007553548651309590106114484853440915388587194513369725002768471281395009860163021817986660832489662722696041097245458897799540803421868653185002527747232404409311740890830640356686405352252217368110346807172375196089756748481962283838369024495596862578478873366365420374623410465663129830589740563295517688721648744027536675485803212201365295872579098842793307126444774955722386859417757467390686637297856306711150736033066278053333989556336385619025337977285180702301628947819392207737668493234015081390401055253140070678674281161314962890654881995277683888946076915274001783066675295676405749267772353793038538472075594314124650846822988857437332523098426899237125800550962721586559125619826712760896033178078966357121583932478347940716184953486827563983125464641967525943313800161392480482970705814422394909224010584694366068170799638509277087755114232157621910912518089856251888824556963422751708263931901050436657197725860873938920292156342523380850960300851804672792645250917632148059920454460585414288403246993861405154833556230972297428222487007032009985197004462470276047943915869927099242189716079602457556811596675942365776599023423468619944314101255601816980259138258412227589004349683250355412328424451015199060187193878941895987400387239451708891527017285186455773548385624385042351649535105178625563455914010719567291948465294879922463345355617403135660825303273397975379376849451747457765798989871144635136176209365675859136392389659055856528474558592519085769581265528445107514540989762354962237980835619851168878890786576303480588019507536933488722202389558731304561492317659887916563779643775173882392345787096527068814849097367853110231673325507519272940784802201908300941710666870599057019621676679168, - -779753553757285947020326299572776391706401999113572330409631968582309226355827274315523072313438502167487890224335762025932130551203219293739080804431449180683904952059773882945236948447932542282381939901835295918811094092826792759210771324531718865394933673038186714779201434984353748414321831296512298335492465747845637872819612817407568579740240105274945878084935753444304363652562414024625850444867292488618038801720144401137050676228993517771812108803064799397922827867207603279593475020404513857908875820530972070017840484533609077628708088772806760782729274974229490992393146894449591869100703873627989973104231755007385577302944826101363192296176705597835124166335900596032104859900673459617416140650749786657192535070975463961050557557475621199430476728477172087720542928736087399160712401311782217634524818415481858518592594113371509288631364497783724516751559518150157925339427222542979885802512354645333231695082776835007991205003915243483557419376302936495431919009123248176090474943238864156997813143440021633307582346990914763214254868999294156408751817372620036151484844291420028126641746054633575458362111504950745534068837195336461311923145126604183039811315127256796237253574397240671300828420885096482257864946651080762664220490884482085265079540540378479933064081989437633576095585681544008085698327064671403430157625121608087288828780484699204202330067382932945175949518484387109442857723337128738809913804133146976637736456324513723389854885059298861453080659545468188307483379562514511359194103056139216796869122546387997764043346350964691916071028651651552139519735440283422515447439971343012358763724020851116385627716476070435523658234954737545274591088606237069638426793711171248952489557148098906354591711901271214587867310279892998452693306350471078599123518774359936516874634514644278663140238738458247416528747706633244991375225542545699121393448520658726998491720456330632859067284446019552715479629612238123765020328102848124368876076552728885121396542468879201329312398549340611337249772963860259487498838382645410323153846177895238013090654848628827424875799766368823929212806748850676033583779303378237902064871680689895711660268695866233399659422395104904505357015494203631372980130636125324526047914004400614124872947410622690787200553549754008956872432506936264284875375785889817821918841015992917690285406612205927639788082662657674021351562575760620968913871947915255320008441861730522419624726873727302053844181225801651227658117463990110925151930118642690053399988094799013281433339833531494206583357602458374867838957438129785070473588794469766542523296281208194692185874327514117794910828112244590260332764034326045823640851011929398324126726582549257705885688314608053881542452406164786016837681326337361610135903352642180941662238313751469478234515132119804066362875296584992941792363511973055119537595659652892081305945282057247087982357051056051919286568482212087186699281405665143779273076628891617693046541363158483136947867186156411296980149139367685616865728471069238708389395257670446432355321732259475571644162140989655959354739901087886526598039573777432394573572310687996466185880208944243076328222522296030053395553098902223291492406936549203492598553160786355309150584962191270254350268249761001812605351784453322050459175631183631023873307997755060163302336299702494748167670028913862498668096552854068496424650485016542070844496332064222714801890786664963522044773249696310420213543471749981793488117066316585429877948142879728934523410689145239700053682744997732293435231731258120969836764203725338715486108781822315268061217023191799769419522121566301062935665058728614804457869368931882391498829601143398957670724790458988893368870494685690464726522747207569914386452125946534600063246385932617849077948773429493244852938648140733646974115637044122062414149044307186047166352097786361372937137242645056600691695834640189002583164700266785804173801589075646430203744275905493203775436053710703275354585589774249604760752355025845933551118965189733837020898915627222339108553009101873345102677569069239900782116777975044299852223226231979079289284603031368141956083665521972129705382823036666795004741782975549056896294645837833506176471073383627007899729920, - -415058548364485635094177591758086000168248724990221720726858078348800554422354793650066534590875312484033584382773864356433523605551804359874252677487782232864778905757008751782004750837678408808352461161105613285743092611010851010069217591705893856185051161176591134308525027546129255021053235609677128035667992751692584310463449457974699788071064322229407907184460622374687253309638036725557138080232325178807776191378844608064638776767997655588363598146367307597696908971070716730047426544342234645792253288539464728811443696915770413781959647085517047159434719413498616294990909457825555956152899705607553621320035990739149633007549435334132821817144509142804122049401758978355959035491661367706094804595305432405630144687911514504013133563490722375416242812985705862298399307329371923805611947863387827029212259869075419857550653397703156327898771976723771332762457330758172845847400649028279938688659959591010071374719568591678703853795975849735732569581426896803959472467639379037028821033792013826989319039448166270529592204466975398430373171333014299222110866166250324275869815460365816580827376258240265963976388773834620482800245134767251230831174678956642354698397862924524783553654936127713874923597537495721894635175547765487670427598846402357591689532143110787876749796020174865262109339816695773933872728425904325018529101202212847981049461750139292057719914545640686863645110202451292597085212955500222085335999826468682814961087250322965976583854867283181955322543284772342003902887637753088814079964587200325901913750932969159201394113138670629764978999860794507685198411437183030861439750591342763277448319567707772528027277357693427340461480114919789982845724708740349567966514296210409308209687022250843398936160704715540770194629573965597183579922390139397778603156368368599865448316434399815032067361377001816414579401308726180233078762384145047055396099428944820858817072952830771036751148462216865500490843878558764904897878661008004292557397828584800935282330485529553379691140283790752831709693592959545014630567247913573687523096992047445281243357097623622071911501147257794977645751283889133764418608063012854403599152877267449510963104516600741204146876666295740078965324561714577620500387987030745532364126037802246981073197361509667828407416225217966056722688329928134523938180201810402375426630171464332585406307848650913023461627218889428951800873995660928302925479593690471866669152560091471094402209100393362578809469296930079110220960682142075053950455954824959808985901801168628103240944621724066246995827520525885130677308270633207154906138264593043526205590132454344615436244982736959547447779232515358805763150928680197510027031486772040144881304799106648854391736312904336782391086865835457884584967557167674089820474083707810008077281727298931346279713602146505274595600690349037074985053123719631583622450945811558341162571109187619578813104725736048992249579939053644825647558427174187920541238288915354070975766374681818292656111389172739682782154657142777133625680624646503209078633003908560706845571649216192425575988826541429713934440041395247153855017238051889620953799849929069854067916389548108589188162830117482177031655154268822398403366594542351494340554999745784911153156365704710951730282888534513224838899404397040335398085862953722734354073235211369528891154127196482591469045777806469473406382502196984478605402691453101840260004093680809640028755223726200156581903353475311746938417657648040964566859057645501767243597210289271289453159968236683695266110276710971846166440483402874535075328984970813697541682827565292771083199621343129039214212383028924971367542602151113588843256225082859994162973967889135130432388950708847030379424479908861615035056276091982926641818418690786400178968089870966903820887466009351666737888829848324531668942273896276810837267202128466145441295302851906709486048069720684098277703561962446239490952950667471668885694073040641449599443622084213393800860777030170716887369149899158679922071761495647084777538175478810943080823408187798212517361022731236296035420325361550093771396368424674740268629215824195120169403669707068320732287400283551513461310623554059932125761260942785816819646741872640, - -205201610392418566785716219759990771843601785297696542245683625454866488132147770964121544876550600608215805039145291565109195310771953928263156306859453534249643815792582647043046142952898613992818307865411989058921469152959916342684731076573608827898859981157682981034864197856671378288862734255268748352729786702863971653447946194580133631194205760507394176499637651523375503498367436713980811598226252033059748432138223226150743151716454433153102082714940804630927452514251348307907986446408491652017281605545347653156557440835704701337376143872017111353957013747354895785148889280596784507544117988827473512239944071343365162580589690650472941863150854206899322578667758944173813800026826960457664604899461127877612427049935473340344558667475868916473278842507793543058114033925280307389798575146504559461752940833516961447949174030475530811072590179980002061216880409909045632065707590139102078908185649745773146631845943050335496533764432219086709018387581194193707730863138244352122485196868745249306537838216899085535573199187745799711506318516191940395824426203795442977242215574564637127681307404847605907304861611985597850038310565083030450214733424077174732439241935751580002469520071401535759261850855086846163345373872536328302074787928284088377832926487530801210186591366041071461809027840354865211478983471037429669303005536976985915471133101934563540007596675707750214289771714010294112161075571976692011671591033229183779315722470652971980708517711473621886008556356381028808422351299943363599382159087358915271315865188761422624442707687095590592635611411366604327025278298404032960159061753260148862369494252573259843971474512455319923547682950814382950046728379679204262500327545844177320840729500089529524641011357181696027243366167606131411019642999609345358695738964419480115559217034113653260184660133292961204855770346214023730975562145932812903357715956070740028054264056184573500545259375729206148859774339155505794379643194713237590450386287351935465150875303856453581174730449260309448731310659694826033852827369174156576460364558809996830757094832426768033336791165967260346888820583043958614581147278382475037182472193778932842036006803435430617164807256465938686346179928021846589678323264220159180881185104566293020502241735566676671986702202350625365128067481104526311416445026244252946250613345761568844529780632195332646731891121330148864883511108278350046668358874322046064189438840733862479921742019783810793543585773578591168456496512370292289882927049925597868747034063302569586861503542010468241522307559666853186916375695744176545672302971979644919365193021830390154725861300069243447335724094202020292152144878061789325461516301498564414223311912868223096316867652661426754097428281652949885159683222529364326477837306264734817702491814095407510411522889776410248068675991581633789591664282778009573097661945665066608939482599099463162206817635980809586345208247545908360406787764348506577590540136196218302685922532424021908800209053872318014898503152756931472207553384807137466906256269096441822356939237302242946270966815981220952364039903403930223265748521708528532181853389647685635980956811626284569349248346862768128482025189203245353000106277844375335045495331282664990815757604472285895293172249665624116603403772784838326637586057273405332461196284281888002554712895162769449335536759757979930140015354596766452630162804098332606903822016063968419499782170770524134511466496347131095364299483638484149153372999327402885172671113205881744337822912251360502773055926726065725612588210352363741852294367887396914200910693505545404457527851300940033052886389796529547414684679288337045104941238151336386193239964073462767666731308189203385684445054263213569178306747935059362949021204477464717000536342818985793867009576712811242250832619523836343546503076661000049375693661796504954203885094298549588422650584144436745826260246034751423492024908260198015045711853775851529338412051789137465255412270320380592220211800992186872071565300033029687173053326899967741483937610041195552489001095489364343395638217001299717691104123626648008955066084296909835148829862343702567565669064360217269864307122367063130112, - -94078650427622879039696592816387031520579795122007613106711761154146718350988191337059081223605728563588850881992451958286512334908853382674509619670997147938701395196667195880879242723328141101125408327823191920061131886740549981207824373722842642889179030424603127959273081174556809834206842946655809216083488891329081452529859236105195930568367563361170457471139086462356320636365192514883667811750252729647941317530769558943334710820689054187763700241910173532725778603122091399084338437172466428458416256724595308220073656865906988299008683108942652957757540104549682010545892954120303367812811941989834189984968680563543684924444723380003269489451507053605570426495701066276343274348911840397947485739238845652843327340391801817879658667573183279542088840941751448350651422305365992556192845351456869250977908960532204186508708824805750380170285679837096073211074999233649974302122700427361403421868594897057478620347404037707181486291620016472628991215725051320760182820796481159485610105521340633282578398419563214447883863355519036106296599773096628489537830500109482957533782806035391814967894696988986905229369542595789413604625557920237109284454977347977928359623093047071949499382256741675866088865138084809062970847483482056373986029745251616960030552011325344984006553536190656582330480310757722224241926756991047936106921985763983524805368643594469736944983442854892539605508114290584191813950946004194412253768611862408724606388211224483845499839845802132392730182073795885510149708778934221931346052170830179894986264210629840600414023050342446577766261658803878076961385437290716762811613635544676996515054637299550336123724201017274216070040844155391005070202902376674124127333213876875520375506216355755619404280386303519317561567113315070806739905451000212318391643970552276428721930837628192101628865098072740884384641454237361233628415621983234081048028901525427212466986570906161477380515856337525413235339550053115525516397164955592968165727479087030119892701452862944131645745936742407282180404463172237029791307815030400793772608665451169383429882449368645260575930233064863237309549728596806841990400192983405657935774018402588941792836001103511127456637101877175313608216229653105066720257766984359349308198669858115829437359332821943213380305898255904085124732419055903744406554340131546140875847973762895094702019283554247459572208948347001899989005037732751313396647698295749424883796635781635203964939648645290237038800381674731920522722964250072071022777190118967021340990869046876022342550917842284384259053402744131675295663466965116931894778770634143428166373199423395935577444059468086159516932280034747433526871636650923473208337180973215709424580695219998882681162236144754768791813618553323585167045602520764862389836239985200263184802745796139817517475462563008632606253785774783301467033404482997345322097399357064334387065655870596932989770092753471944528181500767263381623029380215114874521961280252266798480691287418163587927694918729304859215493216255344576262226021808278298713141986119320389378514426192722622194232781315757666377538443231803014767782962085032054431367178388348454059289407729990227404377108628182875596251493925638494746911353943699368121291007321084309821526010476200161021477519541520471663205524625749348013548001572007670242715955250342566970794338234944132274401239245208901623523842997821399159528378439681334398672818970513448422366536735869785228949071661169453018609740930679524866796429518957660221476189716059698712788363165812567242641838435367065959251559962351548551130633575645845919354385359462949999387604975845211368912662450357796148051002483466704672239919213502751572164561433851414813814309046435272418135636234696727637796547703140673876649145427264414549269525234979116412798139274531554695895670464056507859919215976576395760437118924387955651274370165632448669578754165333977374402187556064176284811254758598926361344007156506659813623292217164779821671443370408598096785638264317761753944281063999972647249522385803099320781183510581583589719920352009568357244544616543559173530703051747586368998352653509434905396026346662933353725952, - -39931558058877085965006919377652572816495707463136350864639836496927208154312122895085578604010894079866858622293616818230165315927687604784290621344229677629126670611470708173054429361830985060985150488182361177499349500496723203499665023169903536606730676928197640855638794582252389877036261352089526421690712011287312674331956108365533264668126570516864404815957254426025409673558854811394672862517001540786114004542070549988339085599450449232217047928404442422696789883017374793802105430118162847789813115338227773350044198438588395846495086722079871973926403101713376642958731707082168733536157708428372801777418611256618701929453032217295091531998395613164878031564247584634371824341378661210861778504259596323150333242530635098108440148460067155772010575770888298324973805977976795746761797064516937638572944373583730241208094489194305884199751903268690261682233857697173221594929286980726357890257463235550835913861347811619903929942794622477629669756159181931637632572433014894061193588023998103515928681221946993426779565937565556600348687758089603146350139130276291597915875154362737335326881050321405203867783989903515825352883657801803504460226521699591335814323726709880891432934429697223830418430333521367448304228801637324262798328463290688262106869887670665941071259702554614231191379506631614059026658631574670451742198168753379551146393463086147490724825728904899736325106431003892947635912045699113651956162265485066135553024051582374568147753760551346306860039262269102985392912975906574349540667018110328628231312044290029215561552302080059870754242309887154008446723252001995733337251893209876443911196480042568871912104091780299778340139633795921146302778244616292428804984030183601659070577790403960203860337887187861811991893414453693273164990470245170758084824924333411117118220006197949071575563046409034338461641781521531390147498325061529127645758956378315177218329673412662954150768602866780825936985813056569025834878941803934402198742084483561531579201581167646826838810344646348688540979369676481280212674568443182068995123187799231436027763215369649253948547066274869159757403873459043517500743350996503637745606429154023647104358072997234130638347968101602778953887546531624938800464239322062992781658818005719714066792528407684734030485864734823478463045833430508886831815838527159879313949451008886521703041271568200524142311196542770250909181994880831450566006367672790978464790325541063877368076569935413403651682771442242761555460903467011273541203796152118699860179092398822856255891930348375622076967033806077180270942876452887047036639113128781193559615180767868854083497859784786560036667633687862617457165073625363526024878663290775363112931414747675314472212901453300167522452470617501835704416077151437429647804825708675108794319811870347857780790868940816756904414108408351699935247375714427179460948938284632414146473392803218481733628707125848110668676860987016176937072226721795375609006810219909481531398289173333338194808448010026480481577253089744975993117930014929158847389114280711561444865657592763792736799148228238654023378587628778660914094259731094933188438429825105876918109528363161911411642318908740567856121787357288068353968346686942420418943059648915481807453137942455919926332014976741714073020391172345637010090561607236111952903504035020502321769793280188933010408733670989146112982754145209427654828776172730090908647531818908751313284222549990942761113560679028490464108811460716136204348951263025255333721114670007689935418582679341511388752044784240451363729034729459998542641936292217040995878450661319280867374029220345406207248782050252635378405456411346855651259117073558878193268819662996647417747091526504419951555818692881231897984954772728265274910842253104869258706888857838429575900236369385725052344752367727108421838704132077921790005084611627978481690932824761933796848501088232383109660063723343815384919693230249045770041183215911002927300471920043866389085140088883949682143333958472995139949330094067975166270887363287523377200538391383096726078647272000053085916522696704054687470000485468970433513328214016, - -15663311507908346205769801405097572956256881002514956258887579237458150631045320605922624205574428377077156361473071242633152064399148953539669213410253154990877141262355413373267133860715073306786427284465393402851949652752400236565105485776495442690783971450367008058869689782564906296071498172180819376960896963076103976965543513840653367357801411952694390353624570546596014477138259999727910050208336293353550421720404101476284868623854439521223748729858957003213555842834920991567851701585718803364106972894913194944122531468167728497747918855267492077201070886629359922535524569714305490337532783133590693992146013095879968753974733395910949800253449469113441364195234012165851405732376510711706266530981004755901201145951731248852498658576724663947115273519113535831294171669216593138625031107310797819243934400005037876491542815370631317477485400017764014027921104527625660508012482920431066204117610970957926413960173574408429274671056454705008190878123375612668885225774806400509308847054349688219818789216142762088191519823952328149455292466462988890472881205165990730454511737918791852838869792916392409808860154924082265742291186111498889362593774111530081367585459379556012184540687191236051824193667019719013618958463620753826679692172536551366650337787159648077789846224023583352068159624048668116846728970080008470406722679761948890796916138050632537413747567124949691328127832171492216996035051343451307862952300813245984244037814025989422138187159307055275055476976568045356214126067405723559216784829196472745577687468254913258021127893677437376116588590907419607623129640436064920677191649506613885320910677475877468545037825009726929986527954737815810497076800805706293245621327329337090730246683410512276838360493794980122019341358575265033335101525089785734290317991331789150133735219841690747551580646288795879262833478988998433370031098932816892586284875731584509381512696115364544823985166319303502828703345281283686145155464040652500331887947266598768263461904691282203561140377537349940833905968325938676390029752322288572223587557653349444507569889160635980639084083749265945230070837640620654029709242803283328470407649210065874984728667137251991497736772962285042541500830894748149781873691613272598556009119767849127746539811645403453267440327309184389213471760604186426444871128035128303883065775215206783277468580596945815439939480407162155254778521595708738055556052348545737098673889576312144481588180262894861533501116183901286153338603500827089979169367137737333935151978808227933488821101408447116461316127026747163442998796155228066380637415614467645028977765034354972179220711959783185905220828656499800936246927121084958842718829107604783630183690213726741258799396313257838632217724014235511480967543901137770202055077393305369996015673190439412724013639828816173629989153335135882941803797308966485356148260335631257080440502836921324926035980846765097647585819371632256345563381540948696169263704112956661195727650409076558290300976891349269668005770172850556034780123060249801932157204097357822944564476893632811677884602909081996026539222038072674687350013618820636413584561618599920446933390782036845181174702652296371572112655497111753263949238382178261495000946167985562305448366607312918365775104690411550888469007695134970583723021911999070094374010799119964423173569390445291200759598873268482158434268380508908954058926482358575740165031083972268062214047603369085252070221709308904200079228827598512678118376938542082940518964788238139098609969993575075156919164757218951264204422060155486306230590480967026373512137519680217673987612676031324900907516506612982846312779167481070788512220211762457556688758592616701737204487873290746515576185419779257034655317524416366052471680152754460317853678789097040620853674114357706040736224650586025067606065670267761324596812786960415063892176007795183861769762553805671467849525792342143100513334169460350685020372951921253603547399675934268321401843359333849428597816904934011483146366955265641143517609495579353860296814641692330664370374007057787614620731559070662656, - -5667157951526794534839677472253814136838944114584048658774056724551181816072771240665809650605292300079277143472796212780350429913450801521551111222327056676508260860544284660968105865450186937810218448207221508189579454252626705958594497880000329099448206025562977734827755782841752245724840957313084006439042293974400781699599048012888341403766306622827822032786377911848402112561795698132239064474206040078721902341726321459736248511049794005858715627857710009274832019993752513710012376253126554671450783885612013527791688752846801342191900719855520409420993823669315090767968075040982265130087617549924645969119426760900493461239950856653004539784252484588564211618047325164012504477948112312834683384877548820064988530694690474109473347757888644780636958376395809065111099799383129881440149696824685792930823712452647755162262316025311188806397194158142285802499355870537072710123259958757661734001656559630231980628945234933809633496955287372617162564537510236241100164286709522899400933684053250625225671476199294452193770860864233690511779751926539159883490234582160373131083369583727215493166505206561653501775160558979092617398338283585723683740478653925620319141428066566106468562391652146851885059502477450373079452669548002217957268229638972412701281549464820296699886903607925738047813397676164406251287771522169680903090541835637158798315889755701186811252738085845535077044276637253144280083966889264440888086815665122720344535051210507803255632780212257739198228100098362429690891226214862396298998917957668172423945627642694425640964606084572136871453949794176674217483037583000147331435924813707293447626802961437916953819487024244437397873871758946330757540279106776911305659202164699055099565837636847267991482220067172730026650026892721943458184678779514712615820669993084924651934143788800949280191118479769678087699242931384125930932336655493493875482627532960612007500372941355698134958153109876735206566005601960193480113487727359322891844115698971420908166076706746218617871475996802147609481212533818847157486928628397154099891838046166048868927004767623699849683180115882810470620032367229759642483895670088586177182090234170887831457545182010440915682231675855448430179030507966297117527869796579996807982225867514512493100209057180551500680478650873348986572330368003372208519358402531649205104296942144430889070187462702461317768976963633772774876449449984338820431557249727780842137053005248111802259689538332910488922915064316743983805550214398017040548737464043249743509910922669192549835871923590273641671767971537403706581045668777843385058466435131715703265929599200936217750314861367661644161736018837385007079569504566745488625437166719615422041325031838223938785349241470989154589472888171907685704613877666049099314519751353639866529522207222418224205650536802728178372316686591475023201099028407158314805565122632232169669443754478844044935252498179440758475655445098085463840755983961538126696013148501095084637572855826937372543388539930121208854953851982168036627231465023903443375836191282772670848871307245370055792973563166737855079750095987069936085591314980457402569331272340569381756063372255001867018978257057741326418215602637697308228992595424957354379125493089542625925570092343395431864993539800701138072508350328529971269312700612425353736043074972225133196790652514734489914635087382949290051833071897159136726976791107087648548462986644818445947482042138832606060311220754087050510478682407959137460739180421968638113199016598021029777067339764404439115596261175686392827945135932695580552245803275552125788663816424900375310398836943455662282992490293032754998740120670698883711545795918397928963129850566394457013823873246553750794631466045607755950965659334577497370621039811121243258176565219503059031068261982139048295046959691850843608780043468520143592979700165334762888189314797778939123478711777298228390559619275221612059503003663272673949183721770516793036588014531144930372310547328346748929401681687669783482777593455179986859504881633695430594452922627202316500992, - -1887429282837392616215846097387077147296864400482521620574466071959115742208502798515779822813341573495552437201164991190701430409538567385674450316652145807738623171129688415505052374351339039184357803200135781563459085007962435899872785120215864415768711599720582825851305318846475623435119262496902302441202900767853654612194607089858347578994983242812077985960111577124002613576402467009572288657157420319662081530391387349570592696002415144399633503987717340220824350567288981825606434163051765272667681882330553330452633955688619665971575380978185968781143326527331477077230081170576538821093634744418497139683800943780021438779598714935291280084405684923313467029367508187335197682130070576316109741133710947362563010279323839574411319024014093977007392013155555579522578833273417559677417684321668644766593544225070849614518326402279145893960754027881826331194560212559441011028209787981409611817177615176631703077754506516426879599186805795770420194024128354234724085656570508422827622147148900875594533344760330510790470902670022899523437634237874179653294374973404845986626468220665213288023484318614588553798635166467443678450949357312217432694604031577963225956955474942139625569051832596008943941948412195627638881890898715941750762371327840373727390222842636466211038352679589721882054151835235907345780066693874106871340039971352771725084698813404127425493473182518519427494627105919005396957403482896129610110565028977278956829607967442598043782888432483635295692741733751317983786355686913806587722155478308077709862796908665039308319476739037974020121860126828253073765665549250956701376373053002474509447512412206184257975577963337806543094721027412756310506677716367817863385466139730042797998711328045893886398625570297480010266719874944565501297117768369250391132662536509808510494662966882491656979268108517472190208459359306774855985404408534591079206186809043681371829600140439203387574580526099616656461730735586062543779139315838466668311797957529134179862337640581358405681851467079017239103465857366602376788972087112058796486532416778992670379023537108996609402443963856383330774433465757427468612691836270121755595597618705839670487522816257268246136783590578826598862373665698818341748973401598134901881762071955431593433962452086536196935005104861291913566141120507930521599738099483362657487956988788225613444308591659575820421018941307770796585148644102101716515484232297653843430920213711607196419880976976431355070047826632395908749996234946919471950629258016558062092847063496687129039316156637898183918402439953181944458878649201546023408555691638444721837819276696909209454528942812566164763228430106092130732685347767416843439595704316469376694948415969655011696551166354494397832964590919396941662896356425682617495359984173670228782230102970624471943061392787654349147852391642645300176890165638684019625512189353694923151637845763205926307823414817443833478748140156662139465113209172927502704733512701314744745585614430543527154955125314953938024311580663401783592002418742318658501179781890633604794085322499505950636918965732732682344606630773055549599172641432693806653394695887635412583946731364780294516028830888493050388405570106223495303138858017341883969960719083582535064882022783962667179283908696244315074795339833690990575455496769233856684904651585714726022062366407136050649513069318169629394096479433334465652951598735411221399828941606171008235137812557255758066168532131207077940229853311616512243011777802551338238541934965214597168820674279331676799318467857026654198397029448706840744248759364204729645037062748395000505753612694743738786535074422152463779149819305094345630858531363038092112402630555222426101720283832421018520547991770576039299951372719644538824355575341069894801357694127778210092851931149400018803027658786564066266536926330314879920335648693606839259891302324948674009369870718727144423503463044884004409269771373965398314267309010760972682990322175283125717846733800604300842938427540451357054479722644068168615407386624, - -577345702813335543895115087576186662278635954277963135678639767225551634466441209230121690649857851441431299391863433261871403846968152853280190682747752440798198281858743955067190807216711252482560971662248142704495418003332248515405786945151882384230814717212949180062034948831427887760338807421148134178112891222931907643047458519599564560939605440832300822950380496965985642276663025605947266919745524133953624576930921168894818835744646237116088223135576297206163229342871700329641575149904265602830241899168430980494345499407700462670708650773712747068173950173213176125194393525018596722014527781199303673343203070214148078670069242605139159396316838898173004003822678314400158972269510887887215530014198159805528512663056392562134214944083302119462514694333083203364695532436576528645747814545661521408951965325136213680182810928949926741536136201579033777905651216118854930472418705394838505884938016330231899123754245212312522850936116452749723605369364956762816979451372812746697559906634604888782660501482830599842325689211385555725239357560855919545402073255836798834405965684298003502489851092043324330518318051924950918568256118824966177677766543191400182616514647722776912951609107798217681050464509566425924539939836043936398451972756316397483065339837783289729825741767345910318658069474724477253813400532194163033995717231244233648663110928005638015991958911831780343197510831298356764927165746829433694354032595226566090241675346914131346349592336143190280094186772071716038698883212600377360494175875542892376290273498227242713532792270827724368288200966732354162329981697041648863172152594537785834232495264437669847540335926843427397575251089996346149620341897104556551273949113830022509347025106303174355122563776585104111792043130926079339857731510304622396714516972282754446871978066736682788436706468324387225885170008120592693253340500340516833929621977222497007512562962416071886638283682322978164509883997585217514019921350613122175673913096654092881182011034486154187106502473763565437757504894109773566124115627484757546955861680417347383168031886495530246074347898579318578009090741599238902352819123199746731829888945052351902533152108592995931757013535119227087367816917661498092460142956447193152020606801367502065504524371940429722802928840141901978975767752035226906343191180267969727966970750366909746823753822195153490098992048640825950295925958879593897194135459334740334109270512702107669181190990631086031804052188433529965025169073971445659305873082940191519431623813771258141539247113335785760096702051502200238172071114925208301118893713475710053498580277365198836949273163428029332269800579042325393067518325759751786342091498386936730585234215810313445058439152959978317724032020155913367966305999650930246275737640022237964938781416046499049388455645515561477672375411921137787600488254671995151884908759274490644900730987437943627334227525706738804657126682715713364839216540292745626835861210246074949157675190671844598862461783367785494869230309052443943520348039984182158324636036715202566100756085259263635049045954096381497996055656866113013986932279359611975915897708480792439013764779814449112669349050660772807463114269246355130934958620697378848141145652884806700389352162058069386816328472293489356044355142636598276133413083359784445762506938593800042193903047170510117460806881287508277558346986394305797618684489812047471181422940487317800840070047738388716444085217435193018479201947756441710879168330334446512280668176404522179981834480799084913459233058409848570929855642049394890344037687300793685866567355763425658223486373658218345364788197375695976635448138369798986693013608640828272868344755390624639452934288425557765684942518487104641854695026676450381166397854487489051896307934110641298358302631198729205108516373784626422854584541633038459048744284549615974763184886180460876610516790985057672697372621065182458294433918051621588957669410780525401289325245571827414963342486366974709274092100890132480, - -161812398273486619978634615957897083140896539102036840041623852230719557662378948999529755342199838354872463409177984521552217530597540783273626376273641119594429071496449649522523443247339104522925610100912596509883805828674499783729149227302726201275407889887149703707875921062042976391390497936760180299458917134117172700400282934790348160857593238513959668578826007090677005113512001915080529361382027102360928636750390925603375386635656139200172263727717983269605964145868532119121250295048333435642018148630163820838912479497806253649664575449425407310729302172441641070665630033698254731001324916148408369981136994401854677531783715633493084066917433933492376777870589763211347180686422993094948633401276090016867848200378623976662273905835403294516108639097388708096448709216039184200238887453509229495784491093620006985581512631441298686068172621644036907209945086346452883056617058758090653569064658070010548436930295061107452721756058200725661458102614701458804024907955957045316719327477027194837526495824017802588163344217925707225429919942266366461252006684930652039827661489647789841410463512820930180105167626855672642923968252481602769785494186467602985094446233043421706005078926715209858689597853634900615395206311009884776511501066637980815535835574320594569147916227605246446784587726512655516126136554586056596213156518770742608165476429589987693284295726564486532790782499921207813301653777093516626626843051158407003479324199213077891836746190503849584126745257358826679716734138599235784069512089445827010855074369010404998568646093144653652361892375378621589444963312904259861057634029303395269308981798620651858867402118694702878308743414914509023575887822199345583513267011499620982609919459930819090927875157313715018989334155188106818994377992027649930260893386650475858266767586471535718219526671792884299360353147851900669368474332827489389349987012678296823713724434912207633637277202046688668333986038790335518043101210860575832645668897548219043104511979411580726931623428957033040158381962880426738641048454746432760788818704123820262122810909241495346585394227371798038555499639933350226047965764451168375975657230955894609135381191959402126524366338758121432879948257559117379775594526929443075761062440921818206847520004607830424333111071783226356826517938727717780197222489426579317819541654545944144730687515238593608201865999171702868300848714735558770235253144626351191938509339699589809161349166625721958460987522755118061026259271925580503661921069533444306028603820948994072587505731822006011733445757136559554826124395992796867958161344161542238735076119981821171267293271983936678055665215394579359051304857866006074069855417392493213939708973138337473805701864499218710800415276414981863405609236511390775410720940253076919242340657121925674283568204786958267399024491683179928501890886879094349391491550738667991778898066286507819805920193784751630991236692807096590816550074877613452515362585187935681700559320201443424512526199737877474693865498974620606281649909261635127015788216922522505157091556518427444482569356980200899420263468325574793067476339617364114792225537417837001473202988452622081020628442876376635085708615055759909996039526115089308549883073805667833595481444033373628733960435709581121249341511927976351505081757042594835998229409483701587596437489479678229611319826867714226339213750753235697755855030974679052029300474247305494057296762302970803733627801804353777183969992790050726888492515307489931417258487348542759952333082279286666405996964553788677300284227571066922093631999471570142212028320378765855066716132447422551179604275514809076026603027187403101865273939489582787123329931945756559077200604898927312126274953038416999489869289873173148048908033100183596430086747705581043254071161735074527573086431291335308082679946162426731245397952512563908933866055919555406441684645055267434177888657983915229117759528169314417340537742286036329363507653166449188405248, - -41442675702159650375529138739373556674862593824965387341988802167257616436138045111275940673762741431028626838031688843744259072364620944995248329369332860472373442085137169617116171942870069720374602940894705752452911331957911668888776798460166667349678991911861727660165106568514961468409311594010791643802520379333285116772961261371369607266166586068461577124261060158148003289252452402670421943188269907688243301137855036766589410793242414282650881740826056165909772470737600450197142365215788777950353902954823731014946995939040249769183537078124679255287390462885394732068942680236729074300832836792463420099205821631627361515374809095448452924017920827875473983032380620859038115678324582640422214953794663308456072341710677417146885518355563056796696317375804398302648564296377394300221940508238436718741036623302308612368268523411725775138508115396612124876602433658677313477668865703924501164870679852916063887333130557152940606845608185937223707071819328473983439892141153943644563857539925538010948266457652469905198731259325530013392872160018473752117948912623763485373216511552241163114708673981381520463126074372709816412112976626583780220640518245856400485716645227271215721692385497649465083388628678670155748164628290051640962221358889891148983466977907599287223639873919505808649283794223895839053713706124618787806591420243097893708500109633854273086355380480086849879153277471958498875501315816487163154400117377166480675855931712355377869423651658930389238611589411677540477089300247253719061675061414512071292603282253207801059514744237121055825371002176597154423458231453499079388599618145421350807749232072942464836542132122563348581778130078581342000159487224615026560303799995524344102328949046111110683971729800476998061165151909103360486260464035999725169062487281897205674859720418505286763868118360933348745959366302464710702609616960045705408498642255536488945411354996207655974571610074475071082850110007138151503504694926671116129986418756447410067233710543347987292625269379298617738898014633845505618466700053772164150225207465248994264214949969468358943705642507086488379082464327114484059923758073518262396974416061957651390192415039738824294958681635974493400639944859538512756704820195450543664654379081838823871730633044225638677330853618508392594589151723863404174631141165055392656777141830501335027362058554730206662938118415926900445386314053029579196676116980016006106219246491938347816425698324426212628497605550843402444803828246892068286871288571580851613004375409570993874510010803722772841216968683025790729108244164698381482085109251778619224949441217158167730336277065182760497989296286968173455161438500801693746056740517201854616384335017265918989303576123235091945477655640870168790953792319758857582033700118665149438701936616274343844932728546270386311505990454034130521765288911122529206603030071093740065244357948499914013859616108207050537611109098656862776337991576843052618685821355348695691136378400725667386327295473591723701598151468314122790736109625780937898702634756640166297397343706534173789416983414637913982124325781097070280437258304777810796337838596808991621462999753686014888583729188767178127172766175716009093214516975496580680037320016551960099459569028327510483501446691446722253738507496078112323105986371152427246370556960470283171759437419985747871178588123497561184813826022560340320523895826971379571896329479565763807590267865447747556571380364254899351911420832331581040909652540612839827446817105276803218110270030443259840398148893883120949727925443583765862538969216595742596756491407324002712398702431156395041835153498664105936827350965457441024751771438699497901829451087778125515655841947402199518328334276935661977998774542554526910065812080506927636317917530429876597574472815972805093988787430821492952010783369153065554568931642276025525966114000163897843487592360657834253373169271138606883796225675376033082541867008, - -9671024690038399902238288854451873339461301334177846043235028037800406619552760059007743857851115305143938629249751541489796134620299039663633853161208855574526688932906630914538359991967286108889730066124056504516043862650082774010754875413613196179320072415580696616825221938080074553107595017741025945750344549950078958574939794696087901656744596969242634833451080760894610967942240958595758095576540536912805618369410447105444718174130541553661919428066511264036178870274688965860548991942789301769791278036194441840089696258447714035539073472775431570510713915357099104759304068773956922129805269782258336139536143260017106066318045709966532742641674011140506674305205438181889475565667792014930799322974214076855860087738665071180082899653942199342668918620757370188570147003738066557121942426196247665169817836202778936399751988081772376001161519298620360623621670478874567718074276624324322314406892748097081856653780109009489753454794152543685982771260686062359811200474292047543412447069195334670871427317067844444048290925913030184900986094045085090923703587041579317724142908223984344130527272264753970126703107439054288586779483996289068000302387274009754311338786796612607345678591394920665220097524281504840651718372376984260719038445736143418096205125043899003793155299486973642987031820752003438879969119126506731518573298268960607180427082255889454703298488302515541535073373818635586333849324666324234888320052555737182536398138349583982236998378482815391339791085221127272048359562258329521812693021616377452983018682499775064209093378372033905616980296405859340272228232920576420911986336458518105906312281988382890815172680331182392131856483481824685318132809651165818606877810822334187624533999547389661147622101960650401127152265928969076349231954372556558552230749921631365210945478313588764913285593070603431695527109024204548320801092147584273460250689045203701879313573769687552196279016162291355154384181910872971077681743531201561637341257333893706815147723235113777840436416491792461717560482947912867340084369955915061467196569115025277736560880240745704823984451702741998009727463424075300641527581137465427086625339145677340155113958658038173843064099672306126942907150960424608178917212165642043172535724364819696806354092476288180330955211144264960456719337812189973704781492241213090798271114503670468581012823526410859596603494819140548758905916663376947489433228358594008800723296362233139947223431199480391252975902213303817849470691106544688764651523383986187576385369829618410278002333334944729416816650220199430908386596941163348915234760487167619769266444893383615163421616317441033479692105857990725338700295614856696761761636779014028100480934851288365423078276062200973150290452307033886294706768062701243260328862457312207895107326541414540381069605841475022754229623405249688260094905243565038521961913846806049003813510008305847827223346913104788441665394216308205298831147751586284817546646664678311171414447721951275139667939400055171798661622653870738639202573101181517125871683108451323565796889169483778565366491214951393864939139881510507554178090281424108416032872942952744489133437539270041847755667455851851046001926516763541368645592611972632440184969510988596064793608173055683949680851876173723067481101827178737776443124503312615163411809046178495186071690400044671952944262129937911552696715132974337350240297390104391548644430553855503495939761797786373898309991194110397209598760993444755868004840278842469664112677549330287974997243070039493064710104015508254160652365019852537015903541392532673883328938520592172303752855808123380522484179066837356404943973602149964926800244313610644287949494496835382144925418710699885245832050067048193190124248645372844908585584937006477791182733723344106510301921301585675083156060937726205367839723774013075933580258745677121364058186986251544462645896142447558774304876852674560, - -2049597456776447242891454301992622192411639663028151000982706465343247058155722795747489864455497107689766476937148486324289542556249896681299332185914755904222700453638972877178070650936992529365800100626283848110575141145035062537506545808412491214671756904102632687324464720685706080997631301925662884523388452965094082455888670967356618510850342777679955977666776262665916596151365796120069926184648072517440353599318206734187077619634202863635093854033877498008424060986267939779448980035220460374901675640694741607505491603423717288582750975229255352556152372524160389622223330884500414728900470200361219834525254439765448895000472807051659963184745596573420271561875121777068439867002783596549175075836591171186721673663910854228036708254010346152153409788547629760567349058038530797848360991581306347274545493766264815778388991436436611111375144040486657014487270297231593938199773037542342453036608580293856765763661911947407139481675696760816712706917291075760503497174615559090557641592308193149032106464829596743565235457353787343219061436479264175829642256827325472802782148312802048334575884294009717111742731490096328842308551815458598066525820298878524035242660510798956294174230044671682174347594758716951648315842109510533838214416470429174295017852004988618367414696529026490541880565063499728626022837942320104253491177129384655901358906156104509659338050979801427186322287713927273337974073252277566888889432977115098753324517403902185931780875545661281695879059192768805138326383159732888474518723484021845040990017553933811820374796726507753269675670792542477534561696192557688315100868959013738381347499969461646265303359409996015322450290430745842540399420700787265965746221822352159276523501184386647434114062498085031404045821849139873171189210645033428494007501852858477362681965778083330093321617058902229704175852785553176136248094787702698665271749246615479183864811419119549846763487639876136608492934928710999777306000434029736797768139367370672764291341917255882699722353340046260280112790386522634727975046129108726743270127804742309760706228378484762709286235639151327432174404523835232804935880447420658064755066547542544022184109852642762670233305297515643963324883853656597960884949734276537278405045499231630551809512084666034959406507606211626192770632194142926749455431421278441051368968177847482642496972654239161108786445416750499611275700839785397308268364285377955300191986858139093992819545077935136571293787870579030072093334777994239278015354055629114896878873155860249238215220039473228326231096060550044861740768347752770984887271437743189183066535833802074542895600277271788758398092281325758903627796268183211986300373913370632693798397195568298009511589700134765493247790037724816513148591031268036859106827596709027572298157302692715298390248587105026192537482292821223940621633208442463946180371958759093782259068905059659731729800646841233524239709083749655715228176114021380720595243664896011447647907541457706572469790676489473308924648072881856546802677587417579632329256306378835631132548399221598081862627320798357541249665391321727288262489271293899701434587016639426818711128485425069790642883968970236010135869920926177660078675771879461512072796845525099132425299136385837900515728655508031996619883368420328702737091830057490701852701060660000262627043198806336172504157616129180647223219294327455474647683116224796008746039319170526389403354492920906530868786995598285869338012973849025479437440035514272476329217019007780246675692360604224410239333443496021489460048834421120313195818874050015400305924180480221530507718082689994263977943536315364964671897962022651085075557470246091287468261933297845314481819773702371190447230202853517307355357408349416525168570818303261076813942599067112103251493675270788923865609986809680249119380698887913434073992078058928330646031034484214726656, - -393043866086444301922552342869681366783102316673848085607590640824302558919286777574347815682082019195760388040952938558495918779628668497507945245633479271747028351854530393404615631471261879095337759494325234017676802051787337160988583413180663993533934074906879336989495654473572959162424939187532290733527380073173835561472755864632509428772992867941735878811920727097834469408269573724473228359542804740612022834645502718280931416237335515444816753585988275497849177717948793772552885074972366522977147660852857486645959305879497487110923845586927368047847728291229836525010562632676376840931147100747724297804965596262283718112911460275414583640603021401474376427367479110660742376653842830286812387953695441658131369236163676983458540232997090909437678828527994498444451682995792264000255664011629354334640565018032082817416550247024534362540714969665311478992275054542954075910846105337214909155736407480801744903124074497305938326834748207076888383245840483576651444762755073577932999752633246304856975649282861342079140067360533633303650965840050911089507896617898663586623186329213290158062271515800646373771744608757650153197243653032463442986142307886752607107338090659974367230766820778423119957032776053025965564981250799647327027759008805563302287781940378356678722825779737974265531285085736817076864691899520923485162320858135712528698869889357518634778778248130500507542281122104883025117502246848655635196352884902522536944239307006392061590317611312681908892437765770506962423880265271085402886889415191746896678188081358384531839692347636402330871074957453012621408460647965361709935624706745055757823809892303923056186881311953499425042602622815906557134123021872415393738771803355687502910365873902456737917259155404856792779020268707242776480266691738833456564864713051450800748970046864263889510332790938325075576659300321878720639098912560718960770108404227428117671164657713811437267180537139614564111273814761654072210408196343110473223129058539591033843279976936371351205192899353081253723321312535263549973581304211591382069129442213173120636018610438939159648841494962203983506774416090315548620627939517567377395924446678180813637378667881239908926148588878614962314250046480161576070211643572956604072800138186869566736943487562471974897591208654369427329220177520821774697130335567734701329036117538168261139007604715383646947999943528320087577658803952602515299662328924236646082435012767507976355454280293488178965458003240643030658577142728068250736018618336651607667280191603431044668222206369584243906007797853891478771967910059894574162037972115717858216092308022183558783839575284073361968334504745740094201720626383589667409516245064945475644795868936060838272096368579714394677608834892704705531043787613706666723574590964546943057615524746124904485647416359829588730427952890210622552047621464823234487866673778837138422828435948609423176719867362474998320212167675374581788050629320735757816011358419075787880768288373805744459079844713691058517023334876890761061634596563477255655662709738070696307834386927974654232760322384672406134652157815721027111468186433942248610607839217646704467561740421891405544091146774151186889890343966430038862295803507514144922328484596507937826458738620730321838128178402254721316971689002561012150925478840448572679292152064109151497630306435617207811744039808298754405294274182308959299593191897142963440202121088575390087989516259489635979236285069326359978249643269156703226916005291660149237847455899462692088845078425905118736583734465117735412368702580216380645538559361329694915454076972581157661773807561535399523715583219804586975223712325312297621919460507506555617332031953776823218093375130304494998986151780796667884707552938733049892515108281686077237296696862202371757830853520733247205791064634258264466943875025027483033403392, - -67916666077775703956615934969143744367657384530413981478169573846540377784700448233789788325992323213672829222670216662668546923703962387581958450356335523296362350779890474082020826833310597122251385376568328660214239335416822514842058770955941862091005930686323082074225612005476429755258665759525351681696483572718040805923198599470734763911014413035002401648087065277246821423856488668825660664544257216586230587235621322112985361583359006194713365961931052822620217333087050259068659630157303512298649648906515170276575238169062084596053350039553934923066457426003843750926115782601993228427648998332641114026855961371953377099833705119665069001151404331410447613703477884786693035305094173175959448895830258272179326794828256045658281518381279761652757237935552421480615903689251166642686777456840583199663577250522137326806781075176061257587887037750988266686836818147919116164869812625479576465266507450663527859166895123030817856555910234328911743999969704528854950889309470285479703685587165164226399333285199145788522494650731062846874833510303443879504756840811052318813283085076103807454370014514274277422026952542206856241159170739587020749845644118932060176641138892734429623060043538755134195179893719078312430550585805178549627302434334172165640461354209080555939533216434345387409190816723445188908935196619937094420725280834313436731798907462950308765805537584294300251021147460307627230528243472672835469056022151248209745346110925651005719997187512473961530504840346826415928066906558684271969957239474665320959519639471900175889720906641726016356586590629318953321372994191769409233565524218435200233219881473467320903135723787178550935500498615300186571740037515315206487588113594113564902946414326075529313997534501409127842053390564351564806023470756221284713629068861660257747730836142617273572151195515928263822308324891774327523839838865579265436267606109526549641133991324801335840439245964020180768959541438678479243611112085760142378107588312128418678225078961715764532624030360605997912960080176423517103225857818392067700432665080959347961195580989515085106434934416876809313867644529268955585324020568349753868454390024820483149499422944750872424137630946669746707071484443321368946878770886994381843277667505959505874480553147663345936661235040072940349084007387033533095151597113231506384535241553107639003362079454228897972901259218038970066381117760968163020262399192068427356000821292080428083115337862553015066752369997469777360103571748325251203348864030334846592439937848039407063729059041563547836743912477997808828609687043052845084297789662840993101275051162797901170344017674231917450285368668424220450992370293950633226981310738784045672899637205377462326976163838535781976107724829530626617365201362664164316176992965761404992279443550279716952444816914704709407847820728791723387615086833041424892682489881710323052709494726888522345086713674502445334878741084741803540664460419058508800429941973439611741677044671649952723812318124827214912552023500879763626305230718748205588095237549929729856926407751969653923364686841336446832628121046079950492054525598048015644080290775583891165072130440830911708224584389761493606160113891289813444309881313431254813391522974481387584830615240141460596885344825854896655928349541121524515861922037288446129795859494691454285025364227203024923890777333976105807486909294685545199895102409325591731310076159090974655391745983336244693017939118469430325987570578494660948175853731624374210195081949426505018004949736322588900477461326223404213840939268822426098790804348084929312493494334356383091358162346617607233088953409348797075810309557914819595243431164600752589448570335816848389363994925446443058646206893963381694434502013776809588855195102531901255866046801585147248737504160313671110854958907392, - -10524211474906449772752785955687129766528981164954204517780772649389760559860988572727146504531354542591995773239937126743036634123343682836323065067427537832655377436753738566885389268838943733381455022079285900112944458266116838534511487154569909548379149436654510922914690840424113840151512413001832508405473476068769887649027818320888943558162230839750037993796892455208037108435553076284670853872199169665524590671290998241882982101311673669432983254746946007337003507764681944632378269042408593504997537883927694193958881798395397618912858183347519437956018216197914490448092628861340470953933787305065155556869083016405431914328206478618090227025049092402967112377589993923217172147521142626877188303784265469923921819257278228522035538250505946344243400647568636890965722764415562818636771248625528022974271052632589986858460039537081968976587699005781609367932224913099103260215782395351263971599399032873116171521665009617900901972182026631128061366277510309085600723344523579215319041413000052553123591330722121107528412198307101998952734824505929918358667862851231595379250678999266830759694768832720804861067248311192223963318245651226942013358200570975981048954235806278972544279956637277860586689283925710438262378893829444200863793957690652335802119405485379368450395519785821417643787090834016389464747030670624442718863746052599548368699275619377890132082388801656673363113229346691022148050305535230602312025639168810705566596997278464552713665772890705662379832104007788785919362216514482048744017501407667087148068442930868427347119623487114274937350818261706644368674723781478076122218606705826859940818880555511246131738062516886062664044205523263444241880578080999812782308434325893956386691282585011485034576653249376420391423528258264633991833091625710815395902962161080337717115894300280169845616167012260060070880030208082203975025097686465780881638787004645377566621705456837937565899242739960353092395716809679892728341697047462796603321197006855007161302338810251824764894630318508012371085134311909739440555397334940220951356445143087848719386644479376295737202330483646927582284175688973907250211053834025795760698506572055767562039683336826434211166656864251395229117703147127497148642697019638379262443819347393430737904255867130498780726523536893172827167164089139460227518359776504468177100270753420093697448725667374475101495046573911743508428295319130643967446298375360712670213017149693222498653989436124709940216704678586831412788081349002781881394236530017013613663606919569990143711571171317481997350653225445662752047158305549874130919308939864018801104619116823309802617318222974290831795795313364897888396352974896693761155822421619234403390622526206304775252240913752520852591401787153429661871013422077463396648837945733630401130624840791252271506212404387018355241717304186397831765355778832537071722519415197666479284230950410356791297290449715940658822096480330410970003592884081743581289988766986626171027586926401479875263933212471372912904082944000744864081466547653549286975663161762704608895194822731483731343669851264113550841880221548481462721533003271586382683088540836029457587248598497920855552871630139220381394837182971422237879005237394104150968911043209944134359588168833219787805180440929113690147693501593576653339450673313826684590411293484136657415183885329347050329191444408430077538017847184813203678570899408330032595179343652692906281200511908441432748158074194008644755545025282409089988772443150812895511254935359832701553013133878266286924054551316146248997528224767019001187594890057678881377930938125887228604157339742672644250008535146553408142760237163807852795118659471441224670908147773098933067935668328285804220704700670746089783254656650055233397237280933092063034553892496998400, - -1454299965848792885191206607524010473440896573080528714674890135017615840674291283454437143439963247561149586308211038914301352475982696778697317560746581068179776846411224307370110211808540772845667774700082214951682923332650169589246013439270709266715315399201038893169023668937158761427896796856057505853425400902212551139958223416350513648378715040584999512701066675665773730813091982116209278220840086325487542661040594069153058763373484937604494572038754664572780148901301274193743689188984804692025319957313562851391511798988993783942394601820824496800121632058045424393191776898346973132022880238915309275139986803309130773075846543469155521850655676234236492231728030495581546945557532211412557861993750488142822478049567781082362335780691032625747216900090838603997299530858147105124740608491468155025287992363774546428090803674443423688942141839179454823341853979209221623954220222017174957012428896806309890821372781225812957962358394095670850384513248030124533992553842555756330861880910223085711915358721955035138768577025129093997081992253211646574725523599757224684514719390020172198768653967532769582135241838485111570162744680657321195485859501423933463166479720450560015200204796661623954511273422697594108772021620200676476663247539768305236180408584009479759671660973247806341335875543226342220285662764186826226137661404517890944472419280676849970720540493415080195958766872956442474533141680276655216248827725869667000870242448519466069648606649735281745258478620263014120389812955078911499282047533764809012404092563485217555436215758870621912022176284086638816251081427447335513455235160158662809589337160221286963840833936051019295731708410441991205574097556131439366302454503769252043404170454802494605206609090725885105432642813155001701818556387775924523545061148081885155496307277103252213187500981185817858651641288331718593292640757920940468983387077954098374347787917757541920325689354853197369987438742630046242453094637524547019137502908307385416084930449581311199739521598570895651333542166396315331038156120972731390753383234110940588221112173665061853884374749793291244019000053966430647764019688693420550714341992996036209601352041686182059258493028039573990588270051124151121670161412355682939262647618212087873768981744141757973868407469334564693882717511379249458351413147062769307280328144015124462227456470447821883174341589889695347801375236949147934831463813074138656512857327878658444878010383820233149585730098235615821160265067287396936055041548027515975347964602401491797638979179228602651196933923395593508237542776284542880398056410660332067187286734157342707514811137523512516949293501233614327004337836389479328185930052399729958496256465753688689933203074680657986798885653947498631614435244273367359119361569418080334625144991085437035981483887379212516628405372779536575142058507688481290405975803721528960880500899148186535452836080842185840595645004366442178592879470582221035754701199489851607302576575764107229613691838038705562311324098311505724786008054544969149521758615113191769783660869136439258562087630831667663045782876083348735215827922093145292365054777307355649297316058757052257136410379360917129028527041220355047672421390697125607300553730564923255113170110380082517991434554324780258718941415478584640715941534160182307175346485887886192799809088378448357692456168784991406508795460760259619512021677731315438733162673189099938088359990094147842275069330966928732770894398965792672146763764914381323775221584900982284186966912396945851806519029767473781204843241168799257286511393335000492598920914812709826336878044629122614324686441793356806525293829692104605636453856704819258556865387608140635453204849693361680834414892804552421116337344391577891504128, - -178035626115691907730260689915567119533874588831828995048615451570287145475980212580335069004063265855878760617356201729456692614812330646776076945419354409200899699772352197824036609444434796737967155341066090388268465018713881584244250623496957183170795089861084280548416494625084634213582394227911340799449389999067412472923933821054837153552270053706148470800399360864863819859038248984067591026466729309181340409613229016010772911236164282656792827136743185755742967914658355484272005601205746784223021454152558496582737828875704081896953610014239857391940053683206761491074536295193677153567246405782797603833785289154917397618416278730049058868276673048422558691993963703965692438228472142704875936061813718397769375649906167945860595013138921730574795439371831865939978768348012197435706729640447821065527161522438593581846688321509518698165556745403325466589756684057237310589596749729677981111959196690444471826231650241431600411331026342057012512648105198069638352360983722153524816273253231735984948928808066653077587014760260179203480818846250631195658094047657760798073868203945398477540238731291939172374118087143926471100958302297483790673845633890026214317278332570151017919388051418462961623971892032652417960431679952078278230590164750550839333820834586555883662801433677949033268622104603035892538852124782575685090027927500342092943697921658304751287363944929116550384771814636847258195194637484517192189294839937652492114189067396680324306977424373636498904502111468089899555802814951638975656387578670857459169813096411216283493161622866809742189526477030688794614696433914256621394988501801865781804174243105676316000427317808442612219517500433035217796501565070572199839308070585506308730516356245914897869054696137044002154942856701057338071788079784952455996063438582534418371660279070550121425334545030407042196114722799325304044070402020942040467263858568338901473408701220801962417997850695680544693004441241280887685729173794334905317092922072305466850295654428963469517126285799296565902691424807214221700206869444783256043069342126148205334232189914885022049478449402319254779466198440243909204965076949558074936378603081784574033036071517105109867233647533269645578920192534235629630839262792853770198109747763585648265012802478642083553073109065384512580507234999166428024725059944351376544463781786369542792662850801852865406818560717360138049062392917070528294860391682681889538345345578341945651356177042549229967745861849747630203105520963839409331794002410168468480169525961584467641455175657600720411952658242371301888310076793181526026879270751283565116413644914629170730532155008544458029159067939839402799802591647242833333330269540068728182069672686667020277940184207672989319082546635510995956300757266760275820704950754889735840482562234525105781441844923215562315227997575243770784174874910756258616898125384191111965656146872753278665011624736507376942512629811253093977924279505538605125270853441726284731301965429042940494751216764979270637422780707290742224006849313568819848555854148500049601573498707315307764179909528346834981199202177499882145679301069947983642375635637302542203402987447352406469442744552148639999965099330863997622437885195898658594660867903520469933145368195778049507451465181275163423436112078392419125586634735827183805309923934456494433016942137764495227057379167259358096635886419689774375448190323079460940591496886466206951094898940561293213901575462884106869202761927388218811644826178720083301496020122667148472837117025696593858592687180045260728393381660726419289430421493382584241285095488453592049865346918011605942729238103983808620237104019155780397113653640488414084279165336597756602797856475978121597891379200, - -19156636526020062511025282737062697194157664068312595811927262631522948042319209585675375961903844234619207991403476893445885580549976540830245754563834464507828225603428526605259540801185839973871554188008603660607541074686508562814586082551766744347371085949395099075098348039762733618163311666475144301305244557549201012317526828060632274704661215880492981716249066117257791233518275731307906867537485859322607620774230012833787020072828001587469433324439284348702665532640279315055818319119867411430507790822998981942502515708609809177093285437782532637382015447342631539161054188853440342863586615524318064617488064328003896841592494576860770484427069030524625948657507348856052578643946620626101319199350795061198822913273205032770076826759247263918177651194354922161572232837717213802610280713710887672703663112903654590281873709906343575037605523342159187306852540183600876331408541779952806577341808261087562461987288030451414117962229007434813280555299893325569280227011601280446185922662130233153281816266709518611778097839462839697736630154972932501429446053294014597509420082703814891072372603495622271050632406724833696001732922630267859425615451156751890256745761604931386007147599989767208429740291211465223334497950219140572944176908077099939452342696557286828141048924029830375182898121762579234100239325402190167270245326637524799906492903674812729951661789410849832483879701944600637255640136103046967135524655473175523227688834322985176545511192916902536458563345305019259514202776589376357677969698164995394263093523202211463734904575959099436579340003186476791942793959936558459788121136987237183912716263939550402925756763349907126912467092958186603553878892609125106088830313917250118285720569480227246577883650875634658618340980196145928794672750747432721190858494895384696497564701981266543772553041739726776965695249334752511936560934459300942961588669817724490465333634394618815163942265611240541990613135037214036719811089867321322650996888394253270551208013113772635080282362120771416048314499837773731588575774679382578095830287742410011678884993619958537157607694002312824290677420753207272064235049636144632789859495349584163742384654940480845441161736640935335404140641101211934044317045785725583746740979179553020830343049508850754769173085660067558577058182168617028672513985922873080246179451035258665421232853074197341188347009792548007655914157745332726574101971399389661612226601821441474099063141479731013603101743323781313355902276989255147311459229065611730460262625533467376270855238194147506149053394802007993492761128911410705296994478558603288824102149343417105644623546243296360382020153343360613021929048923476123747496423275945821784009455034511209974497418801358720884595397543989615149048887958753628241255510874216988659497175176723346493444738306417440611452274648169547668069021230200338435954855758882184949692352323636982346474480260199169058855589483944021027883915188109883443708958627995625207919673354505901037187653988858166349335154896650176692494895677342160072219451292860117301685525573277247392429797435842554878963881808083918277834724011737948940899177445539504099346407532412650531884311656535343066790911023483493078815613891736174384946032493675845122088585184309323172930281349440250007001822289675783192283976416081178211450707765548072532781558863974041174637504548185620559510712014154498508132779749442387079709932581095349477973056905051396222149090302958483518995814213648089964776039050304477355556907569647969047246355250283321188883271956742610898851746619102198147512047847188273170119991480117456189421463406642055459107876982461881749087576879157829942085690474681357845519020167528448, - -1794364494021503718890330584461923770219562049221622867383667093648562804035835203308314590388701198192116056421725886230506152159043590426548046908700597163341921077173352305573996952495687262714603774097294355469949258081009085634140031230830111149722503259358595980214410436673040687319039100833953820155354708519889088918233476437493354914413290278897472432091178129034840238317255857303146346084847496932315681128645191126370229820305610553132952297831549763221383885892864168817332292412784952433752382335998882359486739529893043522743469655179920121289094051357047660924264420612689188364048005192634933538993635523556798670191522522353197334708530777346712316263856077124823071023475635535018236721997074696110515617671245112004218913107808140454262663024653089961226609962953127396662974939340671577122696071212333084674292708054305877182197561228485246394525000338597596641812122051774370860375283003382439912845292351435472155580623325373329914520358086705875499186249057590308491114376907827461689736628543496957671726184488184759290287990689792007982867430324488980053712368398917153445186335740177854090457686822041847702737988909878387768492466778096319106429489569335849554140223658544110877411198236207380929467300079772182600491122933252648641777346233716850729776415662682675850026533445704520183010396656448521866703179914959877116149318575350728204938788767073226410936541837703456094144792823382333327659257419062469199773243504418714749527550638518878872440868772436078799323956441819873916798245481963138977519607791645521665358675737973153360561383028956208801912691112506477105092722483591111076132949577465238216959708215466780930831956708590206523631341074260454294881529722730038967439659785317980253929030628423862585353193867116940044925627771390432072202038448263071845092556963328008864488481526973282920437561806524784249360319172874165608506093286707886371272197534565567298192535474074653527466338354183198362867530355237439682520533933640446160760098580566137374411565812540065954871061586994117743824902090616106313251822028355222228621595449238494551151196491284679555171015391360723871378517471338795537684170496860435996414595355396676092303044804631001717313346389584968540589825361022914052109604666513785432006173115907847374571801800589713403524277858717748809375577904487988614080665636667361893004097596114759518125583420307257648365185283304910533984931559452407287841911644811070170009921008721241003848448747985060442545557990253475259168728209353609021981211380308184468530729295313820651517573414496464630236144058228375303705735702282425723781972692291316873386164773084863272201296618345885437538900134684427745621955762790268660856677239683666014883863687754132937561057594518991959649375185009081270550227595279558991306817944679455224639539057274050054295117555796366311645188673851048176312995558826902524333006002964161756967797607034796899774431757900354679096014029240688588227499976534552149451080290648056984412752706231276420708384487407655929237113019242442863050818553338827092713816667240598083931938455530184636285294703792018319280838328744522579691015292559449498367721700972950878284253724791399121409628845681769749335403447517416045041488982232732032015312733499217116731832842354853767880038841179929938537796558898092851396700004476727144155416809010216738333274234032304783222036088188507274835357862740107407425098197270419169271252592826907485798511113380670928387267980051489083073696581543911996000974844218042946310001856125427316430144734839500212327997450351879810413008223845098398352908345136674603006738605775131161242068465225408905391631399038656446464, - -144569837637431787211068186862914896076134663637711539657421834572176374470685310002460015822143221117612792884052825714645140391466876999556110278048132091194356021085768005211616539544793403539279182377727307548827176756074281830774581989823823477539482675515097597713222684565573826808477006387225981694487568861034362964749587406574526339204092619621566037671566881700583884320019016786162231182465841266071227615502135000147408086450576550116404965578984616202461256391318625260707181627423225953949894639318845942185337627614582621666663270085589016926136435247592689050151156954360631344914269506405912492672223304859322453305325101334422663274704183829054225636260513571816709490041568358905240876925469852755292912577919919751671406801765813074449686546428843739602140494224064190834352382582401496268551419255346565071629239293139668414520463635211097676415652002028644119917626685463511892721027721392666828425500832727433348138688378102448490101384050839736634416739093829329957237016833249822545961666148245107869105106954045985733619532023612797915602723792873575919514272152799033718408618663107286703828654100086474084578793019331452705609037439997867384436866052549522772184318676322966435334073829118872898494650303760837053959235478650343549813492434543557130640535784095109903581468400038118373790826031088314783586942538921463140997570269698542990014492501502320586139689310865441709687442702035937399557755967829088818063478854387473892339355478768766369841444922021029992757420375094886165668523482987706059479973236717114769353714012044637324909067767914845774627677180851198285601715383432233533954637149751621199358136944323952191399933745241949712577326397948900728199090767859778751166730792262373086159624924265162615246853963820003686115718700943728699949181473051817614638899724287141092419774382582035514824542535786193194942649999531165042643716636499337997291655054241377060236387258562188996087951299309510827849456235996075301793082406122027638786841282402036345065391352801208247951032604764443041045778676502057978917589935825167206410134383082207887265650858174404145345573470637923495274957882660842840546440889879322068073599442268369527272498463822733073926123018011107873909924419136032577927941738369138473307609700812983026912401291741056994321898851954508842840430981781292991355395656926218264678037788761069604902116580749589491374457702302385887412702374645206828953465433918168178232866388034298695688214324962124169723703289540002755885875403338374947017057509272772580942535112638692929048367889749833931325907109494699968549739370286434809535545323707473854501905769120813831172573484822882186832192113178488658722619692220271984305816791734892848533537237702976274752588364395744633692233040047552459929955522678566858716804659607753642653493409834685148943528584359238415901943628977919394038079906924960274295754898580338639533231210557672630418163664689832548498886757322086039640750842880831117963277383454385650923634474068349363399095674547677578894049670890951248568404427193772419905156263810683802036223363756584156307009956864992760620529149055758517973698526537687561153218907930248803297199430062127560087524876165583167178506887819187217776920382976348997389356091013463434684924347951309484477012211291489208150851464797614368129805329146879931307463859323534236374885474588352003216284827659225563826732037660416704998867985875283413787117086757725582902326422490752374822803813300155527123224447140824300160571677395450776590735337214307005256452748705997221711402263314289464163954978101888094531405130526092530208161592693939814958891008, - -9866813215326675150687614292695423309938017318307949550903403719835806946183173729356071115741052402392515518742028381965878854227091687656417241596987292177329746909173042996272529841180289304437714527826992893679930008648394553792428798802583236850398039458173295434854090850393176325807461011240311673069065272324245903678162148350839352288293086079932557125863274113381262697161083781083580366795840613847657410889806501766247126506723243514922328153608175522004567126549566785988255822088754095491332521204305296810075171837885396733139620426110382581444786926775210283919455826316483952678712032480186304074653415375336415442116834833619563842558311131302577199479395796460395363905053843210781863249150381429116425226924439562740953862630760495300485527757248319625045492560327363713233525568858749363716819546011683482609317543681076747265989830856556255689509286804861813021219671689375264900656407514667114445080367606813729120327882222087406915626531046404337060512082753289680645263789908306470851239617498248757518332277259022137827250766289458741519375349384012925574530525899603855470719090490304799913798323602966441991330097460589355575840104787183816950836737555677420281593650997109393031786548707865174686958163816497523545143153228757148847525899479925104273439970302855951649147875383650646573228197113255956546750196077088298049725059621997687421024228098120522800378787067823142797450998737190692529321770928351364793122982936007753910241185580365913751946174358368836672819041572786310539139835031434814072740862890898321580707229043384025991680993775415511397517391865249381250237596226127296799940903951719268872603007927712755683261679023090169985005800313578468347436515757109437007364412706972620193134528708099584345709480031216808511578627835055468534690236963734221964089057955534950391732195008301432339786633721809302159696462742959905730353722323990682891083998406951531321441212411552344347506865205442851150359161822000256960445363590509402986585811508066852972719682961134022527198988261502069682000566081713923068384258929476992983574263901409879340901305432504126077918604871874570427278882768319650839726176163079532252402911180005453965898546900238257777514490586633457545371428777821866755966857752886268513395357529387963636240560340455656098593169818522894652710815867472554677145104966357862990187615554952911607190133372932834049520143925185035339040132590188484708474299001611579618614988683745218653915646045610658174600141102313773566217125617462098713482054742447762556980371435561297504251828494002946684996708478786201980561589498106317263469490102391208114091116642347205067985825624636711238671704930025944331573472754828225666621222345235671616406847959054869279531149935148245264514874791983332244596047335934070112726094099258386464888292832308606692964019404432904518547943007228980740355379808307641003690414061504678600962759914119898100345500236527430630765854417913315470911658638484606566537969313166706142337334524069688183499486419211862729999990625841940451439273027071727699204649758975683509613677710525251398491418496331506468325856221723136234925161390906991163301022401325445717203818675662025201218750803479165829256109735790403597168894638730676406886684324919371583201270764577230863310644391707060193905414262351421386152225510378137133098108656901060982391125062412286741944933961283314498813556344109392578016339839783420658640468922176460860341353340920580462754779336265998732225052237493171112836575082891640840188848409539981201533765761262875862191585552989916905495173087725518999079098515456, - -559049757429129264922098188761362857002900424157796790705639537806295382188282960189260397398335291881934990793390953383031500557160359967568307268192516666993606455516803276366272004455721830393001512609839764701038538482376866745746842570421771035347289867185944199439706473872444746027136731265815886570063990171682441591693512891173759125789646683435967088728084388696933599100469463356035702765726543434316556764002788617131568599692295209458666770168559441450643855154335992743666907646516914226577654166160194756790397812056651290412788461933763747907299825502193070542723040130971085038483099804536196061354376494251671319906626839528440109858660472485424614094970512788414353304085594316621894936063609415087602196721061289621866171916257194100361005178955330168144291196010374014046621858935033024235954134407649561215877145737318837161524528036926367766308419920536727990527194936659804140239124713563120346348814077970683864198184235350876138817945884812703016578037736579224777978310694066575783711322611578578583091112446092299512191146043706637238330587431997447131824026173402770261565241760620087518106390349370070378564987356012455790153626824897348312536092887159992771315431786581497529850883089255802890392068421507557346878596475353984876049043889592993474816079436102073894433921054979060039829012327480420869257635275717405043866844624446703605371171830386176060817489412578584611222968148380240143319142941713549723152333199457693160707743593025182335044781897469961398528400622372503229747278499180478484275970787946007338340787426871769855882641717366897030208905093841456146545611782618847604372927970298473428457840781826754973145580824454887276863713480835358894515035755566149672528277191857295860914472469051447386213940000333840925002643845416734558592171202483068907443293907368525833234447945266897886772336843420326522537776377524780031472134350803595872858046704616593716135717930830613286133937068860331927441113118168912093374302977483590858550571086738437100707742295725326474830227716110172608708057382117555760152033443661682565454487061047376326344763966340437089562471946330177889156369984891470282291284921739619675406570034409989684662526962660916135634248636852067192333649253708409448218927094329343454356293497705469159385174913108275560252946194317251874538076176120960841432330486776960333700511768009627307782454559942904913929523122510164258563028318236922632967514120182477720595440741122905911289807031109679682909233708555269439454193202180330472211143943803002804797194784178740818056575917057944573749084596980745404258776223526668647942906854500994510598556098853139906163810919985473562575471850995094001925141155683532854170745363054154267496204118353588087959707448734416962835100578159281874703551520449312408565307254151429627402719217584487713221652485450245247878068093132025598212915179353634856120884793827104598741309169390112906688006533143132768488706870348326915713007676344430812815375688875422219198994269060591363103696164913128365096839270371433937612524848366555242426382750628459669541324970847550055831389580481424040196059017080986627242461135435885010689333662033235271128844729444609729644917735335652512386002171904417648253297237518529904892778792818427390933449905579746837778153152223156028098055752526439286142227075370018465094944038266307212917946919978265368479477177586114527848011012796440889365892717088602782924653472986937009050363298963512339707493533935883314819912618710198799287221696008811933378655855634483192151099323447295623216812725836447744, - -25577462880037901344139700883846914496752096963183378100788991078496797478634109812760670935577916712297210886900145306813590863937360970484146975285690110304285548070309134676529324659652874472027689207274244506867236445920048812832547089293591957120043182387780425083993357919502873802332278194763161621061201040824008980703813082491017387652849164898356449774551332857106843053767085911806925610247295284941939420761431924760240622241901695458121818837423914865542754544527681141297926612203953130690762450995155852317129257494050498321839919380455361706058231804194197201140060613373094860991147026460997215274496504199948960848075298734523540451264750118279522777298387610250089271970484785622950973363774829900967131058956797887400637613879365720453738867480508939536734643690385331015119097785076335574149918350713659759013140009228970385279209268034382236878596041741374454782786386318394820503913035753808443758007988179493676472302048031059078810142091811667060772013982222877492952940507530025436987264179666363032970502976617574476832355980022038281101013782866422233971507673303922865443843031582347016485998307174326798997909136633966495280526951177610187034586623239585265942332093022011464326465021603377388693289520803909242060973723665913036421815086816238754506746396148483857469535941921020555970437263834332982225292797417350545386956400181835235405288524984199324641817003174664503229953513052834609117244771790483029882142305474204204742004202990346373713948305253920656492581239462199257749480059225801031436493036831661960652324142344662428902546079522461534964901332881610379126059894184086718895896264063292956921038787797864800479785924019505655055373064433861737122294029170418444812211408482953348241998795440760924425159515266927280028366479404661664422178768047767856628988929959166866333812277999850068979284348912443196327523743183432623028090508178189672419137291164973062390290136133354945056266396531587479429804768199874487831243839073122627325606953823416604713976972396349536129848199886733077623144032033999994383691180561383896072832165255880379712047951143837519622141292856524568331427489995362599892983415096231005241903630082334726839472121348248274742270506688772805945592188958311667141062365626453058974622391195092245790292970354573539398661060271342789976032347545442765192526524532158053756166390024032574025795459210542725777998973998629787764436745134649612968893724171487305636221173539861123406437656676933773064165212959264464366434862659865269453020598025694405876896508229926536049289482467060029003297283769930715562386542682726327280057632631094886240798524864354909132736687582948745501084153054167538039442806511812535775911971042115108820781453540719213266410151149673164923002428149193775541502270017279794547067430231289787112336581559183096271731276903237499004185561950275492939365520533390956104397930516967850227189135614054900606477724798091274563063624403990501716047995479991624542820901894644372338987808361628396284389402581136113279388131807934780057899384337555184174777378720509320634636001566386536612695612081399075964619022621596959372364282933852285505772480683681516753023371581206636186410716398338874988483725577186673403584447946585303798792262775770355587473065373628084824336766775201705887371958958981192834537730298532212524127041518650301752404395161299985317550569227691225167201525445502806454844206131448935108360342751688892442850899529806101044366094636483650923418640477598118993132297144543377415420107784288586432512, - -907513641004759890492040333698840770640947761683861163205389196151015720127967440579615984613820379937730621161278446492744835316766675785486896930564155325948842231171758002706771204202538805905102941642590164452017881414905548462947782824590811222439361990697573116310215542970169803422068801285985546379463100515492475282118465114102003027843485783939602175491594521367930185201160533407335493833095560287329141882875473630240297263488738553716074297996076851408283137955799120496718360750253210815847717147917144826143543240236976151323553575374010462316981410873514513433540452841233012294088605053483275211921861838677254863240986535432852046055307207247766417254778585604908541768073107785134381843615871194796056274574859562373357731780474204826377223218122686906734126334847764510985737674277723265705832675123446337514410444885277707146507538285966636291666303047243030671141713534044126527014324707666148309437997687257880254287127877615567063563809347904545883381499964256350293218282148714446847106554881450219175197012983901916975901666029202057733703382456030302255193954841593964959336848286723385954523674200999386664996339883351030617695114359343096481399642097442085596351392617002774181558385617174518061108932480870285414775457583533311092137477622634037718480079470742000737684862975158717673853757856643533021910562952047207526252256031958362748104521464300957980261636482635346519551008368107843941110828631016463392840292396651470064917337065424321927444947469857702432200583923332975805153552404199218761046179861232223365154010742745479578210788815553137427656751905870778700588042752287531479342689885322504524633060797183864186782552185869339305589905356380551863941415062808859790618467447256058089098562445190716900071277266825251126599657527758964785935598298688861397631446268600609783288421845580246830542913069577089162342059610722015917070195996309442100314848005722621060969027548493993198367116369378798896255383871841691860617084331845981200492012746451640028646213348998546356395049340345321484692575550982155949904655536281518118981022192775491636726181840104091567973638578967769527117187381821633258590745483595684326480451408848043126422573910526386024354721765757821562649083848183022361847722281856231085785163582483616655412198290436095525405494772613999821838697465419585264219321818351209320731221227978716945325879398753814645832276350160832796475605829940577209969262085254109978084108246201359450244150140470506789698574164293407197183373379365444744675800427910314013579573522583529066132530544051893846772741203420367882373833427174800516541192194834637332356319954710184558597303693744768029549765488568861104081467822725423202725594868671428666187676186983064867104449754489742206520679046505483611408417551807013723179836124171645505168512812001189428201196071795990542627343873496295917726875200656471578363417555400235758325772664613621343657817034828551373602652922864685378161521468805120724911766346638280727399056139942875052877435918365955146502284782904686425509226568982252397646057321852346043347013700680369764935157489169583450420447638594526990942856302585776795528362647477323129622045624376569322519848320409112656502889635510821170912279124379323959728380206484355217548978442140115842769626738214398459660926198064547982059592199058026409926169923324050034645363621700829993642324419746602770560478750879394701583995726353708436089834225248510222780688765452235594627631290039114948075996059168886233621331968, - -23419337410994725905451053002551344970211918237355212294729134479223141353338086506732751698531031684060402763815659631486730616942110358645982289489385542946345442519512229189376771491375145608839837265561331327354198067341711910331915878027254018845507725037409606954174064649190218083142066890828175495518989996037337901003486604489409171057782535302931047117278845943520488858700736275949908373485124260958954392447053234491681588169439701080667995812026179056981970933907108112543646986715116511224383805106739853934345618954545154983685098951197174102056913820095733602168454792404093708961509639273751983639201100358183846053800619851769680688244261769702052206181148643639164851713747137533652554776823423306317715269282826114407259176336038597703428855254808206786666321053031153321921774003394749827701613102289263485517237400138136882290631858408579091342414056703630724535613384846672221414963216549656540628066391849863435799504329107795688726942674273522673312128168321082000059968224535184401225949544712114162897520655262797772649724410837056795431195336538096921699547802968140696857532080528059893286748278077973866329115052048329140857141530598152144981409121674837729565256902259409202503743803874036376240953460095567607705634741869531687966432783858944593520157853877585616077147525410111817333784408729524315610884954454671376653122267737759949174449432456645210213513339228490083405241341685494748345689494109617343238828199459147403918027429706275650908760699471610291785326024174666255652245933230053084469265250992095906406776043792214982023566352091840845053015034599474021794833083871153241669765343573371217854601709911959686397106358195986658091547568925198598444990175358760851511511344677441043674844018453668558690406881703046541550580632589881004189050014766633827786227996999882956032364827957165683332149192652876491167834009308082079813205497820772249488884289200339436358169750310813942525230994994557745815631433594800128372876424939565925940561759459514764417583968360668360509823278753149674345432015117602164218758947557296499489303740171142024795502821595196470475031716961440565263856339432489166423683291991602187923748450900142829318157034514339481479765815989344595845213192256390040829340241440686916215543883479824002016878167051359235954315163536601149208236768676724090972558401349604277148890240020557375421054805967807685953820812984866191711427349847102480587335561255300378895371099290095254804024844309899079780923559894382571201115168309913918031576503757137313628064366261204083108497241513839625945963904577451099313958507005002882400407019871336443656212773032696299344231474842903583357346380524157708595172664695736424618306178286882214318730201362747947739475749704975401950454252604810408806025895652564324867420677332625661438468276521698159528194675180619403557997247094687742527524431852574822923293111689801774490332242707169064757469692755586287502046800710595176482850848986483822263970646461862702142977258985582594478613714762820147328537065231888893876767679040969883208662508898607240191266303715831882909706630359876792829108143701125328145348338791829609292594702981991412834283702874663774947436231017644632973881461871098137918190047319059018866345096909487454980371459781795669070869002654792503561818286563794645330959381392810125129116908522152842117227857136810228776238756140507253293084689706341869125446017315504271583096533285886222342938564401838954788178144264192, - -390844337789008447866092157319868122643336753056237023589990114164487195334664683792939161315967064077929097225978204349803070408225936796477663487248474599107063994433024410308064087582229253273765424429857393593089586953851471712633116516596079283538761908974320301998057421168587490117650237137164786976887766071257153303103543281566586788141259079347290377662272562634449278903918085133871660328243977962996009674903137694987321261670678203220326254802846143597442774117411478410940655406317909485756008838557178266231442812264738981247423545880913310110928527528184063223448168063623038904603386634997868631585377837644879659016087162791438528525759674536425902261876160629893297396505632897503042017589884258740399069992816763877111344026435218089217912884605608968272258852899379477616437759763225049460808074392143390724392107149627307000711988844493708339767243018893250429063267630055051334305749984705080339750616551279079663670033834406195145889511070520865308522061859533103175146342490307115668249042892442356112367816108273206930371440751539373140782282311109759455781636468022591793812405470469684735051634093935827632255723325289461216754786847315050361035726865211448298687907433166417979518275432832151243170420231500421394808950258998508615151033989486537596752780301742733068276066835409432947094582709121440942485113179788386590577789394518081096518727848944430583396072790881647742853914167357911903474497144522709177126716398155821950518090859913200705807810476880093364112859080555152745519947584114317350960542426579215620434665555213549064857579049367136677168357028543502965452489172822215651991213462863191436558669267281082442227957925498542429686684211550122559703384079284437527984649232276985805781588543490185107613456863524412227487113930015030718315488210240099475017462864653312103333766017432739194330958218583115538557643302024925673354037199365111869580869013501981296473771192414713647021322424723459902073756927948398510689938519852118112865949490750878604372276462485166599583803362825255421493105895242387188463416014334894603468373225321172152661638941696430302666657000540688719460244258657888915516891379355198070600334810652466446158014804689549735538910249750113455607523997053375104328239328777012781491503329182588441800755341417850619713489031687721532241646777658555573761490749609645924167708544664247021997115179676199613230708922349833053481236123264291917588885579806587389660535074665941015828821242654620675256484674973474751871066504059425644453844101303903885380431571451442321709273226920664089487129516065696665294140917057746757319430664102239060712045722878040752209205516810137480540400428354887344815868207809254011958875634569746469677031733676719831733491294877183849511580352119654213499774378321548228631513285663792468916224805927675553652287766854413222343757476526299840982527564194631592474696637209371102431745834707328619501297233087789313751329766909707350769853517545671704266178623793119843028798182074972388279413993763228218963436322396785258604056347804797171402140735963032813412360638547532608672824902068676764472901059861371583776347275487570584640132470375280198993008090844609650123633007961923099137828601195502212562061435629992290676483219649198677563102437585002618539257501083544784061484204531082131509077751769575607493915506960677296399163545668489935768123042906260313148484646570978478090775507180319768729351387470626816, - -3164357949505912180696614026341418762462117285952954762957560702254467641281146570935353702503353615339723854882342959996664412720510381009136993200731808635224029129539815445933563076688869544075639168864788680097560584307978732890166263488848073287303581442479021365698344612971958589627042111303554091520576768953121397971202416941804099623955986072545791865110850950226257822975243281452903527828254503036084445075528109022885462773259643894675562407188109083224491867676153271114922567854192430494921276874625596358227610494076347647293354756582185530191059467173225752392341031222650998710697334725875734598923146234410567818185882359383952452920846826247647177846161762431595758482837810970792344698324859319354078886593848217114502744667863109943269358214502052475567447153987407144875354985156567618751383491745013076050460213874410039511323687901534244213101290116490866190299935547532517378678775935613971717444918513679348169911871176778146694160221731944879362109797415189066837642490910780892728318172846648945355217903523435925459701708680932925090087581217619127600661349349893566010243754618438667504382712547997154163677582689347070132594116812232213286171834281174471453330391674761517024065862091611021399369313527389136589687639733669970075854744450961109743399042985202480008238745299215541917820860162024694100681455632881500737328899590706980074195837329354031163804279420653841767425542871663204576356643466304316597431447036895864236324260300505493452596013706086840046090760798121470371861939142855817838869311136804287015126021032283535877226935275500652677431936116912123861249394120036535773325726576198416930298353161205362110905029011840516812469537742216451864903634569865998797018434535694092516377784146050756078136442618297390324429925660804545634355522534176779686340232239748673574856577453211881344781671954651497193692204863793462339186715167341496085093982211575140316031007449808418660353812433238874054621075928134396101717322598981730825463651127907450912782314281990110771350456817802430418866476510788090064265612650488936344064731580129109544481621244061250004855980565649293874740068498050470867905024752083739233436980125092309698081380734486221682890369884880647746840016953308434849621663663618761158988500153462991272408385247936949636834849029713806620571585136769651322164881831787401324699718126256291012014549846430195989929389665652983728706345339250536029475146090944511362405517948972142773236122138331746680370020430323591519145973422068692906413189238631890878177001543007666504250045747858002665304395866579653032904349254938539495977528735183406715418632766640609962282324800608963899840251823920644162453346229802530781629086307873105076309523682452486419626639160284567071732027564119930647133033095330218167774855542279257778151526128737479910525393966806825829998158508298126762518568755366550822678255981049661805448805025986462856770551911983417275970762355469406161439585726338912508600009619303754002777141132006409264888455261134645146341890697436108351202606754304093234805310330348728651429432301168974699638430895526168838638072833292714789496031780544695927948861838717491300899634074567658246956989734772442536638636982765932052636686617461650182633304543487862208334864719447398566226446828085840397798912543156624549560745513065293094230189007094396459121186211063056212554180276303296614126766159432928722944, -] - - -end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Floor/Consts.lean b/formal/ln/LnProof/LnProof/Floor/Consts.lean index ef3aabe01..94f5ae427 100644 --- a/formal/ln/LnProof/LnProof/Floor/Consts.lean +++ b/formal/ln/LnProof/LnProof/Floor/Consts.lean @@ -6,14 +6,15 @@ open FormalYul open FormalYul.Preservation /-! -# Constant-piece exponential caps +# Constant-piece caps for the strict-margin bound Every exponent in the floor-specification assembly is an integer multiple of `1/(10^27 2^99)`: the model's quotient contributes `X1/2^99`, the exponent word contributes `k LN2c/(2^72 10^27)`, and the bias contributes -`BIASc/(2^72 10^27)`. This file pins two-sided caps for the two constant -pieces and a lower cap for one output ulp, each by a single kernel-checked -partial sum (`capUB_of_partial` carries the geometric tail). +`BIASc/(2^72 10^27)`. The strict-margin bound uses two-sided caps for the +scaled `ln 2` piece, a lower cap for the bias, and a lower cap for one output +ulp. Each cap is pinned by a kernel-checked partial sum; upper caps also carry +the geometric tail. -/ set_option maxRecDepth 8192 @@ -31,12 +32,6 @@ theorem cap2U : capUB (LN2c * 2 ^ 27) QS (2 * (10 ^ 40 + 1)) (10 ^ 40) := by theorem cap2L : capLB (LN2c * 2 ^ 27) QS (2 * (10 ^ 40 - 1)) (10 ^ 40) := ⟨40, by decide⟩ -/-- `e^(BIASc 2^27 / QS) ≤ (S/10^18)(1 - 3.383e-28)`. -/ -theorem capBU : capUB (BIASc * 2 ^ 27) QS (Sc * (10 ^ 31 - 3383)) - (10 ^ 18 * 10 ^ 31) := by - refine capUB_of_partial (K := 130) QS_pos (by decide) ?_ - decide - /-- `e^(BIASc 2^27 / QS) ≥ (S/10^18)(1 - 3.404e-28)`. -/ theorem capBL : capLB (BIASc * 2 ^ 27) QS (Sc * (10 ^ 31 - 3384)) (10 ^ 18 * 10 ^ 31) := diff --git a/formal/ln/LnProof/LnProof/Floor/Model.lean b/formal/ln/LnProof/LnProof/Floor/Model.lean index 94a8c01fc..4ffbad5e9 100644 --- a/formal/ln/LnProof/LnProof/Floor/Model.lean +++ b/formal/ln/LnProof/LnProof/Floor/Model.lean @@ -24,6 +24,79 @@ open LnYul Common.Poly /-- Mantissa word of `x`. -/ def mant (x : Nat) : Nat := evmShr 160 (evmShl (evmClz x) x) +/-- Binade window for the mantissa, low-shift side. -/ +theorem mant_window_le {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) + (hc : evmClz x ≤ 160) : + mant x * 2 ^ (160 - evmClz x) ≤ x ∧ + x < (mant x + 1) * 2 ^ (160 - evmClz x) := by + obtain ⟨me, _, _⟩ := mant_facts h1 h2 + have hclz : evmClz x = 255 - Nat.log2 x := evmClz_eq h1 (by omega) + have hm : mant x = x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 := me + rw [hclz] at hc ⊢ + have hdm := Nat.div_add_mod (x * 2 ^ (255 - Nat.log2 x)) (2 ^ 160) + have hml := Nat.mod_lt (x * 2 ^ (255 - Nat.log2 x)) (y := 2 ^ 160) (by decide) + have hsplit : 2 ^ (255 - Nat.log2 x) * 2 ^ (160 - (255 - Nat.log2 x)) = 2 ^ 160 := by + rw [← Nat.pow_add] + congr 1 + omega + rw [hm] + generalize hgq : x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 = q at * + generalize hgA : (2 : Nat) ^ (255 - Nat.log2 x) = A at * + generalize hgB : (2 : Nat) ^ (160 - (255 - Nat.log2 x)) = B at * + have hA0 : 0 < A := by rw [← hgA]; exact Nat.pow_pos (by omega) + constructor + · refine Nat.le_of_mul_le_mul_left ?_ hA0 + have e1 : A * (q * B) = 2 ^ 160 * q := by + rw [show A * (q * B) = q * (A * B) from by + simp only [Nat.mul_left_comm], hsplit] + exact Nat.mul_comm _ _ + have e2 : A * x = x * A := Nat.mul_comm _ _ + generalize hg1 : A * (q * B) = T1 at e1 ⊢ + generalize hg3 : A * x = T3 at e2 ⊢ + generalize hg4 : x * A = T4 at e2 hdm + generalize hg5 : 2 ^ 160 * q = T5 at e1 hdm + omega + · have hlt : x * A < (q + 1) * 2 ^ 160 := by + have e : (q + 1) * 2 ^ 160 = 2 ^ 160 * q + 2 ^ 160 := by + rw [Nat.add_mul, Nat.one_mul, Nat.mul_comm] + omega + refine Nat.lt_of_mul_lt_mul_left (a := A) ?_ + have e1 : A * x = x * A := Nat.mul_comm _ _ + have e2 : A * ((q + 1) * B) = (q + 1) * 2 ^ 160 := by + rw [show A * ((q + 1) * B) = (q + 1) * (A * B) from by + simp only [Nat.mul_assoc, Nat.mul_comm], hsplit] + generalize hg1 : A * x = T1 at e1 ⊢ + generalize hg2 : x * A = T2 at e1 hlt + generalize hg3 : A * ((q + 1) * B) = T3 at e2 ⊢ + generalize hg5 : (q + 1) * 2 ^ 160 = T5 at e2 hlt + omega + +/-- Binade window, high-shift side: the mantissa is exact. -/ +theorem mant_window_gt {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) + (hc : 160 < evmClz x) : + mant x = x * 2 ^ (evmClz x - 160) := by + obtain ⟨me, _, _⟩ := mant_facts h1 h2 + have hclz : evmClz x = 255 - Nat.log2 x := evmClz_eq h1 (by omega) + have hm : mant x = x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 := me + rw [hclz] at hc ⊢ + have hsplit : (2 : Nat) ^ (255 - Nat.log2 x) = + 2 ^ 160 * 2 ^ ((255 - Nat.log2 x) - 160) := by + rw [← Nat.pow_add] + congr 1 + omega + rw [hm, hsplit] + have e : x * (2 ^ 160 * 2 ^ ((255 - Nat.log2 x) - 160)) = + x * 2 ^ ((255 - Nat.log2 x) - 160) * 2 ^ 160 := by + simp only [Nat.mul_comm, Nat.mul_left_comm] + rw [e] + exact Nat.mul_div_cancel _ (by decide) + +theorem clz_bounds {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : + 1 ≤ evmClz x ∧ evmClz x ≤ 255 := by + have hclz : evmClz x = 255 - Nat.log2 x := evmClz_eq h1 (by omega) + have hlog : Nat.log2 x < 255 := (Nat.log2_lt (by omega)).mpr (by omega) + omega + /-- Signed `ln2 * k` summand for clz value `c`. -/ def ln2kInt (c : Nat) : Int := if c ≤ 160 then (LN2c : Int) * ((160 - c : Nat) : Int) @@ -33,18 +106,12 @@ theorem ln2kInt_eq {c : Nat} (hc : c < 256) : int256 (evmMul LN2c (evmSub 160 c)) = ln2kInt c := ln2k_exact hc -theorem ln2kInt_bound {c : Nat} (hc : c < 256) : - -(310963026251328585646059498617736427643747124513200 : Int) ≤ ln2kInt c ∧ - ln2kInt c ≤ (523727202107500775824942313461450825505258314969600 : Int) := by - rw [← ln2kInt_eq hc] - exact ln2k_bound hc - /-- The pre-shift accumulator decomposes exactly. -/ theorem r4_value {m : Nat} (h1 : MLO ≤ m) (h2 : m < MHI) {c : Nat} (hc : c < 256) : int256 (evmAdd (evmAdd (evmMul (x1W (zWord m)) Kc) (evmMul LN2c (evmSub 160 c))) BIASc) = int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by have hB := r1_bound h1 h2 have hr1w : x1W (zWord m) < 2 ^ 256 := by unfold x1W; exact evmSdiv_lt _ _ have hW := ln2k_bound hc @@ -66,7 +133,7 @@ theorem r4_value {m : Nat} (h1 : MLO ≤ m) (h2 : m < MHI) {c : Nat} (hc : c < 2 (by rw [e2]; clear e2 hKc hKlt; simp only [ipow255]; omega) (by rw [e2]; clear e2 hKc hKlt; simp only [ipow255]; omega) have hBIlt : BIASc < 2 ^ 256 := by simp only [BIASc]; omega - have hBI : int256 BIASc = (116873961749927929127912020551516294209054209107914 : Int) := by + have hBI : int256 BIASc = (116873961749927929127912020551560854268589826112230 : Int) := by rw [toInt_of_lt (by simp only [BIASc]; omega)] simp only [BIASc] omega @@ -108,9 +175,9 @@ theorem lnWadToRayBody_floor_bracket {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) (hne : x ≠ 1000000000000000000) : int256 (lnWadToRayBody x) * 4722366482869645213696 ≤ int256 (x1W (zWord (mant x))) * 7450580596923828125 + ln2kInt (evmClz x) + - 116873961749927929127912020551516294209054209107914 ∧ + 116873961749927929127912020551560854268589826112230 ∧ int256 (x1W (zWord (mant x))) * 7450580596923828125 + ln2kInt (evmClz x) + - 116873961749927929127912020551516294209054209107914 < + 116873961749927929127912020551560854268589826112230 < int256 (lnWadToRayBody x) * 4722366482869645213696 + 4722366482869645213696 := by have hx256 : x < 2 ^ 256 := by omega diff --git a/formal/ln/LnProof/LnProof/Floor/Spec.lean b/formal/ln/LnProof/LnProof/Floor/Spec.lean index 963a0ec13..c1c9b1061 100644 --- a/formal/ln/LnProof/LnProof/Floor/Spec.lean +++ b/formal/ln/LnProof/LnProof/Floor/Spec.lean @@ -1,4 +1,6 @@ import LnProof.Floor.Assembly +import LnProof.Floor.CarryIndependent.CertificateRuntime +import LnProof.Floor.CarryIndependent.Upper open FormalYul open FormalYul.Preservation @@ -12,7 +14,7 @@ Top-line cut statement: for every input `1 ≤ x < 2^255`, the body output The two sides are arithmetized without real numbers through the partial sums `S_N(t) = Σ_{j≤N} t^j/j!` of the exponential, using -the Taylor-cut interface from `LnProof.Foundation.ExpSum`: +the Taylor-cut interface from `Common.Foundation.ExpSum`: * `FloorSpecA` says `e^(r/10^27) ≤ x/10^18` (for negative `r`, the reciprocal form `e^(|r|/10^27) ≥ 10^18/x`), corresponding to @@ -82,83 +84,11 @@ theorem lnWadToRayBody_at_wad : int256 (lnWadToRayBody 1000000000000000000) = 0 rw [h] decide -/-- Binade window for the mantissa, low-shift side. -/ -theorem mant_window_le {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) - (hc : evmClz x ≤ 160) : - mant x * 2 ^ (160 - evmClz x) ≤ x ∧ x < (mant x + 1) * 2 ^ (160 - evmClz x) := by - obtain ⟨me, _, _⟩ := mant_facts h1 h2 - have hclz : evmClz x = 255 - Nat.log2 x := evmClz_eq h1 (by omega) - have hm : mant x = x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 := me - rw [hclz] at hc ⊢ - have hdm := Nat.div_add_mod (x * 2 ^ (255 - Nat.log2 x)) (2 ^ 160) - have hml := Nat.mod_lt (x * 2 ^ (255 - Nat.log2 x)) (y := 2 ^ 160) (by decide) - have hsplit : 2 ^ (255 - Nat.log2 x) * 2 ^ (160 - (255 - Nat.log2 x)) = 2 ^ 160 := by - rw [← Nat.pow_add] - congr 1 - omega - rw [hm] - generalize hgq : x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 = q at * - generalize hgA : (2 : Nat) ^ (255 - Nat.log2 x) = A at * - generalize hgB : (2 : Nat) ^ (160 - (255 - Nat.log2 x)) = B at * - have hA0 : 0 < A := by rw [← hgA]; exact Nat.pow_pos (by omega) - constructor - · refine Nat.le_of_mul_le_mul_left ?_ hA0 - have e1 : A * (q * B) = 2 ^ 160 * q := by - rw [show A * (q * B) = q * (A * B) from by - simp only [Nat.mul_left_comm], hsplit] - exact Nat.mul_comm _ _ - have e2 : A * x = x * A := Nat.mul_comm _ _ - generalize hg1 : A * (q * B) = T1 at e1 ⊢ - generalize hg3 : A * x = T3 at e2 ⊢ - generalize hg4 : x * A = T4 at e2 hdm - generalize hg5 : 2 ^ 160 * q = T5 at e1 hdm - omega - · have hlt : x * A < (q + 1) * 2 ^ 160 := by - have e : (q + 1) * 2 ^ 160 = 2 ^ 160 * q + 2 ^ 160 := by - rw [Nat.add_mul, Nat.one_mul, Nat.mul_comm] - omega - refine Nat.lt_of_mul_lt_mul_left (a := A) ?_ - have e1 : A * x = x * A := Nat.mul_comm _ _ - have e2 : A * ((q + 1) * B) = (q + 1) * 2 ^ 160 := by - rw [show A * ((q + 1) * B) = (q + 1) * (A * B) from by - simp only [Nat.mul_assoc, Nat.mul_comm], hsplit] - generalize hg1 : A * x = T1 at e1 ⊢ - generalize hg2 : x * A = T2 at e1 hlt - generalize hg3 : A * ((q + 1) * B) = T3 at e2 ⊢ - generalize hg5 : (q + 1) * 2 ^ 160 = T5 at e2 hlt - omega - -/-- Binade window, high-shift side: the mantissa is exact. -/ -theorem mant_window_gt {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) - (hc : 160 < evmClz x) : - mant x = x * 2 ^ (evmClz x - 160) := by - obtain ⟨me, _, _⟩ := mant_facts h1 h2 - have hclz : evmClz x = 255 - Nat.log2 x := evmClz_eq h1 (by omega) - have hm : mant x = x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 := me - rw [hclz] at hc ⊢ - have hsplit : (2 : Nat) ^ (255 - Nat.log2 x) = - 2 ^ 160 * 2 ^ ((255 - Nat.log2 x) - 160) := by - rw [← Nat.pow_add] - congr 1 - omega - rw [hm, hsplit] - have e : x * (2 ^ 160 * 2 ^ ((255 - Nat.log2 x) - 160)) = - x * 2 ^ ((255 - Nat.log2 x) - 160) * 2 ^ 160 := by - simp only [Nat.mul_comm, Nat.mul_left_comm] - rw [e] - exact Nat.mul_div_cancel _ (by decide) - -theorem clz_bounds {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : - 1 ≤ evmClz x ∧ evmClz x ≤ 255 := by - have hclz : evmClz x = 255 - Nat.log2 x := evmClz_eq h1 (by omega) - have hlog : Nat.log2 x < 255 := (Nat.log2_lt (by omega)).mpr (by omega) - omega - /-- On the `m ≥ S` branch with a nonnegative shift, the accumulator is positive, so the output cannot be negative. -/ theorem v_pos_ge_pos {m c : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) (hc : c ≤ 160) : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 + ln2kInt c + - 116873961749927929127912020551516294209054209107914 := by + 116873961749927929127912020551560854268589826112230 := by have hX1 := x1_nonneg_geF h1 h2 have hx0 : 0 ≤ int256 (x1W (zWord m)) * 7450580596923828125 := Int.mul_nonneg hX1 (by omega) @@ -192,50 +122,55 @@ theorem lnWadToRayBody_floor {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : unfold FloorSpecB rw [if_pos (by omega)] exact ⟨1, by decide +kernel⟩ - · obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne + · obtain ⟨me, hmlo, hmhi⟩ := mant_facts h1 h2 + have hmant_eq : mant x = x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 := me + have hmant_lo : MLO ≤ mant x := by rw [hmant_eq]; exact hmlo + have hmant_hi : mant x < MHI := by rw [hmant_eq]; exact hmhi + have hcoreRuntime := LnFloorCarry.certified_mantissa_runtime_core_bound + hmant_lo hmant_hi + have hray : (LnFloorCarry.rayScale : Real) = 10 ^ 27 := by + norm_num [LnFloorCarry.rayScale] + have hlimit : + LnFloorCarry.coreErrorLimit = + (LnFloorCarry.coreErrorNum : Real) / LnFloorCarry.coreErrorDen := by + norm_num [LnFloorCarry.coreErrorLimit, LnFloorCarry.coreErrorNum, + LnFloorCarry.coreErrorDen] + have hcore : + LnFloorCarry.coreErrorRay (mant x) + (int256 (x1W (zWord (mant x)))) < + (LnFloorCarry.coreErrorNum : Real) / LnFloorCarry.coreErrorDen := by + rw [hray, hlimit] at hcoreRuntime + simpa only [LnFloorCarry.coreErrorRay] using hcoreRuntime + have haCut := LnFloorCarry.lnWadToRayBody_cut_of_core_bound + h1 h2 hne hcore + have ha : FloorSpecA (int256 (lnWadToRayBody x)) x := by + simpa [FloorSpecA, CutLeLogWadRay, CutExpLe, CutRatioLeExp] using haCut + obtain ⟨hbr1, hbr2⟩ := lnWadToRayBody_floor_bracket h1 h2 hne rw [show (4722366482869645213696 : Int) = 2 ^ 72 from by decide] at hbr1 hbr2 have hbr2' : int256 (x1W (zWord (mant x))) * 7450580596923828125 + - ln2kInt (evmClz x) + 116873961749927929127912020551516294209054209107914 < + ln2kInt (evmClz x) + 116873961749927929127912020551560854268589826112230 < (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 := by have e : (int256 (lnWadToRayBody x) + 1) * 2 ^ 72 = int256 (lnWadToRayBody x) * 2 ^ 72 + 2 ^ 72 := by rw [Int.add_mul, Int.one_mul] omega - -- Generalize the body word: it is the self-corrected floor, whose term - -- doubles the accumulator; keeping it opaque avoids reducing it below. - revert hbr1 hbr2' - generalize int256 (lnWadToRayBody x) = R - intro hbr1 hbr2' - obtain ⟨me, hmlo, hmhi⟩ := mant_facts h1 h2 - have hmant_eq : mant x = x * 2 ^ (255 - Nat.log2 x) / 2 ^ 160 := me - have hmant_lo : MLO ≤ mant x := by rw [hmant_eq]; exact hmlo - have hmant_hi : mant x < MHI := by rw [hmant_eq]; exact hmhi + generalize int256 (lnWadToRayBody x) = R at hbr1 hbr2' ha ⊢ obtain ⟨hc1, hc255⟩ := clz_bounds h1 h2 rcases Nat.lt_or_ge (mant x) Sc with hbranch | hbranch · -- m < S rcases Nat.lt_or_ge 160 (evmClz x) with hcgt | hc · have hw := mant_window_gt h1 h2 hcgt constructor - · unfold FloorSpecA - rcases Int.lt_or_le R 0 with hr | hr - · rw [if_neg (by omega)] - exact an_lt_neg hmant_lo hbranch hcgt hc255 hbr1 hbr2' hr hw - · rw [if_pos hr] - exact up_lt_neg hmant_lo hbranch hcgt hc255 hbr1 hr hw + · exact ha · unfold FloorSpecB rcases Int.lt_or_le R (-1) with hr | hr · rw [if_neg (by omega)] exact bn_lt_neg hmant_lo hbranch hcgt hc255 hbr2' (by omega) hw · rw [if_pos (by omega)] exact lo_lt_neg hmant_lo hbranch hcgt hc255 hbr2' hbr1 (by omega) hw - · obtain ⟨hw1, hw2⟩ := mant_window_le h1 h2 hc + · obtain ⟨_, hw2⟩ := mant_window_le h1 h2 hc constructor - · unfold FloorSpecA - rcases Int.lt_or_le R 0 with hr | hr - · rw [if_neg (by omega)] - exact an_lt_pos hmant_lo hbranch hc1 hc hbr1 hbr2' hr hw1 - · rw [if_pos hr] - exact up_lt_pos hmant_lo hbranch hc1 hc hbr1 hr hw1 + · exact ha · unfold FloorSpecB rcases Int.lt_or_le R (-1) with hr | hr · rw [if_neg (by omega)] @@ -246,19 +181,14 @@ theorem lnWadToRayBody_floor {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : rcases Nat.lt_or_ge 160 (evmClz x) with hcgt | hc · have hw := mant_window_gt h1 h2 hcgt constructor - · unfold FloorSpecA - rcases Int.lt_or_le R 0 with hr | hr - · rw [if_neg (by omega)] - exact an_ge_neg hbranch hmant_hi hcgt hc255 hbr1 hbr2' hr hw - · rw [if_pos hr] - exact up_ge_neg hbranch hmant_hi hcgt hc255 hbr1 hr hw + · exact ha · unfold FloorSpecB rcases Int.lt_or_le R (-1) with hr | hr · rw [if_neg (by omega)] exact bn_ge_neg hbranch hmant_hi hcgt hc255 hbr2' (by omega) hw · rw [if_pos (by omega)] exact lo_ge_neg hbranch hmant_hi hcgt hc255 hbr2' hbr1 (by omega) hw - · obtain ⟨hw1, hw2⟩ := mant_window_le h1 h2 hc + · obtain ⟨_, hw2⟩ := mant_window_le h1 h2 hc have hVpos := v_pos_ge_pos hbranch hmant_hi hc have hrpos : 0 ≤ R := by rcases Int.lt_or_le R 0 with hr | hr @@ -271,9 +201,7 @@ theorem lnWadToRayBody_floor {x : Nat} (h1 : 1 ≤ x) (h2 : x < 2 ^ 255) : omega · exact hr constructor - · unfold FloorSpecA - rw [if_pos hrpos] - exact up_ge_pos hbranch hmant_hi hc1 hc hbr1 hrpos hw1 + · exact ha · unfold FloorSpecB rw [if_pos (by omega)] exact lo_ge_pos hbranch hmant_hi hc1 hc hbr2' (by omega) hw2 diff --git a/formal/ln/LnProof/LnProof/Floor/Window.lean b/formal/ln/LnProof/LnProof/Floor/Window.lean index d6513e9ce..5c413e8ef 100644 --- a/formal/ln/LnProof/LnProof/Floor/Window.lean +++ b/formal/ln/LnProof/LnProof/Floor/Window.lean @@ -1,21 +1,18 @@ import LnProof.Floor.Caps -import LnProof.Floor.Budget import LnProof.Floor.Consts -import LnProof.Floor.CertGeUp import LnProof.Floor.CertGeLo -import LnProof.Floor.CertLtUp import LnProof.Floor.CertLtLo open FormalYul open FormalYul.Preservation /-! -# Full-branch X1 caps +# Full-branch X1 lower caps The certificate rationals only bracket the pipeline outside the `|m - S| ≤ 45` window, where the certified ε keeps its margin. Inside the window the pipeline argument is within a few parts in `10^30` of -zero, so the caps hold pointwise with room to spare; they are checked +zero, so the lower caps hold pointwise with room to spare; they are checked here by kernel evaluation of the partial-sum conditions at each of the 91 mantissas, and combined with the certificate inequalities into caps that cover each whole branch. @@ -29,13 +26,6 @@ set_option maxRecDepth 10000 /-- Pointwise window check, `m = Sc + i`, `0 ≤ i ≤ 45`. -/ def wCheckGe (i : Nat) : Bool := decide (0 ≤ int256 (x1W (zWord (Sc + i)))) && - decide (2 * ((int256 (x1W (zWord (Sc + i)))).toNat * 1000000000000000000000000000) ≤ - 24 * QS) && - decide ((expNum 22 ((int256 (x1W (zWord (Sc + i)))).toNat * - 1000000000000000000000000000) QS * (23 * QS) + - 2 * ((int256 (x1W (zWord (Sc + i)))).toNat * 1000000000000000000000000000) ^ 23) * - 560227709747861399187319382270000000000000000000000000000000 ≤ - (Sc + i) * 10000000000000000000000000003382 * (fact 23 * QS ^ 23)) && decide ((Sc + i) * 9999999999999999999999999996615 * (fact 22 * QS ^ 22) ≤ expNum 22 ((int256 (x1W (zWord (Sc + i)))).toNat * 1000000000000000000000000000) QS * 560227709747861399187319382270000000000000000000000000000000) @@ -51,12 +41,7 @@ def wCheckLt (i : Nat) : Bool := 1000000000000000000000000000) ^ 23) * ((Sc - 45 + i) * 9999999999999999999999999996615) ≤ 560227709747861399187319382270000000000000000000000000000000 * - (fact 23 * QS ^ 23)) && - decide (560227709747861399187319382270000000000000000000000000000000 * - (fact 22 * QS ^ 22) ≤ - expNum 22 ((-int256 (x1W (zWord (Sc - 45 + i)))).toNat * - 1000000000000000000000000000) QS * - ((Sc - 45 + i) * 10000000000000000000000000003382)) + (fact 23 * QS ^ 23)) theorem wCheckGe_all : (List.range 46).all wCheckGe = true := by decide +kernel @@ -66,24 +51,16 @@ theorem wCheckLt_all : (List.range 45).all wCheckLt = true := by theorem wGe_facts {m : Nat} (h1 : Sc ≤ m) (h2 : m ≤ Sc + 45) : 0 ≤ int256 (x1W (zWord m)) ∧ - capUB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS - (m * 10000000000000000000000000003382) - 560227709747861399187319382270000000000000000000000000000000 ∧ capLB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS (m * 9999999999999999999999999996615) 560227709747861399187319382270000000000000000000000000000000 := by have hi := List.all_eq_true.mp wCheckGe_all (m - Sc) (List.mem_range.mpr (by omega)) simp only [wCheckGe, Bool.and_eq_true, decide_eq_true_eq] at hi rw [show Sc + (m - Sc) = m from by omega] at hi - obtain ⟨⟨⟨hsign, hH⟩, hUB⟩, hLB⟩ := hi - refine ⟨hsign, ?_, ⟨22, hLB⟩⟩ - exact capUB_of_partial QS_pos hH hUB + exact ⟨hi.1, ⟨22, hi.2⟩⟩ theorem wLt_facts {m : Nat} (h1 : Sc - 45 ≤ m) (h2 : m < Sc) : int256 (x1W (zWord m)) ≤ 0 ∧ - capLB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS - 560227709747861399187319382270000000000000000000000000000000 - (m * 10000000000000000000000000003382) ∧ capUB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS 560227709747861399187319382270000000000000000000000000000000 (m * 9999999999999999999999999996615) := by @@ -91,8 +68,8 @@ theorem wLt_facts {m : Nat} (h1 : Sc - 45 ≤ m) (h2 : m < Sc) : (List.mem_range.mpr (by simp only [Sc] at h1 h2 ⊢; omega)) simp only [wCheckLt, Bool.and_eq_true, decide_eq_true_eq] at hi rw [show Sc - 45 + (m - (Sc - 45)) = m from by simp only [Sc] at h1 ⊢; omega] at hi - obtain ⟨⟨⟨hsign, hH⟩, hUB⟩, hLB⟩ := hi - refine ⟨hsign, ⟨22, hLB⟩, ?_⟩ + obtain ⟨⟨hsign, hH⟩, hUB⟩ := hi + refine ⟨hsign, ?_⟩ exact capUB_of_partial QS_pos hH hUB /-! ## Full-branch caps and signs -/ @@ -109,25 +86,12 @@ theorem x1_nonpos_ltF {m : Nat} (h1 : MLO ≤ m) (h2 : m < Sc) : · exact x1_nonpos_lt h1 (by simp only [Sc] at ho ⊢; omega) · exact (wLt_facts hw h2).1 -theorem x1capGeUpF {m : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) : - capUB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS - (m * 10000000000000000000000000003382) - 560227709747861399187319382270000000000000000000000000000000 := by - rcases Nat.lt_or_ge m (Sc + 46) with hw | ho - · exact (wGe_facts h1 (by omega)).2.1 - · have hup := geUp_nonnegOn (m : Int) - (by simp only [Sc] at ho; omega) (by simp only [MHI] at h2; omega) - have h := x1capGeUp ho h2 hup - rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS - from by decide] at h - exact h - theorem x1capGeLoF {m : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) : capLB ((int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS (m * 9999999999999999999999999996615) 560227709747861399187319382270000000000000000000000000000000 := by rcases Nat.lt_or_ge m (Sc + 46) with hw | ho - · exact (wGe_facts h1 (by omega)).2.2 + · exact (wGe_facts h1 (by omega)).2 · have hlo := geLo_nonnegOn (m : Int) (by simp only [Sc] at ho; omega) (by simp only [MHI] at h2; omega) have h := x1capGeLo ho h2 hlo @@ -135,19 +99,6 @@ theorem x1capGeLoF {m : Nat} (h1 : Sc ≤ m) (h2 : m < MHI) : from by decide] at h exact h -theorem x1capLtUpF {m : Nat} (h1 : MLO ≤ m) (h2 : m < Sc) : - capLB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS - 560227709747861399187319382270000000000000000000000000000000 - (m * 10000000000000000000000000003382) := by - rcases Nat.lt_or_ge m (Sc - 45) with ho | hw - · have hup := ltUp_nonnegOn (m : Int) - (by simp only [MLO] at h1; omega) (by simp only [Sc] at ho ⊢; omega) - have h := x1capLtUp h1 (by simp only [Sc] at ho ⊢; omega) hup - rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS - from by decide] at h - exact h - · exact (wLt_facts hw h2).2.1 - theorem x1capLtLoF {m : Nat} (h1 : MLO ≤ m) (h2 : m < Sc) : capUB ((-int256 (x1W (zWord m))).toNat * 1000000000000000000000000000) QS 560227709747861399187319382270000000000000000000000000000000 @@ -159,6 +110,6 @@ theorem x1capLtLoF {m : Nat} (h1 : MLO ≤ m) (h2 : m < Sc) : rw [show (633825300114114700748351602688000000000000000000000000000 : Nat) = QS from by decide] at h exact h - · exact (wLt_facts hw h2).2.2 + · exact (wLt_facts hw h2).2 end LnFloorCert diff --git a/formal/ln/LnProof/LnProof/Foundation.lean b/formal/ln/LnProof/LnProof/Foundation.lean deleted file mode 100644 index edda25870..000000000 --- a/formal/ln/LnProof/LnProof/Foundation.lean +++ /dev/null @@ -1,16 +0,0 @@ -/-! -# Foundation facade - -Domain-agnostic primitives this proof relies on: EVM-word arithmetic transport -(`Word`, `WordDiv`, local), plus the function-agnostic machinery from the -shared `Common` package — the exponential partial-sum interface (`Common.Exp`) -and the polynomial-positivity / Kronecker certificate machinery -(`Common.Poly`). No `lnWad`-specific semantics live here. --/ -import LnProof.Foundation.Word -import LnProof.Foundation.WordDiv -import Common.Foundation.ExpSum -import Common.Foundation.Poly -import Common.Foundation.ShiftCert -import Common.Foundation.Kronecker -import Common.Foundation.KroneckerShift diff --git a/formal/ln/LnProof/LnProof/Model/Body.lean b/formal/ln/LnProof/LnProof/Model/Body.lean index 91bceac8f..69b115d4e 100644 --- a/formal/ln/LnProof/LnProof/Model/Body.lean +++ b/formal/ln/LnProof/LnProof/Model/Body.lean @@ -32,18 +32,14 @@ def Q2c : Nat := 53722296096946541673620529149 def Q1c : Nat := 16613772931382142257332678212554 def Kc : Nat := 7450580596923828125 def LN2c : Nat := 3273295013171879848905889459134067659407864468560 -def BIASc : Nat := 116873961749927929127912020551516294209054209107914 +def BIASc : Nat := 116873961749927929127912020551560854268589826112230 /-- Largest |z| over the mantissa domain. -/ def Zc : Nat := 217494458298375249691265569565 -theorem Zc_def : Zc = ((Sc - 2 ^ 95) * 2 ^ 100) / (2 ^ 95 + Sc) := by decide - /-- Largest `u`. -/ def Uc : Nat := 2332259347626381040680638252 -theorem Uc_def : Uc = Zc * Zc / 2 ^ 104 := by decide - def SLOPP1 : Int := 19342813113834066795298815 def SLOPP2 : Int := 69057699520159162110141648894228821086113826043390164 def SLOPP3 : Int := 3955335645359842146091088249708864238312943862544998285589320092854593149420376176 @@ -674,7 +670,4 @@ theorem qS5_facts {u : Nat} (hu : u ≤ Uc) : generalize hD : int256 (evmSar 95 (evmMul (qS4 u) u)) = D at hs1 hs2 ⊢ omega -def pWordD (u : Nat) : Nat := pS4 u -def qWordD (u : Nat) : Nat := qS5 u - end LnYul diff --git a/formal/ln/LnProof/LnProof/Mono.lean b/formal/ln/LnProof/LnProof/Mono.lean deleted file mode 100644 index 21c6f70a7..000000000 --- a/formal/ln/LnProof/LnProof/Mono.lean +++ /dev/null @@ -1,9 +0,0 @@ -/-! -# Mono facade - -Monotonicity of the model over its whole domain. `Top` is the entry point -(`lnWadToRayBody_mono` / `lnWadBody_mono`); it composes the within-octave step -(`Step`, `ZOctave`, `Octave`, `Certs`) with the cross-`clz`-seam and -corrected-point cases (`Seams`). --/ -import LnProof.Mono.Top diff --git a/formal/ln/LnProof/LnProof/Mono/Octave.lean b/formal/ln/LnProof/LnProof/Mono/Octave.lean index a140d98ed..055e07d0d 100644 --- a/formal/ln/LnProof/LnProof/Mono/Octave.lean +++ b/formal/ln/LnProof/LnProof/Mono/Octave.lean @@ -45,7 +45,7 @@ theorem lnWadToRayBody_eq_tail {x : Nat} (_h : x < 2 ^ 256) : rw [evmMul_comm 7450580596923828125, evmAdd_comm (evmMul 3273295013171879848905889459134067659407864468560 (evmSub 160 (evmClz x))), - evmAdd_comm 116873961749927929127912020551516294209054209107914] + evmAdd_comm 116873961749927929127912020551560854268589826112230] /-- Per-`clz` bracket on the signed value of `ln2 * k`; `[-LN2c*95, LN2c*160]`. -/ def ln2kOK (c : Nat) : Bool := @@ -140,7 +140,7 @@ theorem affine_tail_mono {a a' W : Nat} (by rw [e2']; clear e2 e2' e3 hKc hKlt; simp only [ipow255]; omega) (by rw [e2']; clear e2 e2' e3 hKc hKlt; simp only [ipow255]; omega) have hBIlt : BIASc < 2 ^ 256 := by simp only [BIASc]; omega - have hBI : int256 BIASc = (116873961749927929127912020551516294209054209107914 : Int) := by + have hBI : int256 BIASc = (116873961749927929127912020551560854268589826112230 : Int) := by rw [toInt_of_lt (by simp only [BIASc]; omega)] simp only [BIASc] omega diff --git a/formal/ln/LnProof/LnProof/Seam.lean b/formal/ln/LnProof/LnProof/Seam.lean deleted file mode 100644 index ab3868bc6..000000000 --- a/formal/ln/LnProof/LnProof/Seam.lean +++ /dev/null @@ -1,10 +0,0 @@ -/-! -# Seam facade - -The two semantic bridges. `RuntimeModel` proves the compiled runtime -(`run_ln_wad_*_evm`) equals the hand model (`Model.Body`); `RealLog` bridges -the real-free cut predicates to `Real.log`. Together they connect the -implementation to the `Real.log` specification. --/ -import LnProof.Seam.RuntimeModel -import LnProof.Seam.RealLog diff --git a/formal/ln/LnProof/LnProof/Seam/RealLog.lean b/formal/ln/LnProof/LnProof/Seam/RealLog.lean index 36849bb1a..615cd3e43 100644 --- a/formal/ln/LnProof/LnProof/Seam/RealLog.lean +++ b/formal/ln/LnProof/LnProof/Seam/RealLog.lean @@ -51,6 +51,32 @@ lemma reciprocal_wadRatio {x : Nat} (hx : 0 < x) : have hxR : (x : Real) ≠ 0 := by exact_mod_cast ne_of_gt hx field_simp [hxR] +lemma cutLeLogWadRay_of_lt {r : Int} {x : Nat} (hx : 0 < x) + (h : (r : Real) / ((10 ^ 27 : Nat) : Real) < + Real.log ((x : Real) / ((10 ^ 18 : Nat) : Real))) : + CutLeLogWadRay r x := by + have hratio : 0 < (x : Real) / ((10 ^ 18 : Nat) : Real) := wadRatio_pos hx + by_cases hr : 0 ≤ r + · rw [CutLeLogWadRay, if_pos hr] + unfold CutExpLe + apply capUB_of_exp_le QS_pos (by decide) + rw [ray_exp_arg_of_nonneg hr] + calc + Real.exp ((r : Real) / ((10 ^ 27 : Nat) : Real)) + ≤ Real.exp (Real.log ((x : Real) / ((10 ^ 18 : Nat) : Real))) := + Real.exp_le_exp.mpr h.le + _ = (x : Real) / ((10 ^ 18 : Nat) : Real) := Real.exp_log hratio + · have hrlt : r < 0 := by omega + rw [CutLeLogWadRay, if_neg hr] + unfold CutRatioLeExp + apply capLB_of_lt_exp QS_pos hx + rw [ray_exp_arg_of_neg hrlt] + have hneg : -Real.log ((x : Real) / ((10 ^ 18 : Nat) : Real)) < + -((r : Real) / ((10 ^ 27 : Nat) : Real)) := by linarith + have hexp := Real.exp_lt_exp.mpr hneg + rw [Real.exp_neg, Real.exp_log hratio, ← reciprocal_wadRatio hx] at hexp + exact hexp + lemma le_rayLog_of_cutLeLogWadRay {r : Int} {x : Nat} (hx : 0 < x) (hcut : CutLeLogWadRay r x) : (r : Real) ≤ ((10 ^ 27 : Nat) : Real) * Real.log ((x : Real) / ((10 ^ 18 : Nat) : Real)) := by diff --git a/formal/ln/LnProof/LnProof/Spec.lean b/formal/ln/LnProof/LnProof/Spec.lean deleted file mode 100644 index 57c41c772..000000000 --- a/formal/ln/LnProof/LnProof/Spec.lean +++ /dev/null @@ -1,10 +0,0 @@ -/-! -# Spec facade - -What "correct" means. `Real` is the public target — a fixed-point bracket -around `Real.log`. `Cut` is the real-free arithmetized restatement (exponential -Taylor cuts) the EVM-side proof actually discharges; the two are shown -equivalent by `Floor.CutEquiv` and `Seam.RealLog`. --/ -import LnProof.Spec.Real -import LnProof.Spec.Cut diff --git a/formal/ln/README.md b/formal/ln/README.md index b4d1fe7f2..5f6a9e32f 100644 --- a/formal/ln/README.md +++ b/formal/ln/README.md @@ -30,8 +30,8 @@ Machine-checked Lean 4 proof that the compiled `lnWad` / `lnWadToRay` (from ## Layout (`LnProof/LnProof/`) -The directories are the proof's abstraction layers, lowest first; each has a -facade module (`Foundation.lean`, `Spec.lean`, …) re-exporting its public face. +The directories are the proof's abstraction layers, lowest first. The root +`LnProof.lean` is the checked aggregate of their public entry modules. | Directory | Role | |----------------|------| @@ -42,11 +42,13 @@ facade module (`Foundation.lean`, `Spec.lean`, …) re-exporting its public face | `Floor/` | The model ⊨ floor/cut spec proof and its bracket/cap/cert machinery. | | `Error/` | The model-level `1.6986`-ulp error bound and its cell covers / caps. | | `Seam/` | The semantic bridges: `RuntimeModel` (runtime ↔ model) and `RealLog` (cut ↔ `Real.log`). | -| `Cert/` | **Generated** certificate literals and cell covers — machine output, do not edit. | +| `Cert/` | **Generated** certificate literals, cells, and aggregate covers — machine output, do not edit. | | (top level) | `Theorems`, `Correct`, `ErrorBoundRuntime`, and the two generated EVM artifacts `LnYulRuntime` / `LnYulProof`. | ## Build +After the generated sources described below are present: + ```bash cd formal/ln/LnProof && lake build ``` @@ -69,28 +71,38 @@ The **generated certificates** under `Cert/` (ignored) come from the in-tree generators, run from `formal/ln/LnProof`: ```bash +find LnProof/Cert -type f ! -name .gitkeep -delete +find LnProof/Cert -depth -type d -empty ! -path LnProof/Cert -delete +for path in .lake/build/lib/lean/LnProof/Cert .lake/build/ir/LnProof/Cert; do + if [[ -e "$path" ]]; then + rm -r -- "$path" + fi +done lake build LnProof.Floor.CertDefs Common.Foundation.KroneckerShift LnProof.Floor.Consts Common.GenCover lake env lean GenFloorCertLit.lean lake build \ - LnProof.Cert.FloorCertGeUpLit \ LnProof.Cert.FloorCertGeLoLit \ - LnProof.Cert.FloorCertLtUpLit \ LnProof.Cert.FloorCertLtLoLit lake env lean GenCover.lean lake env lean GenErr1.lean lake build \ - LnProof.Error.Core.ExpMargin \ - LnProof.Error.Core.Budget \ - LnProof.Error.Core.BranchCertHardDefs + LnProof.Floor.CarryIndependent.Approximation \ + Common.GenBernstein \ + Common.Foundation.PackedShift +lake env lean GenApproximationCert.lean +lake build LnProof.Error.Core.Budget lake env lean GenErrLit.lean -lake env lean GenBranchCertHard.lean -lake build LnProof.Cert.HardMantissaLtGap lake build ``` -The hard-mantissa certificate consists of ten generated 16-case-or-smaller -kernel checks in two contiguous dependency lanes. The generated aggregate -imports the two lane tips and reconstructs the 159-case theorem from those -checked chunks. +`GenCover.lean` emits each floor certificate's cells and its complete generated +aggregate; the checked-in floor modules supply the polynomial-evaluation bridge. +`GenErrLit.lean` emits the complete specialized error-bound cover. +`GenApproximationCert.lean` emits two approximation-envelope covers containing +310 cells: 291 use a packed Kronecker shift followed by interval Horner, and 19 +use Bernstein witnesses. Four contiguous dependency lanes connect the cells to +an aggregate that imports only their tips. A separate Bernstein certificate +bounds the ratio gap induced by the variable-propagated numerator and +denominator errors by its endpoint value. See `.github/workflows/formal.yml` for the canonical CI sequence. diff --git a/src/vendor/Ln.sol b/src/vendor/Ln.sol index 581f55a0a..146913668 100644 --- a/src/vendor/Ln.sol +++ b/src/vendor/Ln.sol @@ -32,7 +32,7 @@ library Ln { // rational polynomial approximation of f(u) = atanh(√u)/√u on u ∈ [0, (3-2√2)²], fit under // the weight √u (the weight the error carries into ln), with q monic and p(0) = -q(0) // constrained so both polynomials share their constant-term literal. The weighted sup-norm - // error of the integer-rounded rational 2⋅√u⋅|p/-q - f|⋅10²⁷ is ≤0.327ulp. + // error of the integer-rounded rational 2⋅√u⋅|p/-q - f|⋅10²⁷ is <0.323662ulp. // // Mixed fixed-point bases, chosen so every renormalizing shift lands a value directly // at the basis its consumer needs: @@ -53,11 +53,12 @@ library Ln { // and the bias, so the closing `sar(72, …)` is the single output-rounding floor // // Error budget in ulps (1 ulp = 10⁻²⁷ of ln; 2⁷² pre-shift units): rational polynomial - // approximation and coefficient quantization ≤0.327 combined; mantissa (Q95) truncation - // ≤2⁻⁹⁵⋅10²⁷ ≈ 0.026 (downward only); z, u, and `SDIV` truncations ≤0.005 combined; Horner - // stage truncations ≤10⁻⁴; ln(2) and bias constant rounding ≤10⁻¹⁹. The bias is reduced by - // a margin of ~1.598⋅10²¹ units (0.3383 ulp), so the Q72 accumulator never exceeds L⋅2⁷²; - // margin plus downward errors total < 0.699 ⋅ 2⁷², so it always exceeds (L-1)⋅2⁷². + // approximation and coefficient quantization <0.323662; normalized-mantissa/z and u + // truncations <0.001626 and <0.001497; Horner stage truncations <0.000503; the closing + // `SDIV` contributes <0.001578; and the ln(2) phase contributes <4⋅10⁻²¹. Their certified + // one-sided total is <0.3288640403604298097806. The bias is reduced by ~1.553⋅10²¹ units + // (0.3288640403604298097807 ulp), so the Q72 accumulator never exceeds L⋅2⁷²; margin plus + // downward errors total <0.699⋅2⁷², so it always exceeds (L-1)⋅2⁷². // `sar(72, …)` therefore yields ⌊L⌋ or ⌊L⌋ - 1. // // Monotonicity: within an octave, the integer z = sdiv((s-m)⋅2¹⁰⁰, m+s) is strictly @@ -117,7 +118,7 @@ library Ln { // Add ⌊(ln(s/2⁹⁵) + 95⋅ln(2) - 18⋅ln(10)) ⋅ 10²⁷ ⋅ 2⁷²⌋ minus the one-sided error // margin described above. - r := add(0x4ff7e9b32826a6aec97ea1e69740845a0dd9c667ca, r) + r := add(0x4ff7e9b32826a6aec97ea1e699aae97c1cc87bfae6, r) // Q72 → integer ray result (`SAR` floors). r := sar(0x48, r) From e856969c4313055c9f69679ba4c55f14e56a7fb4 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Jul 2026 13:18:28 +0200 Subject: [PATCH 102/107] DRY --- src/vendor/Exp.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 2d5c3d922..98a57e717 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -62,8 +62,9 @@ library Exp { function mulExpRay(int128 y, int256 x) internal pure returns (int128) { unchecked { // Split `y` into a sign mask and a magnitude - int256 sign = int256(y) >> 255; - uint256 ay = uint256((int256(y) ^ sign) - sign); + int256 y_ = int256(y); + int256 sign = y_ >> 255; + uint256 ay = uint256((y_ ^ sign) - sign); // The top-bit term admits ay = abs(type(int128).min) at s = 0 while leaving every // smaller magnitude's normalization unchanged. From 3099e3420329afa1c4e6d629c24d948a500360c8 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Jul 2026 15:28:39 +0200 Subject: [PATCH 103/107] Comment --- src/vendor/Exp.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 98a57e717..8df9baebf 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -44,10 +44,10 @@ library Exp { /// @notice Compute `trunc(y * exp(x / 10**27))` with up to 1ulp of error, towards zero /// @dev Let A = |y| ⋅ exp(x / 10²⁷). For accepted inputs, this function returns sign(y) ⋅ m - /// with 0 ≤ m ≤ A ∧ A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, without - /// underflow. `mulExpRay(0, x) == 0` for every accepted x, and `mulExpRay(y, 0) == y` - /// exactly whenever 4⋅|y| ≤ 2¹²⁷ - 1 = 170141183460469231731687303715884105727. Among - /// accepted inputs, the result is monotone in `x`: nondecreasing if y ≥ 0 and + /// with 0 ≤ m ≤ A ∧ A < m + 2: the magnitude m is ⌊A⌋ or ⌊A⌋ - 1, without underflow; it + /// never overestimates. `mulExpRay(0, x) == 0` for every accepted x, and `mulExpRay(y, 0) + /// == y` exactly whenever 4⋅|y| ≤ 2¹²⁷ - 1 = 170141183460469231731687303715884105727 + /// . Among accepted inputs, the result is monotone in `x`: nondecreasing if y ≥ 0 and /// nonincreasing if y < 0. For a fixed `x`, among accepted inputs, the result is /// nondecreasing in `y`. Jointly, for accepted (y₁, x₁, r₁ = mulExpRay(y₁, x₁)) and (y₂, /// x₂, r₂ = mulExpRay(y₂, x₂)), r₁ ≤ r₂ when 0 ≤ y₁ ≤ y₂ ∧ x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 ∧ x₂ From 987951adb49680fa6ac3bf1ad5ef0a09d5ad1799 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Wed, 15 Jul 2026 19:02:54 +0200 Subject: [PATCH 104/107] Clean up CI runtime warnings Run cache actions on Node 24, pin workflow dependencies, suppress checkout initialization hints, and remove actionable Lean lints. Co-Authored-By: OpenAI Codex --- .../actions/cache-formal-package/action.yml | 4 ++-- .github/actions/setup-formal/action.yml | 10 ++++---- .github/workflows/formal.yml | 23 +++++++++++-------- .github/workflows/integration.yml | 11 ++++++--- .github/workflows/safeguard-zksync.yml | 7 +++++- .github/workflows/size.yml | 11 ++++++--- .github/workflows/test.yml | 9 ++++++-- .../Cbrt512Proof/Cbrt512Correct.lean | 1 + .../CarryIndependent/AnalyticRuntime.lean | 2 +- .../CarryIndependent/ApproximationReal.lean | 6 ++--- .../Floor/CarryIndependent/Normalization.lean | 5 ++-- .../LnProof/Floor/CarryIndependent/Phase.lean | 3 +-- .../Sqrt512Proof/Sqrt512YulCorrect.lean | 10 ++++---- 13 files changed, 62 insertions(+), 40 deletions(-) diff --git a/.github/actions/cache-formal-package/action.yml b/.github/actions/cache-formal-package/action.yml index 0e3cb6e96..8af225765 100644 --- a/.github/actions/cache-formal-package/action.yml +++ b/.github/actions/cache-formal-package/action.yml @@ -34,7 +34,7 @@ runs: - name: Restore and publish ${{ inputs.cache-name }} cache id: cache if: inputs.publish == 'true' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: ${{ inputs.cache-path }} key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/workflows/formal.yml', '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} @@ -45,7 +45,7 @@ runs: - name: Restore ${{ inputs.cache-name }} cache without publishing id: restore if: inputs.publish != 'true' - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: ${{ inputs.cache-path }} key: ${{ runner.os }}-formal-${{ inputs.cache-name }}-${{ hashFiles(inputs.dependency-hash-globs, 'lib/EVMYulLean/EvmYul/FFI/ffi.c') }}-${{ hashFiles(inputs.source-hash-globs, '.github/workflows/formal.yml', '.github/actions/setup-formal/**', '.github/actions/cache-formal-package/**', '.github/actions/fetch-lean-cache/**') }} diff --git a/.github/actions/setup-formal/action.yml b/.github/actions/setup-formal/action.yml index 51bb37e7c..58a2ccf62 100644 --- a/.github/actions/setup-formal/action.yml +++ b/.github/actions/setup-formal/action.yml @@ -28,7 +28,7 @@ runs: using: composite steps: - name: Install Foundry - uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1 + uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1.9.0 with: version: v1.5.1 @@ -56,7 +56,7 @@ runs: - name: Restore and publish formal dependency cache id: dependency-cache if: inputs.publish == 'true' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: formal/yul/.lake/packages key: ${{ runner.os }}-formal-packages-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} @@ -66,7 +66,7 @@ runs: - name: Restore formal dependency cache without publishing id: dependency-restore if: inputs.publish != 'true' - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: formal/yul/.lake/packages key: ${{ runner.os }}-formal-packages-${{ hashFiles('formal/yul/lean-toolchain', 'formal/yul/lakefile.toml', 'formal/yul/lake-manifest.json', 'lib/EVMYulLean/lean-toolchain', 'lib/EVMYulLean/lakefile.lean', 'lib/EVMYulLean/lake-manifest.json') }} @@ -81,7 +81,7 @@ runs: - name: Restore and publish formal tool cache id: tool-cache if: inputs.publish == 'true' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: | formal/yul/.lake/build @@ -94,7 +94,7 @@ runs: - name: Restore formal tool cache without publishing id: tool-restore if: inputs.publish != 'true' - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: | formal/yul/.lake/build diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml index b86660c47..2b5f3a75a 100644 --- a/.github/workflows/formal.yml +++ b/.github/workflows/formal.yml @@ -9,6 +9,11 @@ on: permissions: contents: read +env: + GIT_CONFIG_COUNT: "1" + GIT_CONFIG_KEY_0: init.defaultBranch + GIT_CONFIG_VALUE_0: main + jobs: route: name: Select formal checks @@ -23,7 +28,7 @@ jobs: ln: ${{ steps.route.outputs.ln }} exp: ${{ steps.route.outputs.exp }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 persist-credentials: false @@ -43,7 +48,7 @@ jobs: if: needs.route.outputs.any == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -71,7 +76,7 @@ jobs: if: needs.route.outputs.common == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -123,7 +128,7 @@ jobs: if: needs.route.outputs.cbrt == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -187,7 +192,7 @@ jobs: if: needs.route.outputs.sqrt == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -252,7 +257,7 @@ jobs: if: needs.route.outputs.cbrt512 == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -375,7 +380,7 @@ jobs: if: needs.route.outputs.sqrt512 == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -498,7 +503,7 @@ jobs: if: needs.route.outputs.ln == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false @@ -595,7 +600,7 @@ jobs: if: needs.route.outputs.exp == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: submodules: recursive persist-credentials: false diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f8f989c4f..c21295926 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -8,21 +8,26 @@ on: - fork/shanghai pull_request: +env: + GIT_CONFIG_COUNT: "1" + GIT_CONFIG_KEY_0: init.defaultBranch + GIT_CONFIG_VALUE_0: main + jobs: integration: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Node.js 18.x - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 18.x - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1.9.0 with: version: v1.5.1 diff --git a/.github/workflows/safeguard-zksync.yml b/.github/workflows/safeguard-zksync.yml index 698f0da35..e3c397487 100644 --- a/.github/workflows/safeguard-zksync.yml +++ b/.github/workflows/safeguard-zksync.yml @@ -9,11 +9,16 @@ on: permissions: contents: read +env: + GIT_CONFIG_COUNT: "1" + GIT_CONFIG_KEY_0: init.defaultBranch + GIT_CONFIG_VALUE_0: main + jobs: safeguard-zksync: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: Install Foundry-ZKsync run: | diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml index 1ad36bd09..fce766354 100644 --- a/.github/workflows/size.yml +++ b/.github/workflows/size.yml @@ -8,21 +8,26 @@ on: - fork/shanghai pull_request: +env: + GIT_CONFIG_COUNT: "1" + GIT_CONFIG_KEY_0: init.defaultBranch + GIT_CONFIG_VALUE_0: main + jobs: size-limit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Node.js 18.x - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 18.x - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1.9.0 with: version: v1.5.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4de124756..a5a309df2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,16 +8,21 @@ on: - fork/shanghai pull_request: +env: + GIT_CONFIG_COUNT: "1" + GIT_CONFIG_KEY_0: init.defaultBranch + GIT_CONFIG_VALUE_0: main + jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + uses: foundry-rs/foundry-toolchain@b00af27efadbc7b4ca8b82abbd903b17cc874d2a # v1.9.0 with: version: v1.5.1 diff --git a/formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Correct.lean b/formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Correct.lean index 266d5616a..f0d90eec2 100644 --- a/formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Correct.lean +++ b/formal/cbrt/Cbrt512Proof/Cbrt512Proof/Cbrt512Correct.lean @@ -3229,6 +3229,7 @@ theorem cbrt512_floorCorrection_correct (xHi xLo r : Nat) rw [hrEq] omega +set_option exponentiation.threshold 1024 in /-- The cube root of a value below `WORD_MOD^2` (= 2^512) is tiny, so `icbrt x + 2` still fits in a word — needed to rule out overflow in the ceiling increment. -/ private theorem icbrt_add_two_lt_word (x : Nat) (hx : x < WORD_MOD * WORD_MOD) : diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean index ea2998788..f0b4d6dd0 100644 --- a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/AnalyticRuntime.lean @@ -76,7 +76,7 @@ theorem crossLog_hasDerivAt {t : Real} (htm : -1 < t) (htp : t < 1) : ((hasDerivAt_const t 1).sub (hasDerivAt_id t)) have hsq : 1 - t ^ 2 ≠ 0 := by nlinarith [sq_nonneg t] unfold crossLog - convert hp.sub hm using 1 <;> field_simp [hp0, hm0, hsq] <;> ring_nf + convert hp.sub hm using 1; field_simp [hp0, hm0, hsq]; ring_nf theorem crossLog_increment_le {a t T : Real} (ha0 : 0 ≤ a) (hat : a ≤ t) (htT : t ≤ T) diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean index cc6ece621..d2f304d1b 100644 --- a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/ApproximationReal.lean @@ -141,9 +141,9 @@ theorem approximationUpper_eval (u : Nat) (hu : u < approximationScale) : evalPoly_oneMinus, approximationTailPower, evalPoly_tailPower] push_cast rw [← hTaylor] - field_simp [hTaylorDen, hScale, hGap] <;> + field_simp [hTaylorDen, hScale, hGap]; norm_num [approximationTaylorDen, approximationOddProduct, - approximationScale, approximationTerms] <;> ring + approximationScale, approximationTerms]; ring theorem approximationUpperDen_pos {u : Nat} (hu : u ≤ approximationMaxU) : 0 < evalPoly approximationUpperDen (u : Int) := by @@ -183,7 +183,7 @@ theorem approximationRational_eval (u : Nat) (hu : u ≤ approximationMaxU) : evalPoly_polyScale, evalPoly_polyNeg] push_cast at hq hqScaled ⊢ apply (div_eq_div_iff hq.ne' hqScaled).2 - field_simp [h358, h386] <;> norm_num <;> ring + field_simp [h358, h386]; norm_num; ring theorem approximationLowCell_implies_series_eval_bound {hi u z a : Nat} (ha : approximationEnvelopeCandidate hi a) diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean index 8c353ab89..d96cff690 100644 --- a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Normalization.lean @@ -107,8 +107,7 @@ private theorem low_z_num_toNat {m : Nat} have hsub : (0 : Int) ≤ (Sc : Int) - m := sub_nonneg.mpr (Int.ofNat_le.mpr (Nat.le_of_lt hmsc)) have hsubNat : ((Sc : Int) - m).toNat = Sc - m := by - simpa using Int.toNat_sub_of_le - (Int.ofNat_le.mpr (Nat.le_of_lt hmsc)) + simp have hscale : (0 : Int) ≤ 1267650600228229401496703205376 := by norm_num have hscaleNat : (1267650600228229401496703205376 : Int).toNat = wordQ100 := by @@ -305,7 +304,7 @@ private theorem high_z_num_toNat {m : Nat} have hsub : (0 : Int) ≤ (m : Int) - Sc := sub_nonneg.mpr (Int.ofNat_le.mpr hscm) have hsubNat : ((m : Int) - Sc).toNat = m - Sc := by - simpa using Int.toNat_sub_of_le (Int.ofNat_le.mpr hscm) + simp have hscale : (0 : Int) ≤ 1267650600228229401496703205376 := by norm_num have hscaleNat : (1267650600228229401496703205376 : Int).toNat = wordQ100 := by diff --git a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean index 7dcbf4fdd..1459547ab 100644 --- a/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean +++ b/formal/ln/LnProof/LnProof/Floor/CarryIndependent/Phase.lean @@ -74,8 +74,7 @@ theorem phaseDeltaRay_le : 10 ^ 27 * ((phaseErrorNum : Real) / (10 ^ 27 * phaseErrorDen)) := mul_le_mul_of_nonneg_left hsmall hscale.le _ = (phaseErrorNum : Real) / phaseErrorDen := by - field_simp [hden.ne', hscale.ne'] - <;> ring + field_simp [hden.ne', hscale.ne']; ring theorem phaseErrorRay_le {k : Int} (hlo : -95 ≤ k) (hhi : k ≤ 159) : phaseErrorRay k ≤ (159 : Real) * phaseErrorNum / phaseErrorDen := by diff --git a/formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulCorrect.lean b/formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulCorrect.lean index fb35dd16c..331d6ae82 100644 --- a/formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulCorrect.lean +++ b/formal/sqrt/Sqrt512Proof/Sqrt512Proof/Sqrt512YulCorrect.lean @@ -672,7 +672,7 @@ private theorem call_fun_unsafeDec_direct (hlookup := hlookup)] apply FormalYul.Preservation.eq_of_wordNat_eq simp only [FormalYul.Preservation.wordNat_sub] - simp [FormalYul.Preservation.evmSub_u256_left, FormalYul.Preservation.evmSub_u256_right] + simp [FormalYul.Preservation.evmSub_u256_left] private theorem call_fun_unsafeDec_uint256_direct (x b : EvmYul.UInt256) (fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -734,8 +734,7 @@ private theorem call_fun_unsafeDec_ofNat_uint256_direct apply FormalYul.Preservation.eq_of_wordNat_eq simp only [FormalYul.Preservation.wordNat_sub, FormalYul.Preservation.wordNat_ofNat, FormalYul.Preservation.wordNat_lt] - simp [FormalYul.word, FormalYul.Preservation.evmSub_u256_left, - FormalYul.Preservation.evmLt_u256_left] + simp [FormalYul.word, FormalYul.Preservation.evmSub_u256_left] private theorem call_wrapping_add_t_uint256_direct (x y fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) @@ -817,7 +816,6 @@ private theorem call_fun_and_direct apply FormalYul.Preservation.eq_of_wordNat_eq simp only [FormalYul.Preservation.wordNat_mul] simp [FormalYul.Preservation.wordNat_lt, FormalYul.Preservation.evmMul_u256_left, - FormalYul.Preservation.evmMul_u256_right, FormalYul.Preservation.evmLt_u256_left, FormalYul.Preservation.evmLt_u256_right] private theorem call_fun_and_uint256_direct @@ -954,7 +952,7 @@ private theorem call_fun_toUint_direct FormalYul.Preservation.functionDefinition_body_def, EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.evalPrimCall.eq_def, + EvmYul.Yul.execPrimCall.eq_def, EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.multifill', EvmYul.Yul.evalTail.eq_def, EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, @@ -969,7 +967,7 @@ private theorem call_fun_toUint_direct (hlookup := hlookup)] apply FormalYul.Preservation.eq_of_wordNat_eq simp [FormalYul.Preservation.wordNat_lt, FormalYul.Preservation.wordNat_ofNat, - FormalYul.Preservation.evmLt_u256_left, FormalYul.Preservation.evmLt_u256_right] + FormalYul.Preservation.evmLt_u256_right] private theorem call_fun__gt_direct (xHi xLo yHi yLo fuel : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) From 54341cd79e76f72da2fb6de3532152332cd69b8e Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 17 Jul 2026 13:01:58 +0200 Subject: [PATCH 105/107] Reword mulExpRay revert docs around a single acceptance rule State the revert condition as one inequality in bitlen(|y|) and the octave index, with A-space never/always-revert thresholds as consequences. Round all doc approximations to 4 significant figures. Co-Authored-By: Claude Fable 5 --- src/vendor/Exp.sol | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 8df9baebf..3d2a814c2 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -16,7 +16,7 @@ library Exp { /// expRayToWad(x₁) ≤ expRayToWad(x₂). For "central" inputs 707106781186547525 ≤ w ≤ /// 1414213562373095048, `expRayToWad(lnWadToRay(w)) == w - 1`, except at w = 10¹⁸ where it /// returns w. Reverts with `Panic(17)` when x is large enough to leave the supported range - /// (x ≥ 0x92b2f16cc66c5a4ae96e80d4 ≈ 45.40 ⋅ 10²⁷, i.e. E ≳ 5.22 ⋅ 10³⁷). + /// (x ≥ 0x92b2f16cc66c5a4ae96e80d4 ≈ 45.40 ⋅ 10²⁷, i.e. E ≳ 5.218 ⋅ 10³⁷). function expRayToWad(int256 x) internal pure returns (int128) { // This is ⌈(66⋅2¹⁹² - 2¹⁹¹) / CINV⌉, with CINV the Q192 reciprocal in `_octave`; here the // octave count reaches 66 and the deficit envelope exceeds 1ulp. @@ -52,13 +52,11 @@ library Exp { /// nondecreasing in `y`. Jointly, for accepted (y₁, x₁, r₁ = mulExpRay(y₁, x₁)) and (y₂, /// x₂, r₂ = mulExpRay(y₂, x₂)), r₁ ≤ r₂ when 0 ≤ y₁ ≤ y₂ ∧ x₁ ≤ x₂, when y₁ ≤ y₂ ≤ 0 ∧ x₂ /// ≤ x₁, and when y₁ ≤ 0 ≤ y₂ (for any x₁, x₂). - /// @dev Reverts with `Panic(17)` when x ≥ 86989971160273136331862631244 ≈ 87.00⋅10²⁷ - /// (regardless of y), or when round(x / (10²⁷⋅ln(2))) exceeds s - 2, with 2ˢ the scale - /// headroom above |y|; s = 0 at both maximal signed magnitudes and s = 127 at y = 0. The - /// accepted exponents form one interval that narrows as |y| grows, and every accepted x ≤ - /// -88376265521393026950697095485 ≈ -88.38⋅10²⁷ evaluates to zero. Below the wrap boundary - /// (x ≲ -5.7⋅10⁴⁵) the wrapped octave word decides: such `x` revert or clamp to zero, (A < - /// 1 there at every supported magnitude). + /// @dev Reverts with `Panic(17)` iff bitlen(|y|) + round(x / (10²⁷⋅ln(2))) > 125 (below + /// x = -2¹⁵² ≈ -5.709⋅10⁴⁵ it may revert regardless). At y = 0 the rule reads x > + /// 86989971160273136331862631243 ≈ 86.99⋅10²⁷. Hence it never reverts when A < 2¹²⁴⋅√2 ≈ + /// 3.008⋅10³⁷ ∧ y ≠ 0, nor when 2√2⋅A < |y|, and always reverts when A > 2¹²⁵⋅√2 ≈ + /// 6.015⋅10³⁷. Every accepted x ≤ -88376265521393026950697095485 ≈ -88.38⋅10²⁷ returns 0. function mulExpRay(int128 y, int256 x) internal pure returns (int128) { unchecked { // Split `y` into a sign mask and a magnitude @@ -197,7 +195,7 @@ library Exp { // Hence the maximum underestimation is E - A⋅2ᵏ⁻ˢ ≤ (2993/1000 + margin)⋅2ᵏ⁻ˢ. The caller // keeps k ≤ s - 2, where this is < 1, so the floor returns ⌊E⌋ or ⌊E⌋ - 1. For the wad // specialization s = 67, the deficit envelope exceeds 1ulp at k ≥ 66. On the central octave - // k = 0, the margin is 2⁻⁶⁷ ≈ 6.8⋅10⁻²¹ ulp, far below the ≈10⁻⁹ ulp gap `lnWadToRay` + // k = 0, the margin is 2⁻⁶⁷ ≈ 6.776⋅10⁻²¹ ulp, far below the ≈10⁻⁹ ulp gap `lnWadToRay` // leaves, so the round trip floors to ⌊E⌋. The k = 0 band is exactly [-H, H] with H = // ⌊10²⁷⋅ln(2)/2⌋, matching `lnWadToRay`'s image over [1/√2, √2). // From 4d6060d0d1e5365341c3ce63c4681002194e8dd1 Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Thu, 23 Jul 2026 23:47:38 +0200 Subject: [PATCH 106/107] Size golf --- src/vendor/Exp.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vendor/Exp.sol b/src/vendor/Exp.sol index 3d2a814c2..963a51273 100644 --- a/src/vendor/Exp.sol +++ b/src/vendor/Exp.sol @@ -65,8 +65,9 @@ library Exp { uint256 ay = uint256((y_ ^ sign) - sign); // The top-bit term admits ay = abs(type(int128).min) at s = 0 while leaving every - // smaller magnitude's normalization unchanged. - uint256 s = Clz.clz(ay) - 129 + (ay >> 127); + // smaller magnitude's normalization unchanged. The top bit is boolean, so `129 ^ + // topBit` is `129 - topBit`. + uint256 s = Clz.clz(ay) - (129 ^ ay >> 127); int256 k = _octave(x); int256 shift = int256(s) - k; From ea7f9721d3bc2cd7be849ec0ba46b0de3a403e1a Mon Sep 17 00:00:00 2001 From: Duncan Townsend Date: Fri, 24 Jul 2026 00:43:53 +0200 Subject: [PATCH 107/107] Track the xor-based headroom bias in the exp proof mulExpRay computes the scale headroom as clz(ay) - (129 ^ (ay >> 127)). scaleShiftTree and its normal-form lemmas mirror the new word tree, the mulExpRay symbolic-execution reductions follow the emitted Yul's call sites and fuel positions, and the wrapping_add_t_uint256 reduction is removed along with the emitted function. Co-Authored-By: Claude Fable 5 --- .../exp/ExpProof/ExpProof/Mono/MulTree.lean | 8 ++--- formal/exp/ExpProof/ExpProof/Mul/Shell.lean | 22 +++++-------- .../exp/ExpProof/ExpProof/Mul/Transport.lean | 28 ++++++++-------- .../exp/ExpProof/ExpProof/Seam/Helpers.lean | 33 ------------------- .../exp/ExpProof/ExpProof/Seam/MulRevert.lean | 25 ++++++-------- .../exp/ExpProof/ExpProof/Seam/MulValue.lean | 25 ++++++-------- 6 files changed, 46 insertions(+), 95 deletions(-) diff --git a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean index 6635ab987..0903c1758 100644 --- a/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean +++ b/formal/exp/ExpProof/ExpProof/Mono/MulTree.lean @@ -26,10 +26,10 @@ def signTree (y : Nat) : Nat := def absTree (y : Nat) : Nat := evmSub (evmXor y (signTree y)) (signTree y) -/-- The scale headroom computed from the magnitude's bit length, with the `int128.min` -magnitude's wrapping subtraction saturated back to zero. -/ +/-- The scale headroom computed from the magnitude's bit length. The top bit of the magnitude +is boolean, so xor lowers the bias to `128` exactly for the `int128.min` magnitude. -/ def scaleShiftTree (ay : Nat) : Nat := - evmAdd (evmSub (evmClz ay) scaleClzBias) (evmShr 127 ay) + evmSub (evmClz ay) (evmXor scaleClzBias (evmShr 127 ay)) /-- Dynamic pre-shift scale `abs(y) << S`. -/ def mulScaleTree (y : Nat) : Nat := @@ -72,7 +72,7 @@ theorem absTree_lt (y : Nat) : absTree y < 2 ^ 256 := by theorem scaleShiftTree_lt (ay : Nat) : scaleShiftTree ay < 2 ^ 256 := by unfold scaleShiftTree - exact evmAdd_lt _ _ + exact evmSub_lt _ _ theorem mulScaleTree_lt (y : Nat) : mulScaleTree y < 2 ^ 256 := by unfold mulScaleTree diff --git a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean index 0ddeb584a..f7f1bd1b3 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Shell.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Shell.lean @@ -228,8 +228,10 @@ theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) have hsst : scaleShiftTree (absTree y) = 127 := by rw [h0] unfold scaleShiftTree - rw [hclz, hs] - norm_num [evmShr, evmAdd, u256, WORD_MOD] + have hshr : evmShr 127 0 = 0 := by + norm_num [evmShr, u256, WORD_MOD] + have hxor : evmXor scaleClzBias 0 = scaleClzBias := by decide + rw [hclz, hshr, hxor, hs] have hshl : evmShl 127 (0 : Nat) = 0 := by rw [evmShl_small (by norm_num) (by norm_num) (by norm_num)] ring @@ -249,13 +251,12 @@ theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) have hclz : evmClz (2 ^ 127) = 128 := by unfold evmClz rw [u256_self (by norm_num), if_neg (by norm_num), hlog] - have hsub : evmSub 128 scaleClzBias = 2 ^ 256 - 1 := by - norm_num [evmSub, scaleClzBias, u256, WORD_MOD] have hshr : evmShr 127 (2 ^ 127) = 1 := by norm_num [evmShr, u256, WORD_MOD] + have hxor : evmXor scaleClzBias 1 = 128 := by decide unfold scaleShiftTree - rw [hclz, hsub, hshr] - norm_num [evmAdd, u256, WORD_MOD] + rw [hclz, hshr, hxor] + norm_num [evmSub, u256, WORD_MOD] have hscale : mulScaleTree y = kernelScaleMax := by unfold mulScaleTree rw [hs, hend] @@ -284,18 +285,13 @@ theorem mulScaleTree_spec {y : Nat} (_hy : y < 2 ^ 256) exact Nat.div_eq_of_lt hay127 have hs : scaleShiftTree (absTree y) = 126 - Nat.log2 (absTree y) := by unfold scaleShiftTree + have hxor : evmXor scaleClzBias 0 = scaleClzBias := by decide have hsub : evmSub (255 - Nat.log2 (absTree y)) scaleClzBias = 126 - Nat.log2 (absTree y) := by rw [evmSub_small (by unfold scaleClzBias; omega) (by omega)] unfold scaleClzBias omega - rw [hclz, hshr, hsub] - unfold evmAdd - have hshiftlt : 126 - Nat.log2 (absTree y) < 2 ^ 256 := by - exact lt_of_le_of_lt (Nat.sub_le _ _) (by norm_num) - rw [show u256 (126 - Nat.log2 (absTree y)) = 126 - Nat.log2 (absTree y) from - u256_self hshiftlt, show u256 0 = 0 from u256_self (by norm_num)] - rw [Nat.add_zero, u256_self hshiftlt] + rw [hclz, hshr, hxor, hsub] have hfit : absTree y * 2 ^ (126 - Nat.log2 (absTree y)) < 2 ^ 127 := by calc absTree y * 2 ^ (126 - Nat.log2 (absTree y)) < 2 ^ (Nat.log2 (absTree y) + 1) * diff --git a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean index fa4b35ebc..49a50b544 100644 --- a/formal/exp/ExpProof/ExpProof/Mul/Transport.lean +++ b/formal/exp/ExpProof/ExpProof/Mul/Transport.lean @@ -62,15 +62,14 @@ theorem scaleShiftTree_pos {ay : Nat} (hy : ay < 2 ^ 256) have hclz : evmClz (2 ^ 127) = 128 := by unfold evmClz rw [u256_self (by norm_num), if_neg (by norm_num), hlog] - have hsub : evmSub 128 scaleClzBias = 2 ^ 256 - 1 := by - norm_num [evmSub, scaleClzBias, u256, WORD_MOD] have hshr : evmShr 127 (2 ^ 127) = 1 := by norm_num [evmShr, u256, WORD_MOD] + have hxor : evmXor scaleClzBias 1 = 128 := by decide unfold scaleShiftTree - rw [hclz, hsub, hshr] - have hadd : evmAdd (2 ^ 256 - 1) 1 = 0 := by - norm_num [evmAdd, u256, WORD_MOD] - rw [hadd] + rw [hclz, hshr, hxor] + have hsub : evmSub 128 128 = 0 := by + norm_num [evmSub, u256, WORD_MOD] + rw [hsub] change 0 = 126 - Nat.log2 (2 ^ 127) rw [hlog] · have hay127 : ay < 2 ^ 127 := by rw [← kernelScaleMax_eq]; omega @@ -88,27 +87,26 @@ theorem scaleShiftTree_pos {ay : Nat} (hy : ay < 2 ^ 256) unfold evmShr rw [u256_self (by norm_num), u256_self hy, if_pos (by norm_num)] exact Nat.div_eq_of_lt hay127 + have hxor : evmXor scaleClzBias 0 = scaleClzBias := by decide have hsub : evmSub (255 - Nat.log2 ay) scaleClzBias = 126 - Nat.log2 ay := by rw [evmSub_small (by unfold scaleClzBias; omega) (by omega)] unfold scaleClzBias omega unfold scaleShiftTree - rw [hclz, hshr, hsub] - unfold evmAdd - have hshiftlt : 126 - Nat.log2 ay < 2 ^ 256 := - lt_of_le_of_lt (Nat.sub_le _ _) (by norm_num) - rw [show u256 (126 - Nat.log2 ay) = 126 - Nat.log2 ay from u256_self hshiftlt, - show u256 0 = 0 from u256_self (by norm_num)] - rw [Nat.add_zero, u256_self hshiftlt] + rw [hclz, hshr, hxor, hsub] theorem scaleShiftTree_zero : scaleShiftTree 0 = 127 := by have hclz : evmClz 0 = 256 := by unfold evmClz rw [u256_self (by norm_num)] simp + have hshr : evmShr 127 0 = 0 := by + norm_num [evmShr, u256, WORD_MOD] + have hxor : evmXor scaleClzBias 0 = scaleClzBias := by decide unfold scaleShiftTree - rw [hclz, evmSub_small (by unfold scaleClzBias; omega) (by norm_num)] - norm_num [scaleClzBias, evmShr, evmAdd, u256, WORD_MOD] + rw [hclz, hshr, hxor, evmSub_small (by unfold scaleClzBias; omega) (by norm_num)] + unfold scaleClzBias + norm_num theorem scaleShiftTree_int128Max : scaleShiftTree int128Max = 0 := by have hmax : int128Max ≠ 0 := by unfold int128Max; norm_num diff --git a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean index 9bc1833a5..97d21e8a4 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/Helpers.lean @@ -1344,39 +1344,6 @@ theorem call_wrapping_sub_t_uint256_direct Finmap.lookup_insert, FormalYul.word, FormalYul.Preservation.uint256_ofNat_sub_eq_word_evmSub, hcleanup] -theorem call_wrapping_add_t_uint256_direct - (x y fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) - (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = - some (FormalYul.accountFor yulContract)) : - EvmYul.Yul.call (fuel + (extra + 80)) [FormalYul.word x, FormalYul.word y] - (.some "wrapping_add_t_uint256") (.some yulContract) - (EvmYul.Yul.State.Ok shared store) = - .ok (EvmYul.Yul.State.Ok shared store, [FormalYul.word (evmAdd x y)]) := by - rw [show fuel + (extra + 80) = (fuel + extra) + 80 by omega] - rw [EvmYul.Yul.call.eq_def] - simp only [hlookup, Option.getD_some, yulContract_functions, lookup_wrapping_add_t_uint256] - simp only [yulFunction_wrapping_add_t_uint256, - FormalYul.Preservation.functionDefinition_params_def, - FormalYul.Preservation.functionDefinition_rets_def, - FormalYul.Preservation.functionDefinition_body_def, - EvmYul.Yul.State.initcall, EvmYul.Yul.State.mkOk] - have hcleanup := - call_cleanup_t_uint256_direct (v := evmAdd x y) (fuel := fuel + extra) (extra := 56) - (shared := shared) - (store := Finmap.insert "x" (FormalYul.word x) - (Finmap.insert "y" (FormalYul.word y) (Inhabited.default : EvmYul.Yul.VarStore))) - (hlookup := hlookup) - simp [FormalYul.word] at hcleanup - simp +decide [EvmYul.Yul.execCall.eq_def, - EvmYul.Yul.evalPrimCall.eq_def, - EvmYul.Yul.reverse', EvmYul.Yul.cons', EvmYul.Yul.head', EvmYul.Yul.multifill', - EvmYul.Yul.evalTail.eq_def, - EvmYul.Yul.State.insert, EvmYul.Yul.State.multifill, - EvmYul.Yul.State.lookup!, EvmYul.Yul.State.setStore, - EvmYul.Yul.State.reviveJump, EvmYul.Yul.State.overwrite?, - Finmap.lookup_insert, FormalYul.word, - FormalYul.Preservation.uint256_ofNat_add_eq_word_evmAdd, hcleanup] - theorem call_fun_clz_direct (x fuel extra : Nat) (shared : EvmYul.SharedState .Yul) (store : EvmYul.Yul.VarStore) (hlookup : shared.accountMap.find? shared.executionEnv.codeOwner = diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean index 2aa375dd3..d8a34f237 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulRevert.lean @@ -71,20 +71,17 @@ theorem call_fun_mulExpRay_revert_direct call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2090) (shared := shared) (hlookup := hlookup) have hscaleClzBias := - call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2046) + call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2039) (shared := shared) (hlookup := hlookup) - have hwrapS := - call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) - (fuel := fuel + extra) (extra := 2088) (shared := shared) (hlookup := hlookup) have hconvert127 := - call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2044) + call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2045) (shared := shared) (hlookup := hlookup) have hshrAy := call_shift_right_t_uint256_t_uint8_127_direct (value := ay) - (fuel := fuel + extra) (extra := 1983) (shared := shared) (hlookup := hlookup) - have hwrapAdd := - call_wrapping_add_t_uint256_direct - (x := evmSub (evmClz ay) scaleClzBias) (y := evmShr 127 ay) + (fuel := fuel + extra) (extra := 1984) (shared := shared) (hlookup := hlookup) + have hwrapS := + call_wrapping_sub_t_uint256_direct (x := evmClz ay) + (y := evmXor scaleClzBias (evmShr 127 ay)) (fuel := fuel + extra) (extra := 2081) (shared := shared) (hlookup := hlookup) have hoctave := call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2037) @@ -125,10 +122,9 @@ theorem call_fun_mulExpRay_revert_direct simp only [Nat.reduceAdd, FormalYul.word] at hconvertY1 hconvert255 hshiftSign hwrapAy hayAsUint hzeroInit simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word] at hscaleClzBias - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree] at hshrAy - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapAdd + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hconvertS @@ -152,9 +148,8 @@ theorem call_fun_mulExpRay_revert_direct (evmSgt x 86989971160273136331862631243) (evmSlt (evmSub - (evmAdd - (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmShr 127 (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)))) + (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) + (evmXor 129 (evmShr 127 (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))))) (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) 2) = 1 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, @@ -169,7 +164,7 @@ theorem call_fun_mulExpRay_revert_direct hconvertY1, hconvert255, hshiftSign, hwrapAy, hayAsUint, hguardUnfold, hzeroInit, hclz, hscaleClzBias, hwrapS, - hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, + hconvert127, hshrAy, hoctave, hconvertS, hwrapShift, hHi, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hoverflow, hconvu, hpanic, diff --git a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean index 0706d5a6d..d849371aa 100644 --- a/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean +++ b/formal/exp/ExpProof/ExpProof/Seam/MulValue.lean @@ -78,20 +78,17 @@ theorem call_fun_mulExpRay_direct call_fun_clz_direct (x := ay) (fuel := fuel + extra) (extra := 2090) (shared := shared) (hlookup := hlookup) have hscaleClzBias := - call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2046) + call_convert_129_to_uint256_direct (fuel := fuel + extra) (extra := 2039) (shared := shared) (hlookup := hlookup) - have hwrapS := - call_wrapping_sub_t_uint256_direct (x := evmClz ay) (y := scaleClzBias) - (fuel := fuel + extra) (extra := 2088) (shared := shared) (hlookup := hlookup) have hconvert127 := - call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2044) + call_convert_127_to_uint8_direct (fuel := fuel + extra) (extra := 2045) (shared := shared) (hlookup := hlookup) have hshrAy := call_shift_right_t_uint256_t_uint8_127_direct (value := ay) - (fuel := fuel + extra) (extra := 1983) (shared := shared) (hlookup := hlookup) - have hwrapAdd := - call_wrapping_add_t_uint256_direct - (x := evmSub (evmClz ay) scaleClzBias) (y := evmShr 127 ay) + (fuel := fuel + extra) (extra := 1984) (shared := shared) (hlookup := hlookup) + have hwrapS := + call_wrapping_sub_t_uint256_direct (x := evmClz ay) + (y := evmXor scaleClzBias (evmShr 127 ay)) (fuel := fuel + extra) (extra := 2081) (shared := shared) (hlookup := hlookup) have hoctave := call_fun__octave_direct (x := x) (fuel := fuel + extra) (extra := 2037) @@ -144,10 +141,9 @@ theorem call_fun_mulExpRay_direct simp only [Nat.reduceAdd, FormalYul.word] at hwrapAy hconvertAy hzeroInit simp only [Nat.reduceAdd, FormalYul.word, yulName_fun_clz, ay, absTree, signTree] at hclz simp only [Nat.reduceAdd, FormalYul.word] at hscaleClzBias - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS simp only [Nat.reduceAdd, FormalYul.word] at hconvert127 simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree] at hshrAy - simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapAdd + simp only [Nat.reduceAdd, FormalYul.word, ay, absTree, signTree, scaleClzBias] at hwrapS simp only [Nat.reduceAdd, FormalYul.word, yulName_fun__octave] at hoctave simp only [Nat.reduceAdd, FormalYul.word, s, ay, absTree, signTree, scaleShiftTree, scaleClzBias] at hconvertS @@ -182,9 +178,8 @@ theorem call_fun_mulExpRay_direct (evmSgt x 86989971160273136331862631243) (evmSlt (evmSub - (evmAdd - (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) 129) - (evmShr 127 (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y)))) + (evmSub (evmClz (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))) + (evmXor 129 (evmShr 127 (evmSub (evmXor y (evmSar 255 y)) (evmSar 255 y))))) (evmSar kRoundShift (evmAdd (evmShl kHalfShift 1) (evmMul cInvQ192 x)))) 2) = 0 := by simpa [mulExpGuardTree, mulShiftTree, scaleShiftTree, absTree, signTree, kTree, @@ -210,7 +205,7 @@ theorem call_fun_mulExpRay_direct hconvertY1, hconvert255, hshiftSign, hwrapAy, hconvertAy, hguardUnfold, hzeroInit, hclz, hscaleClzBias, hwrapS, - hconvert127, hshrAy, hwrapAdd, hoctave, hconvertS, hwrapShift, + hconvert127, hshrAy, hoctave, hconvertS, hwrapShift, hHi, hcleanupXForHi, hconvertTwo, hcleanupShift, hOrGuard, hscaleShift, hconvertShiftOut, hZM, hkernel, hconvertInt256, hconvertNarrow,