Add poanetwork/vdf code

From commit 719925d
https://github.com/poanetwork/vdf
This commit is contained in:
Agost Biro 2024-06-05 21:36:25 +02:00
parent 58456c1057
commit 7a29f65100
No known key found for this signature in database
24 changed files with 5572 additions and 0 deletions

3
.gitignore vendored
View File

@ -8,3 +8,6 @@ ceremony-client
.env.signers .env.signers
.task .task
node-tmp-* node-tmp-*
# Rust
target

701
Cargo.lock generated Normal file
View File

@ -0,0 +1,701 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bit-vec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstyle",
"clap_lex",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "classgroup"
version = "0.1.0"
dependencies = [
"criterion",
"libc",
"num-traits",
]
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array",
]
[[package]]
name = "either"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "half"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "is-terminal"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "plotters"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7"
[[package]]
name = "plotters-svg"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "regex"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "serde"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
dependencies = [
"block-buffer",
"digest",
"fake-simd",
"opaque-debug",
]
[[package]]
name = "syn"
version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "vdf"
version = "0.1.0"
dependencies = [
"bit-vec",
"classgroup",
"criterion",
"hex",
"num-traits",
"sha2",
]
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "web-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

24
Cargo.toml Normal file
View File

@ -0,0 +1,24 @@
# Copyright 2018 Chia Network Inc and POA Networks Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# and limitations under the License.
[workspace]
members = [
"crates/vdf",
"crates/classgroup",
]
[profile.release]
rpath = true
lto = true
debug = false
# panic = 'abort'

View File

@ -0,0 +1,34 @@
# Copyright 2018 POA Networks Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# and limitations under the License.
[package]
name = "classgroup"
version = "0.1.0"
authors = ["Demi M. Obenour <demiobenour@gmail.com>"]
description = """An implementation of class groups in Rust. Uses GMP for arithmetic."""
keywords = ["classgroup", "vdf"]
repository = "https://github.com/poanetwork/vdf"
license = "Apache-2.0"
edition = "2018"
[dependencies]
num-traits = "0.2"
libc = "0.2"
[dev-dependencies]
criterion = ">=0.2"
[[bench]]
name = "classgroup-bench"
harness = false
path = "bench/bench.rs"

View File

@ -0,0 +1,66 @@
// Copyright 2018 POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_use]
extern crate criterion;
use classgroup::{gmp_classgroup::GmpClassGroup, ClassGroup};
use criterion::Criterion;
use gmp::mpz::Mpz;
use std::str::FromStr;
fn bench_square(c: &mut Criterion) {
for _ in 0..2 {
let m_2048 = -Mpz::from_str(
"201493927071865251625903550712920535753645598483515670853547009\
878440933309489362800393797428711071833308081461824159206915864\
150805748296170245037221957772328044276705571745811271212292422\
075849739248257870371300001313586036515879618764093772248760562\
386804073478433157526816295216137723803793411828867470089409596\
238958950007370719325959579892866588928887249912429688364409867\
895510817680171869190054122881274299350947669820596157115994418\
034091728887584373727555384075665624624856766441009974642693066\
751400054217209981490667208950669417773785631693879782993019167\
69407006303085854796535778826115224633447713584423",
)
.unwrap();
let m_1024 = -Mpz::from_str(
"-11208471744389096429663063172516742066731683613191418514476174383781\
682509882427394963852743081347678693241523614532942268295868231081182\
819214054220080323345750407342623884342617809879459211722505867733607\
400509994975706778681543998242335468203860240586171413971485860382901\
6409314686266660248501773529803183",
)
.unwrap();
let group_1024 = GmpClassGroup::generator_for_discriminant(m_1024);
let group_2048 = GmpClassGroup::generator_for_discriminant(m_2048);
let (group_1024_clone, group_2048_clone) = (group_1024.clone(), group_2048.clone());
c.bench_function("square 1024", move |b| {
b.iter(|| group_1024_clone.clone().square())
});
c.bench_function("multiply 1024", move |b| {
b.iter(|| &group_1024 * &group_1024)
});
c.bench_function("square 2048", move |b| {
b.iter(|| group_2048_clone.clone().square())
});
c.bench_function("multiply 2048", move |b| {
b.iter(|| &group_2048 * &group_2048)
});
}
}
criterion_group!(benches, bench_square);
criterion_main!(benches);

View File

@ -0,0 +1,7 @@
use super::mpz::*;
#[link(name = "gmp")]
extern "C" {
pub fn __gmpz_fdiv_q(q: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
pub fn __gmpz_cdiv_q(q: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
}

View File

@ -0,0 +1,12 @@
#![warn(deprecated)]
#![allow(non_camel_case_types)]
extern crate libc;
extern crate num_traits;
mod ffi;
pub mod mpz;
pub mod sign;
#[cfg(test)]
mod test;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
pub enum Sign {
Negative,
Zero,
Positive,
}

View File

@ -0,0 +1,582 @@
use super::mpz::mp_limb_t;
use std;
use libc::c_int;
#[link(name = "gmp")]
extern "C" {
static __gmp_bits_per_limb: c_int;
}
#[test]
#[allow(unsafe_code)]
fn test_limb_size() {
// We are assuming that the limb size is the same as the pointer size.
assert_eq!(std::mem::size_of::<mp_limb_t>() * 8,
unsafe { __gmp_bits_per_limb as usize });
}
mod mpz {
use super::super::mpz::Mpz;
use super::super::mpz::ProbabPrimeResult;
use super::super::sign::Sign;
use std::str::FromStr;
use std::convert::{From, Into};
use std::{i64, u64};
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
#[test]
fn test_set() {
let mut x: Mpz = From::<i64>::from(1000);
let y: Mpz = From::<i64>::from(5000);
assert!(x != y);
x.set(&y);
assert!(x == y);
}
#[test]
fn test_set_from_str_radix() {
let mut x: Mpz = From::<i64>::from(1000);
let y: Mpz = From::<i64>::from(5000);
assert!(x != y);
assert!(x.set_from_str_radix("5000", 10));
assert!(x == y);
assert!(!x.set_from_str_radix("aaaa", 2));
}
#[test]
#[should_panic]
fn test_from_str_radix_lower_bound() {
let _ = Mpz::from_str_radix("", 1);
}
#[test]
#[should_panic]
fn test_from_str_radix_upper_bound() {
let _ = Mpz::from_str_radix("", 63);
}
#[test]
#[should_panic]
fn test_set_from_str_radix_lower_bound() {
let mut x = Mpz::new();
x.set_from_str_radix("", 1);
}
#[test]
#[should_panic]
fn test_set_from_str_radix_upper_bound() {
let mut x = Mpz::new();
x.set_from_str_radix("", 63);
}
#[test]
fn test_eq() {
let x: Mpz = From::<i64>::from(4242142195);
let y: Mpz = From::<i64>::from(4242142195);
let z: Mpz = From::<i64>::from(4242142196);
assert!(x == y);
assert!(x != z);
assert!(y != z);
}
#[test]
fn test_ord() {
let x: Mpz = FromStr::from_str("40000000000000000000000").unwrap();
let y: Mpz = FromStr::from_str("45000000000000000000000").unwrap();
let z: Mpz = FromStr::from_str("50000000000000000000000").unwrap();
assert!(x < y && x < z && y < z);
assert!(x <= x && x <= y && x <= z && y <= z);
assert!(z > y && z > x && y > x);
assert!(z >= z && z >= y && z >= x && y >= x);
}
#[test]
#[should_panic]
fn test_div_zero() {
let x: Mpz = From::<i64>::from(1);
let y = Mpz::new();
drop(x / y)
}
#[test]
#[should_panic]
fn test_rem_zero() {
let x: Mpz = From::<i64>::from(1);
let y = Mpz::new();
drop(x % y)
}
#[test]
fn test_div_round() {
let x: Mpz = From::<i64>::from(2);
let y: Mpz = From::<i64>::from(3);
assert!((&x / &y).to_string() == (2i32 / 3).to_string());
assert!((&x / -&y).to_string() == (2i32 / -3).to_string());
}
#[test]
fn test_rem() {
let x: Mpz = From::<i64>::from(20);
let y: Mpz = From::<i64>::from(3);
assert!((&x % &y).to_string() == (20i32 % 3).to_string());
assert!((&x % 3).to_string() == (20i32 % 3).to_string());
assert!((&x % -&y).to_string() == (20i32 % -3).to_string());
assert!((-&x % &y).to_string() == (-20i32 % 3).to_string());
}
#[test]
fn test_add() {
let x: Mpz = From::<i64>::from(2);
let y: Mpz = From::<i64>::from(3);
let str5 = 5i32.to_string();
assert!((&x + &y).to_string() == str5);
assert!((&x + 3).to_string() == str5);
assert!((&y + 2).to_string() == str5);
}
#[test]
fn test_sub() {
let x: Mpz = From::<i64>::from(2);
let y: Mpz = From::<i64>::from(3);
assert!((&x - &y).to_string() == (-1i32).to_string());
assert!((&y - &x).to_string() == 1i32.to_string());
assert!((&y - 8).to_string() == (-5i32).to_string());
}
#[test]
fn test_mul() {
let x: Mpz = From::<i64>::from(2);
let y: Mpz = From::<i64>::from(3);
assert!((&x * &y).to_string() == 6i32.to_string());
assert!((&x * 3i64).to_string() == 6i32.to_string());
assert!((&y * -5i64).to_string() == (-15i32).to_string());
// check with values not fitting in 32 bits
assert!((&x * 5000000000i64).to_string() == 10000000000i64.to_string());
}
#[test]
fn test_to_str_radix() {
let x: Mpz = From::<i64>::from(255);
assert!(x.to_str_radix(16) == "ff".to_string());
}
#[test]
fn test_to_string() {
let x: Mpz = FromStr::from_str("1234567890").unwrap();
assert!(x.to_string() == "1234567890".to_string());
}
#[test]
fn test_invalid_str() {
let x: Result<Mpz, _> = FromStr::from_str("foobar");
assert!(x.is_err());
}
#[test]
fn test_clone() {
let a: Mpz = From::<i64>::from(100);
let b = a.clone();
let aplusb: Mpz = From::<i64>::from(200);
assert!(b == a);
assert!(a + b == aplusb);
}
#[test]
fn test_from_int() {
let x: Mpz = From::<i64>::from(150);
assert!(x.to_string() == "150".to_string());
assert!(x == FromStr::from_str("150").unwrap());
}
#[test]
fn test_from_slice_u8() {
let v: Vec<u8> = vec!(255, 255);
let x: Mpz = From::from(&v[..]);
assert!(x.to_string() == "65535".to_string());
}
#[test]
fn test_abs() {
let x: Mpz = From::<i64>::from(1000);
let y: Mpz = From::<i64>::from(-1000);
assert!(-&x == y);
assert!(x == -&y);
assert!(x == y.abs());
assert!(x.abs() == y.abs());
}
#[test]
fn test_div_floor() {
let two: Mpz = From::<i64>::from(2);
let eight: Mpz = From::<i64>::from(8);
let minuseight: Mpz = From::<i64>::from(-8);
let three: Mpz = From::<i64>::from(3);
let minusthree: Mpz = From::<i64>::from(-3);
assert_eq!(eight.div_floor(&three), two);
assert_eq!(eight.div_floor(&minusthree), minusthree);
assert_eq!(minuseight.div_floor(&three), minusthree);
assert_eq!(minuseight.div_floor(&minusthree), two);
}
#[test]
fn test_mod_floor() {
let one: Mpz = From::<i64>::from(1);
let minusone: Mpz = From::<i64>::from(-1);
let two: Mpz = From::<i64>::from(2);
let minustwo: Mpz = From::<i64>::from(-2);
let three: Mpz = From::<i64>::from(3);
let minusthree: Mpz = From::<i64>::from(-3);
let eight: Mpz = From::<i64>::from(8);
let minuseight: Mpz = From::<i64>::from(-8);
assert_eq!(eight.mod_floor(&three), two);
assert_eq!(eight.mod_floor(&minusthree), minusone);
assert_eq!(minuseight.mod_floor(&three), one);
assert_eq!(minuseight.mod_floor(&minusthree), minustwo);
}
#[test]
fn test_bitand() {
let a = 0b1001_0111;
let b = 0b1100_0100;
let mpza: Mpz = From::<i64>::from(a);
let mpzb: Mpz = From::<i64>::from(b);
let mpzres: Mpz = From::<i64>::from(a & b);
assert!(mpza & mpzb == mpzres);
}
#[test]
fn test_bitor() {
let a = 0b1001_0111;
let b = 0b1100_0100;
let mpza: Mpz = From::<i64>::from(a);
let mpzb: Mpz = From::<i64>::from(b);
let mpzres: Mpz = From::<i64>::from(a | b);
assert!(mpza | mpzb == mpzres);
}
#[test]
fn test_bitxor() {
let a = 0b1001_0111;
let b = 0b1100_0100;
let mpza: Mpz = From::<i64>::from(a);
let mpzb: Mpz = From::<i64>::from(b);
let mpzres: Mpz = From::<i64>::from(a ^ b);
assert!(mpza ^ mpzb == mpzres);
}
#[test]
fn test_shifts() {
let i = 227;
let j: Mpz = From::<i64>::from(i);
assert!((i << 4).to_string() == (&j << 4).to_string());
assert!((-i << 4).to_string() == (-&j << 4).to_string());
assert!((i >> 4).to_string() == (&j >> 4).to_string());
assert!((-i >> 4).to_string() == (-&j >> 4).to_string());
}
#[test]
fn test_compl() {
let a: Mpz = From::<i64>::from(13);
let b: Mpz = From::<i64>::from(-442);
assert!(a.compl().to_string() == (!13i32).to_string());
assert!(b.compl().to_string() == (!-442i32).to_string());
}
#[test]
fn test_pow() {
let a: Mpz = From::<i64>::from(2);
let b: Mpz = From::<i64>::from(8);
assert!(a.pow(3) == b);
assert!(Mpz::ui_pow_ui(2, 3) == b);
}
#[test]
fn test_powm() {
let a: Mpz = From::<i64>::from(13);
let b: Mpz = From::<i64>::from(7);
let p: Mpz = From::<i64>::from(19);
let c: Mpz = From::<i64>::from(10);
assert!(a.powm(&b, &p) == c);
}
#[test]
fn test_powm_sec() {
let a: Mpz = From::<i64>::from(13);
let b: Mpz = From::<i64>::from(7);
let p: Mpz = From::<i64>::from(19);
let c: Mpz = From::<i64>::from(10);
assert!(a.powm_sec(&b, &p) == c);
}
#[test]
fn test_popcount() {
assert_eq!(Mpz::from_str_radix("1010010011", 2).unwrap().popcount(), 5);
}
#[test]
fn test_hamdist() {
let a: Mpz = From::<i64>::from(0b1011_0001);
let b: Mpz = From::<i64>::from(0b0010_1011);
assert!(a.hamdist(&b) == 4);
}
#[test]
fn test_bit_length() {
let a: Mpz = From::<i64>::from(0b1011_0000_0001_0000);
let b: Mpz = From::<i64>::from(0b101);
assert!(a.bit_length() == 16);
assert!(b.bit_length() == 3);
}
#[test]
fn test_probab_prime() {
let prime: Mpz = From::<i64>::from(2);
assert!(prime.probab_prime(15) == ProbabPrimeResult::Prime);
let not_prime: Mpz = From::<i64>::from(4);
assert!(not_prime.probab_prime(15) == ProbabPrimeResult::NotPrime);
}
#[test]
fn test_nextprime() {
let a: Mpz = From::<i64>::from(123456);
let b: Mpz = From::<i64>::from(123457);
assert!(a.nextprime() == b);
}
#[test]
fn test_gcd() {
let zero: Mpz = From::<i64>::from(0);
let three: Mpz = From::<i64>::from(3);
let six: Mpz = From::<i64>::from(6);
let eighteen: Mpz = From::<i64>::from(18);
let twentyfour: Mpz = From::<i64>::from(24);
assert!(zero.gcd(&zero) == zero);
assert!(three.gcd(&six) == three);
assert!(eighteen.gcd(&twentyfour) == six);
}
#[test]
fn test_gcdext() {
let six: Mpz = From::<i64>::from(6);
let eighteen: Mpz = From::<i64>::from(18);
let twentyfour: Mpz = From::<i64>::from(24);
let (g, s, t) = eighteen.gcdext(&twentyfour);
assert!(g == six);
assert!(g == s*eighteen + t*twentyfour);
}
#[test]
fn test_lcm() {
let zero: Mpz = From::<i64>::from(0);
let three: Mpz = From::<i64>::from(3);
let five: Mpz = From::<i64>::from(5);
let six: Mpz = From::<i64>::from(6);
let eighteen: Mpz = From::<i64>::from(18);
let twentyfour: Mpz = From::<i64>::from(24);
let seventytwo: Mpz = From::<i64>::from(72);
assert!(zero.lcm(&five) == zero);
assert!(five.lcm(&zero) == zero);
assert!(three.lcm(&six) == six);
assert!(eighteen.lcm(&twentyfour) == seventytwo);
}
#[test]
fn test_is_multiple_of() {
let two: Mpz = From::<i64>::from(2);
let three: Mpz = From::<i64>::from(3);
let six: Mpz = From::<i64>::from(6);
assert!(six.is_multiple_of(&two));
assert!(six.is_multiple_of(&three));
assert!(!three.is_multiple_of(&two));
}
#[test]
fn test_modulus() {
let minusone: Mpz = From::<i64>::from(-1);
let two: Mpz = From::<i64>::from(2);
let three: Mpz = From::<i64>::from(3);
assert_eq!(two.modulus(&three), two);
assert_eq!(minusone.modulus(&three), two);
}
#[test]
fn test_invert() {
let two: Mpz = From::<i64>::from(2);
let three: Mpz = From::<i64>::from(3);
let four: Mpz = From::<i64>::from(4);
let five: Mpz = From::<i64>::from(5);
let eleven: Mpz = From::<i64>::from(11);
assert!(three.invert(&eleven) == Some(four.clone()));
assert!(four.invert(&eleven) == Some(three.clone()));
assert!(two.invert(&five) == Some(three.clone()));
assert!(three.invert(&five) == Some(two.clone()));
assert!(two.invert(&four).is_none());
}
#[test]
fn test_one() {
let onea: Mpz = From::<i64>::from(1);
let oneb: Mpz = From::<i64>::from(1);
assert!(onea == oneb);
}
#[test]
fn test_bit_fiddling() {
let mut xs: Mpz = From::<i64>::from(0b1010_1000_0010_0011);
assert!(xs.bit_length() == 16);
let mut ys = [true, false, true, false,
true, false, false, false,
false, false, true, false,
false, false, true, true];
ys.reverse();
for i in 0..xs.bit_length() {
assert!(xs.tstbit(i) == ys[i]);
}
xs.setbit(0);
ys[0] = true;
xs.setbit(3);
ys[3] = true;
xs.clrbit(1);
ys[1] = false;
xs.clrbit(5);
ys[5] = false;
xs.combit(14);
ys[14] = !ys[14];
xs.combit(15);
ys[15] = !ys[15];
for i in 0..xs.bit_length() {
assert!(xs.tstbit(i) == ys[i]);
}
}
#[test]
fn test_root() {
let x: Mpz = From::<i64>::from(123456);
let y: Mpz = From::<i64>::from(49);
assert!(x.root(3) == y);
}
#[test]
fn test_sqrt() {
let x: Mpz = From::<i64>::from(567);
let y: Mpz = From::<i64>::from(23);
assert!(x.sqrt() == y);
}
#[test]
fn test_hash_short() {
let zero: Mpz = From::<i64>::from(0);
let one: Mpz = From::<i64>::from(1);
let two = &one + &one;
let hash = |x : &Mpz| {
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
assert!(hash(&zero) != hash(&one));
assert_eq!(hash(&one), hash(&(&two - &one)));
}
#[test]
fn test_hash_long() {
let a = Mpz::from_str_radix("348917329847193287498312749187234192387", 10)
.unwrap();
let b = Mpz::from_str_radix("348917329847193287498312749187234192386", 10)
.unwrap();
let one: Mpz = From::<i64>::from(1);
let hash = |x : &Mpz| {
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
assert!(hash(&a) != hash(&b));
assert_eq!(hash(&a), hash(&(&b + &one)));
assert_eq!(hash(&(&a - &a)), hash(&(&one - &one)));
}
#[test]
fn test_to_vec_u8() {
let minus_five: Mpz = From::<i64>::from(-5);
let minus_one: Mpz = From::<i64>::from(-1);
let zero: Mpz = From::<i64>::from(0);
let one: Mpz = From::<i64>::from(1);
let five: Mpz = From::<i64>::from(5);
let xffff: Mpz = From::<i64>::from(65535);
let max_u64: Mpz = From::<u64>::from(u64::MAX);
assert_eq!(Into::<Vec<u8>>::into(&minus_five), vec!(5u8));
assert_eq!(Into::<Vec<u8>>::into(&minus_one), vec!(1u8));
assert_eq!(Into::<Vec<u8>>::into(&zero), vec!(0u8));
assert_eq!(Into::<Vec<u8>>::into(&one), vec!(1u8));
assert_eq!(Into::<Vec<u8>>::into(&five), vec!(5u8));
assert_eq!(Into::<Vec<u8>>::into(&xffff), vec!(255u8, 255u8));
assert_eq!(Into::<Vec<u8>>::into(&max_u64), vec!(255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8));
}
#[test]
fn test_to_u64() {
let minus_five: Mpz = From::<i64>::from(-5);
let minus_one: Mpz = From::<i64>::from(-1);
let zero: Mpz = From::<i64>::from(0);
let one: Mpz = From::<i64>::from(1);
let five: Mpz = From::<i64>::from(5);
let max_u64: Mpz = From::<u64>::from(u64::MAX);
assert_eq!(Into::<Option<u64>>::into(&minus_five), None);
assert_eq!(Into::<Option<u64>>::into(&minus_one), None);
assert_eq!(Into::<Option<u64>>::into(&zero), Some(0u64));
assert_eq!(Into::<Option<u64>>::into(&one), Some(1u64));
assert_eq!(Into::<Option<u64>>::into(&five), Some(5u64));
assert_eq!(Into::<Option<u64>>::into(&max_u64), Some(u64::MAX));
assert_eq!(Into::<Option<u64>>::into(&(&max_u64 + &one)), None);
}
#[test]
fn test_to_i64() {
let min_i64: Mpz = From::<i64>::from(i64::MIN);
let minus_five: Mpz = From::<i64>::from(-5);
let minus_one: Mpz = From::<i64>::from(-1);
let zero: Mpz = From::<i64>::from(0);
let one: Mpz = From::<i64>::from(1);
let five: Mpz = From::<i64>::from(5);
let max_i64: Mpz = From::<i64>::from(i64::MAX);
assert_eq!(Into::<Option<i64>>::into(&(&min_i64 - &one)), None);
assert_eq!(Into::<Option<i64>>::into(&min_i64), Some(i64::MIN));
assert_eq!(Into::<Option<i64>>::into(&minus_five), Some(-5i64));
assert_eq!(Into::<Option<i64>>::into(&minus_one), Some(-1i64));
assert_eq!(Into::<Option<i64>>::into(&zero), Some(0i64));
assert_eq!(Into::<Option<i64>>::into(&one), Some(1i64));
assert_eq!(Into::<Option<i64>>::into(&five), Some(5i64));
assert_eq!(Into::<Option<i64>>::into(&max_i64), Some(i64::MAX));
assert_eq!(Into::<Option<i64>>::into(&(&max_i64 + &one)), None);
}
#[test]
fn test_sign() {
let zero: Mpz = From::<i64>::from(0);
let five: Mpz = From::<i64>::from(5);
let minus_five: Mpz = From::<i64>::from(-5);
assert_eq!(zero.sign(), Sign::Zero);
assert_eq!(five.sign(), Sign::Positive);
assert_eq!(minus_five.sign(), Sign::Negative);
}
#[test]
fn test_format() {
let zero = Mpz::zero();
assert_eq!(format!("{}", zero), "0");
let zero = Mpz::from(-51213);
assert_eq!(format!("{}", zero), "-51213");
}
}

View File

@ -0,0 +1,90 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![forbid(unsafe_code)]
use self::ffi::Mpz;
use super::ffi;
/// Stores temporary values for congruence computations, to avoid
/// repeated allocations.
///
/// It is allowed (but inefficient) to generate a fresh `CongruenceContest`
/// for each call to `solve_linear_congruence`.
///
/// `self.solve_linear_congruence` can be called no matter what values
/// this structs public members hold, so long as they are valid `Mpz` values.
/// However, the values of these members after such a call must not be relied
/// on.
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct CongruenceContext {
pub g: Mpz,
pub d: Mpz,
pub q: Mpz,
pub r: Mpz,
}
// #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
// struct NoCongruence;
impl Default for CongruenceContext {
fn default() -> Self {
Self {
g: Mpz::new(),
d: Mpz::new(),
q: Mpz::new(),
r: Mpz::new(),
}
}
}
impl CongruenceContext {
/// Solves `a*x = b (mod m)`, storing `x` in `mu`
///
/// This function may clobber any or all of `self`s member variables.
///
/// # Panics
///
/// Panics if the congruence could not be solved.
pub fn solve_linear_congruence(
&mut self,
mu: &mut Mpz,
v: Option<&mut Mpz>,
a: &Mpz,
b: &Mpz,
m: &Mpz,
) {
ffi::mpz_gcdext(&mut self.g, &mut self.d, mu, a, m);
if cfg!(test) {
println!(
"g = {}, d = {}, e = {}, a = {}, m = {}",
self.g, self.d, mu, a, m
);
}
if cfg!(debug_assertions) {
ffi::mpz_fdiv_qr(&mut self.q, &mut self.r, b, &self.g);
debug_assert!(self.r.is_zero(), "Could not solve the congruence ― did you pass a non-prime or a positive number to the command line tool?!");
} else {
ffi::mpz_divexact(&mut self.q, b, &self.g)
}
ffi::mpz_mul(&mut self.r, &self.q, &self.d);
ffi::mpz_tdiv_r(mu, &self.r, m);
if let Some(v) = v {
if cfg!(debug_assertions) {
ffi::mpz_fdiv_qr(v, &mut self.r, &m, &self.g);
debug_assert!(self.r.is_zero(), "Could not solve the congruence ― did you pass a non-prime or a positive number to the command line tool?!");
} else {
ffi::mpz_divexact(v, &m, &self.g)
}
}
}
}

View File

@ -0,0 +1,340 @@
// Copyright 2018 POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! FFI bindings to GMP. This module exists because the `rust-gmp` crate
//! is too high-level. High-performance bignum computation requires that
//! bignums be modified in-place, so that their storage can be reused.
//! Furthermore, the `rust-gmp` crate doesnt support many operations that
//! this library requires.
#![allow(unsafe_code)]
pub use super::super::gmp::mpz::Mpz;
use super::super::gmp::mpz::{mp_bitcnt_t, mp_limb_t};
use libc::{c_int, c_long, c_ulong, c_void, size_t};
// pub use c_ulong;
use std::{mem, usize};
// We use the unsafe versions to avoid unecessary allocations.
#[link(name = "gmp")]
extern "C" {
fn __gmpz_gcdext(gcd: *mut Mpz, s: *mut Mpz, t: *mut Mpz, a: *const Mpz, b: *const Mpz);
fn __gmpz_gcd(rop: *mut Mpz, op1: *const Mpz, op2: *const Mpz);
fn __gmpz_fdiv_qr(q: *mut Mpz, r: *mut Mpz, b: *const Mpz, g: *const Mpz);
fn __gmpz_fdiv_q(q: *mut Mpz, n: *const Mpz, d: *const Mpz);
fn __gmpz_divexact(q: *mut Mpz, n: *const Mpz, d: *const Mpz);
fn __gmpz_tdiv_q(q: *mut Mpz, n: *const Mpz, d: *const Mpz);
fn __gmpz_mul(p: *mut Mpz, a: *const Mpz, b: *const Mpz);
fn __gmpz_mul_2exp(rop: *mut Mpz, op1: *const Mpz, op2: mp_bitcnt_t);
fn __gmpz_sub(rop: *mut Mpz, op1: *const Mpz, op2: *const Mpz);
fn __gmpz_import(
rop: *mut Mpz,
count: size_t,
order: c_int,
size: size_t,
endian: c_int,
nails: size_t,
op: *const c_void,
);
fn __gmpz_tdiv_r(r: *mut Mpz, n: *const Mpz, d: *const Mpz);
fn __gmpz_sizeinbase(op: &Mpz, base: c_int) -> size_t;
fn __gmpz_fdiv_q_ui(rop: *mut Mpz, op1: *const Mpz, op2: c_ulong) -> c_ulong;
fn __gmpz_add(rop: *mut Mpz, op1: *const Mpz, op2: *const Mpz);
fn __gmpz_add_ui(rop: *mut Mpz, op1: *const Mpz, op2: c_ulong);
fn __gmpz_set_ui(rop: &mut Mpz, op: c_ulong);
fn __gmpz_set_si(rop: &mut Mpz, op: c_long);
fn __gmpz_cdiv_ui(n: &Mpz, d: c_ulong) -> c_ulong;
fn __gmpz_fdiv_ui(n: &Mpz, d: c_ulong) -> c_ulong;
fn __gmpz_tdiv_ui(n: &Mpz, d: c_ulong) -> c_ulong;
fn __gmpz_export(
rop: *mut c_void,
countp: *mut size_t,
order: c_int,
size: size_t,
endian: c_int,
nails: size_t,
op: &Mpz,
) -> *mut c_void;
fn __gmpz_powm(rop: *mut Mpz, base: *const Mpz, exp: *const Mpz, modulus: *const Mpz);
}
// MEGA HACK: rust-gmp doesnt expose the fields of this struct, so we must define
// it ourselves and cast.
//
// Should be stable though, as only GMP can change it, and doing would break binary compatibility.
#[repr(C)]
struct MpzStruct {
mp_alloc: c_int,
mp_size: c_int,
mp_d: *mut mp_limb_t,
}
macro_rules! impl_div_ui {
($t:ident, $i:ident, $f:expr) => {
pub fn $i(n: &Mpz, d: $t) -> $t {
use std::$t;
let res = unsafe { $f(n, c_ulong::from(d)) };
assert!(res <= $t::MAX.into());
res as $t
}
};
}
impl_div_ui!(u16, mpz_crem_u16, __gmpz_cdiv_ui);
impl_div_ui!(u32, mpz_frem_u32, __gmpz_fdiv_ui);
/// Returns `true` if `z` is negative and not zero. Otherwise,
/// returns `false`.
#[inline]
pub fn mpz_is_negative(z: &Mpz) -> bool {
unsafe { (*(z as *const _ as *const MpzStruct)).mp_size < 0 }
}
#[inline]
pub fn mpz_powm(rop: &mut Mpz, base: &Mpz, exponent: &Mpz, modulus: &Mpz) {
unsafe { __gmpz_powm(rop, base, exponent, modulus) }
}
#[inline]
pub fn mpz_tdiv_r(r: &mut Mpz, n: &Mpz, d: &Mpz) {
unsafe { __gmpz_tdiv_r(r, n, d) }
}
/// Sets `g` to the GCD of `a` and `b`.
#[inline]
pub fn mpz_gcdext(gcd: &mut Mpz, s: &mut Mpz, t: &mut Mpz, a: &Mpz, b: &Mpz) {
unsafe { __gmpz_gcdext(gcd, s, t, a, b) }
}
/// Doubles `rop` in-place
#[inline]
pub fn mpz_double(rop: &mut Mpz) {
if true {
// slightly faster
unsafe { __gmpz_mul_2exp(rop, rop, 1) }
} else {
unsafe { __gmpz_add(rop, rop, rop) }
}
}
#[inline]
pub fn mpz_fdiv_qr(q: &mut Mpz, r: &mut Mpz, b: &Mpz, g: &Mpz) {
unsafe { __gmpz_fdiv_qr(q, r, b, g) }
}
#[inline]
pub fn mpz_fdiv_q_ui_self(rop: &mut Mpz, op: c_ulong) -> c_ulong {
unsafe { __gmpz_fdiv_q_ui(rop, rop, op) }
}
/// Unmarshals a buffer to an `Mpz`. `buf` is interpreted as a 2s complement,
/// big-endian integer. If the buffer is empty, zero is returned.
pub fn import_obj(buf: &[u8]) -> Mpz {
fn raw_import(buf: &[u8]) -> Mpz {
let mut obj = Mpz::new();
unsafe { __gmpz_import(&mut obj, buf.len(), 1, 1, 1, 0, buf.as_ptr() as *const _) }
obj
}
let is_negative = match buf.first() {
None => return Mpz::zero(),
Some(x) => x & 0x80 != 0,
};
if !is_negative {
raw_import(buf)
} else {
let mut new_buf: Vec<_> = buf.iter().cloned().skip_while(|&x| x == 0xFF).collect();
if new_buf.is_empty() {
(-1).into()
} else {
for i in &mut new_buf {
*i ^= 0xFF
}
!raw_import(&new_buf)
}
}
}
pub fn three_gcd(rop: &mut Mpz, a: &Mpz, b: &Mpz, c: &Mpz) {
unsafe {
__gmpz_gcd(rop, a, b);
__gmpz_gcd(rop, rop, c)
}
}
#[inline]
pub fn size_in_bits(obj: &Mpz) -> usize {
unsafe { __gmpz_sizeinbase(obj, 2) }
}
#[inline]
pub fn mpz_add(rop: &mut Mpz, op1: &Mpz, op2: &Mpz) {
unsafe { __gmpz_add(rop, op1, op2) }
}
#[inline]
pub fn mpz_mul(rop: &mut Mpz, op1: &Mpz, op2: &Mpz) {
unsafe { __gmpz_mul(rop, op1, op2) }
}
#[inline]
pub fn mpz_divexact(q: &mut Mpz, n: &Mpz, d: &Mpz) {
unsafe { __gmpz_divexact(q, n, d) }
}
#[inline]
pub fn mpz_mul_2exp(rop: &mut Mpz, op1: &Mpz, op2: mp_bitcnt_t) {
unsafe { __gmpz_mul_2exp(rop as *mut _ as *mut Mpz, op1, op2) }
}
/// Divide `n` by `d`. Round towards -∞ and place the result in `q`.
#[inline]
pub fn mpz_fdiv_q(q: &mut Mpz, n: &Mpz, d: &Mpz) {
if mpz_is_negative(n) == mpz_is_negative(d) {
unsafe { __gmpz_tdiv_q(q, n, d) }
} else {
unsafe { __gmpz_fdiv_q(q, n, d) }
}
}
/// Sets `rop` to `(-1) * op`
#[inline]
#[cfg(none)]
pub fn mpz_neg(rop: &mut Mpz) {
assert!(mem::size_of::<Mpz>() == mem::size_of::<MpzStruct>());
unsafe {
let ptr = rop as *mut _ as *mut MpzStruct;
let v = (*ptr).mp_size;
(*ptr).mp_size = -v;
}
}
/// Subtracts `op2` from `op1` and stores the result in `rop`.
#[inline]
pub fn mpz_sub(rop: &mut Mpz, op1: &Mpz, op2: &Mpz) {
unsafe { __gmpz_sub(rop as *mut _ as *mut Mpz, op1, op2) }
}
/// Exports `obj` to `v` as an array of 2s complement, big-endian
/// bytes. If `v` is too small to hold the result, returns `Err(s)`,
/// where `s` is the size needed to hold the exported version of `obj`.
pub fn export_obj(obj: &Mpz, v: &mut [u8]) -> Result<(), usize> {
// Requires: offset < v.len() and v[offset..] be able to hold all of `obj`
unsafe fn raw_export(v: &mut [u8], offset: usize, obj: &Mpz) -> usize {
// SAFE as `offset` will always be in-bounds, since byte_len always <=
// byte_len_needed and we check that v.len() >= byte_len_needed.
let ptr = v.as_mut_ptr().add(offset) as *mut c_void;
// Necessary ― this byte may not be fully overwritten
*(ptr as *mut u8) = 0;
// SAFE as __gmpz_export will *always* initialize this.
let mut s: usize = mem::uninitialized();
let ptr2 = __gmpz_export(ptr, &mut s, 1, 1, 1, 0, obj);
assert_eq!(ptr, ptr2);
if 0 == s {
1
} else {
s
}
}
let size = size_in_bits(obj);
assert!(size > 0);
// Check to avoid integer overflow in later operations.
if size > usize::MAX - 8 || v.len() > usize::MAX >> 3 {
return Err(usize::MAX);
}
// One additional bit is needed for the sign bit.
let byte_len_needed = (size + 8) >> 3;
if v.len() < byte_len_needed {
return if v.is_empty() && obj.is_zero() {
Ok(())
} else {
Err(byte_len_needed)
};
}
let is_negative = mpz_is_negative(obj);
if is_negative {
// MEGA HACK: GMP does not have a function to perform 2's complement
let obj = !obj;
debug_assert!(
!mpz_is_negative(&obj),
"bitwise negation of a negative number produced a negative number"
);
let new_byte_size = (size_in_bits(&obj) + 7) >> 3;
let offset = v.len() - new_byte_size;
for i in &mut v[..offset] {
*i = 0xFF
}
unsafe {
assert_eq!(raw_export(v, offset, &obj), new_byte_size);
}
// We had to do a ones complement to get the data in a decent format,
// so now we need to flip all of the bits back. LLVM should be able to
// vectorize this loop easily.
for i in &mut v[offset..] {
*i ^= 0xFF
}
} else {
// ...but GMP will not include that in the number of bytes it writes
// (except for negative numbers)
let byte_len = (size + 7) >> 3;
assert!(byte_len > 0);
let offset = v.len() - byte_len;
// Zero out any leading bytes
for i in &mut v[..offset] {
*i = 0
}
unsafe {
assert_eq!(raw_export(v, offset, &obj), byte_len);
}
}
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn check_expected_bit_width() {
let mut s: Mpz = (-2).into();
assert_eq!(size_in_bits(&s), 2);
s = !s;
assert_eq!(s, 1.into());
s.setbit(2);
assert_eq!(s, 5.into());
}
#[test]
fn check_export() {
let mut s: Mpz = 0x100.into();
s = !s;
let mut buf = [0, 0, 0];
export_obj(&s, &mut buf).expect("buffer should be large enough");
assert_eq!(buf, [0xFF, 0xFE, 0xFF]);
export_obj(&Mpz::zero(), &mut []).unwrap();
}
#[test]
fn check_rem() {
assert_eq!(mpz_crem_u16(&(-100i64).into(), 3), 1);
assert_eq!(mpz_crem_u16(&(100i64).into(), 3), 2);
}
}

View File

@ -0,0 +1,587 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![deny(unsafe_code)]
use super::ClassGroup;
use super::gmp::mpz::Mpz;
use super::gmp::mpz::ProbabPrimeResult::NotPrime;
use num_traits::{One, Zero};
use std::{
borrow::Borrow,
cell::RefCell,
mem::swap,
ops::{Mul, MulAssign},
};
mod congruence;
pub(super) mod ffi;
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Clone)]
pub struct GmpClassGroup {
a: Mpz,
b: Mpz,
c: Mpz,
discriminant: Mpz,
}
#[derive(PartialEq, PartialOrd, Eq, Ord, Clone, Hash, Debug)]
pub struct Ctx {
negative_a: Mpz,
r: Mpz,
denom: Mpz,
old_a: Mpz,
old_b: Mpz,
ra: Mpz,
s: Mpz,
x: Mpz,
congruence_context: congruence::CongruenceContext,
h: Mpz,
w: Mpz,
m: Mpz,
u: Mpz,
a: Mpz,
l: Mpz,
j: Mpz,
b: Mpz,
k: Mpz,
t: Mpz,
mu: Mpz,
v: Mpz,
sigma: Mpz,
lambda: Mpz,
}
thread_local! {
static CTX: RefCell<Ctx> = Default::default();
}
impl GmpClassGroup {
pub fn into_raw(self) -> (Mpz, Mpz) {
(self.a, self.b)
}
fn inner_multiply(&mut self, rhs: &Self, ctx: &mut Ctx) {
self.assert_valid();
rhs.assert_valid();
// g = (b1 + b2) / 2
ffi::mpz_add(&mut ctx.congruence_context.g, &self.b, &rhs.b);
ffi::mpz_fdiv_q_ui_self(&mut ctx.congruence_context.g, 2);
// h = (b2 - b1) / 2
ffi::mpz_sub(&mut ctx.h, &rhs.b, &self.b);
ffi::mpz_fdiv_q_ui_self(&mut ctx.h, 2);
debug_assert!(&ctx.h + &ctx.congruence_context.g == rhs.b);
debug_assert!(&ctx.congruence_context.g - &ctx.h == self.b);
// w = gcd(a1, a2, g)
ffi::three_gcd(&mut ctx.w, &self.a, &rhs.a, &ctx.congruence_context.g);
// j = w
ctx.j.set(&ctx.w);
// s = a1/w
ffi::mpz_fdiv_q(&mut ctx.s, &self.a, &ctx.w);
// t = a2/w
ffi::mpz_fdiv_q(&mut ctx.t, &rhs.a, &ctx.w);
// u = g/w
ffi::mpz_fdiv_q(&mut ctx.u, &ctx.congruence_context.g, &ctx.w);
// a = t*u
ffi::mpz_mul(&mut ctx.a, &ctx.t, &ctx.u);
// b = h*u - s*c1
ffi::mpz_mul(&mut ctx.b, &ctx.h, &ctx.u);
ffi::mpz_mul(&mut ctx.m, &ctx.s, &self.c);
ctx.b += &ctx.m;
// m = s*t
ffi::mpz_mul(&mut ctx.m, &ctx.s, &ctx.t);
ctx.congruence_context.solve_linear_congruence(
&mut ctx.mu,
Some(&mut ctx.v),
&ctx.a,
&ctx.b,
&ctx.m,
);
// a = t*v
ffi::mpz_mul(&mut ctx.a, &ctx.t, &ctx.v);
// b = h - t * mu
ffi::mpz_mul(&mut ctx.m, &ctx.t, &ctx.mu);
ffi::mpz_sub(&mut ctx.b, &ctx.h, &ctx.m);
// m = s
ctx.m.set(&ctx.s);
ctx.congruence_context.solve_linear_congruence(
&mut ctx.lambda,
Some(&mut ctx.sigma),
&ctx.a,
&ctx.b,
&ctx.m,
);
// k = mu + v*lambda
ffi::mpz_mul(&mut ctx.a, &ctx.v, &ctx.lambda);
ffi::mpz_add(&mut ctx.k, &ctx.mu, &ctx.a);
// l = (k*t - h)/s
ffi::mpz_mul(&mut ctx.l, &ctx.k, &ctx.t);
ffi::mpz_sub(&mut ctx.v, &ctx.l, &ctx.h);
ffi::mpz_fdiv_q(&mut ctx.l, &ctx.v, &ctx.s);
// m = (t*u*k - h*u - c*s) / s*t
ffi::mpz_mul(&mut ctx.m, &ctx.t, &ctx.u);
ctx.m *= &ctx.k;
ffi::mpz_mul(&mut ctx.a, &ctx.h, &ctx.u);
ctx.m -= &ctx.a;
ffi::mpz_mul(&mut ctx.a, &self.c, &ctx.s);
ctx.m -= &ctx.a;
ffi::mpz_mul(&mut ctx.a, &ctx.s, &ctx.t);
ffi::mpz_fdiv_q(&mut ctx.lambda, &ctx.m, &ctx.a);
// A = s*t - r*u
ffi::mpz_mul(&mut self.a, &ctx.s, &ctx.t);
// B = ju + mr - (kt + ls)
ffi::mpz_mul(&mut self.b, &ctx.j, &ctx.u);
ffi::mpz_mul(&mut ctx.a, &ctx.k, &ctx.t);
self.b -= &ctx.a;
ffi::mpz_mul(&mut ctx.a, &ctx.l, &ctx.s);
self.b -= &ctx.a;
// C = kl - jm
ffi::mpz_mul(&mut self.c, &ctx.k, &ctx.l);
ffi::mpz_mul(&mut ctx.a, &ctx.j, &ctx.lambda);
self.c -= &ctx.a;
self.inner_reduce(ctx);
}
#[cfg_attr(not(debug_assertions), inline(always))]
fn new(a: Mpz, b: Mpz, c: Mpz, discriminant: Mpz) -> Self {
let s = GmpClassGroup {
a,
b,
c,
discriminant,
};
s.assert_valid();
s
}
#[cfg_attr(not(debug_assertions), inline(always))]
fn assert_valid(&self) {
if cfg!(debug_assertions) {
let four: Mpz = 4u64.into();
let four_ac: Mpz = four * &self.a * &self.c;
assert!(&self.discriminant + four_ac == &self.b * &self.b);
}
}
fn inner_normalize(&mut self, ctx: &mut Ctx) {
self.assert_valid();
ctx.negative_a = -&self.a;
if self.b > ctx.negative_a && self.b <= self.a {
return;
}
ffi::mpz_sub(&mut ctx.r, &self.a, &self.b);
ffi::mpz_mul_2exp(&mut ctx.denom, &self.a, 1);
ffi::mpz_fdiv_q(&mut ctx.negative_a, &ctx.r, &ctx.denom);
swap(&mut ctx.negative_a, &mut ctx.r);
swap(&mut ctx.old_b, &mut self.b);
ffi::mpz_mul(&mut ctx.ra, &ctx.r, &self.a);
ffi::mpz_mul_2exp(&mut ctx.negative_a, &ctx.ra, 1);
ffi::mpz_add(&mut self.b, &ctx.old_b, &ctx.negative_a);
ffi::mpz_mul(&mut ctx.negative_a, &ctx.ra, &ctx.r);
ffi::mpz_add(&mut ctx.old_a, &self.c, &ctx.negative_a);
ffi::mpz_mul(&mut ctx.ra, &ctx.r, &ctx.old_b);
ffi::mpz_add(&mut self.c, &ctx.old_a, &ctx.ra);
self.assert_valid();
}
fn inner_reduce(&mut self, ctx: &mut Ctx) {
self.inner_normalize(ctx);
while if ffi::mpz_is_negative(&self.b) {
self.a >= self.c
} else {
self.a > self.c
} {
debug_assert!(!self.c.is_zero());
ffi::mpz_add(&mut ctx.s, &self.c, &self.b);
ffi::mpz_add(&mut ctx.x, &self.c, &self.c);
swap(&mut self.b, &mut ctx.old_b);
ffi::mpz_fdiv_q(&mut self.b, &ctx.s, &ctx.x);
swap(&mut self.b, &mut ctx.s);
swap(&mut self.a, &mut self.c);
// x = 2sc
ffi::mpz_mul(&mut self.b, &ctx.s, &self.a);
ffi::mpz_mul_2exp(&mut ctx.x, &self.b, 1);
// b = x - old_b
ffi::mpz_sub(&mut self.b, &ctx.x, &ctx.old_b);
// x = b*s
ffi::mpz_mul(&mut ctx.x, &ctx.old_b, &ctx.s);
// s = c*s^2
ffi::mpz_mul(&mut ctx.old_b, &ctx.s, &ctx.s);
ffi::mpz_mul(&mut ctx.s, &self.a, &ctx.old_b);
// c = s - x
ffi::mpz_sub(&mut ctx.old_a, &ctx.s, &ctx.x);
// c += a
self.c += &ctx.old_a;
}
self.inner_normalize(ctx);
}
fn inner_square_impl(&mut self, ctx: &mut Ctx) {
self.assert_valid();
ctx.congruence_context.solve_linear_congruence(
&mut ctx.mu,
None,
&self.b,
&self.c,
&self.a,
);
ffi::mpz_mul(&mut ctx.m, &self.b, &ctx.mu);
ctx.m -= &self.c;
ctx.m = ctx.m.div_floor(&self.a);
// New a
ctx.old_a.set(&self.a);
ffi::mpz_mul(&mut self.a, &ctx.old_a, &ctx.old_a);
// New b
ffi::mpz_mul(&mut ctx.a, &ctx.mu, &ctx.old_a);
ffi::mpz_double(&mut ctx.a);
self.b -= &ctx.a;
// New c
ffi::mpz_mul(&mut self.c, &ctx.mu, &ctx.mu);
self.c -= &ctx.m;
self.inner_reduce(ctx);
}
#[cfg_attr(not(debug_assertions), inline(always))]
fn inner_square(&mut self, ctx: &mut Ctx) {
if cfg!(debug_assertions) {
let mut q = self.clone();
q.inner_multiply(self, ctx);
self.inner_square_impl(ctx);
assert_eq!(*self, q);
} else {
self.inner_square_impl(ctx);
}
}
/// Call `cb` with a mutable reference to the context of type `Ctx`.
///
/// The reference cannot escape the closure and cannot be sent across
/// threads.
///
/// # Panics
///
/// Panics if called recursively. This library guarantees that it will
/// never call this function from any function that takes a parameter of
/// type `&mut Ctx`.
pub fn with_context<T, U>(cb: T) -> U
where
T: FnOnce(&mut Ctx) -> U,
{
let mut opt = None;
CTX.with(|x| opt = Some(cb(&mut x.borrow_mut())));
opt.unwrap()
}
}
impl Default for GmpClassGroup {
fn default() -> Self {
GmpClassGroup {
a: Mpz::new(),
b: Mpz::new(),
c: Mpz::new(),
discriminant: Mpz::new(),
}
}
}
impl<B: Borrow<GmpClassGroup>> MulAssign<B> for GmpClassGroup {
#[cfg_attr(not(debug_assertions), inline(always))]
fn mul_assign(&mut self, rhs: B) {
let rhs = rhs.borrow();
debug_assert!(self.discriminant == rhs.discriminant);
GmpClassGroup::with_context(|ctx| self.inner_multiply(rhs, ctx));
}
}
impl super::BigNum for Mpz {
fn probab_prime(&self, iterations: u32) -> bool {
self.probab_prime(iterations.max(256) as _) != NotPrime
}
fn setbit(&mut self, bit_index: usize) {
self.setbit(bit_index)
}
fn mod_powm(&mut self, base: &Self, exponent: &Self, modulus: &Self) {
ffi::mpz_powm(self, base, exponent, modulus)
}
}
impl super::BigNumExt for Mpz {
fn frem_u32(&self, modulus: u32) -> u32 {
ffi::mpz_frem_u32(self, modulus)
}
fn crem_u16(&mut self, modulus: u16) -> u16 {
ffi::mpz_crem_u16(self, modulus)
}
}
impl<B: Borrow<Self>> Mul<B> for GmpClassGroup {
type Output = Self;
#[inline]
fn mul(mut self, rhs: B) -> Self {
self *= rhs.borrow();
self
}
}
impl<'a, B: Borrow<GmpClassGroup>> Mul<B> for &'a GmpClassGroup {
type Output = GmpClassGroup;
#[inline(always)]
fn mul(self, rhs: B) -> Self::Output {
let mut s = Clone::clone(self.borrow());
s *= rhs;
s
}
}
impl ClassGroup for GmpClassGroup {
type BigNum = Mpz;
/// Normalize `self`.
///
/// # Panics
///
/// Panics if called within a call to `Self::with_context`.
fn normalize(&mut self) {
Self::with_context(|x| self.inner_normalize(x))
}
#[cfg_attr(not(debug_assertions), inline(always))]
fn inverse(&mut self) {
self.assert_valid();
self.b = -self.b.clone();
}
fn serialize(&self, buf: &mut [u8]) -> Result<(), usize> {
self.assert_valid();
if buf.len() & 1 == 1 {
// odd lengths do not make sense
Err(0)
} else {
let len = buf.len() >> 1;
ffi::export_obj(&self.a, &mut buf[..len])?;
ffi::export_obj(&self.b, &mut buf[len..])
}
}
fn from_bytes(bytearray: &[u8], discriminant: Self::BigNum) -> Self {
let len = (ffi::size_in_bits(&discriminant) + 16) >> 4;
let a = ffi::import_obj(&bytearray[..len]);
let b = ffi::import_obj(&bytearray[len..]);
Self::from_ab_discriminant(a, b, discriminant)
}
fn from_ab_discriminant(a: Self::BigNum, b: Self::BigNum, discriminant: Self::BigNum) -> Self {
let mut four_a: Self::BigNum = 4u64.into();
four_a *= &a;
let c = (&b * &b - &discriminant) / four_a;
Self {
a,
b,
c,
discriminant,
}
}
/// Returns the discriminant of `self`.
#[inline(always)]
fn discriminant(&self) -> &Self::BigNum {
&self.discriminant
}
fn size_in_bits(num: &Self::BigNum) -> usize {
ffi::size_in_bits(num)
}
/// Reduce `self`.
///
/// # Panics
///
/// Panics if called within a call to `Self::with_context`.
fn reduce(&mut self) {
Self::with_context(|x| self.inner_reduce(x))
}
fn deserialize(buf: &[u8], discriminant: Self::BigNum) -> Self {
let len = buf.len();
debug_assert!(len != 0, "Cannot deserialize an empty buffer!");
debug_assert!(len & 1 == 0, "Buffer must be of even length");
let half_len = len >> 1;
Self::from_ab_discriminant(
ffi::import_obj(&buf[..half_len]),
ffi::import_obj(&buf[half_len..]),
discriminant,
)
}
/// Square `self`.ClassGroupPartial
///
/// # Panics
///
/// Panics if called within the scope of a call to `with_context`.
fn square(&mut self) {
Self::with_context(|ctx| self.inner_square(ctx))
}
fn unsigned_deserialize_bignum(buf: &[u8]) -> Self::BigNum {
buf.into()
}
/// Square `self` `iterations` times.
///
/// # Panics
///
/// Panics if called within the scope of a call to `with_context`.
fn repeated_square(&mut self, iterations: u64) {
Self::with_context(|ctx| {
for _ in 0..iterations {
self.inner_square(ctx)
}
})
}
fn generator_for_discriminant(discriminant: Self::BigNum) -> Self {
let one: Mpz = One::one();
let x: Mpz = &one - &discriminant;
let mut form = Self::new(2.into(), one, x.div_floor(&8.into()), discriminant);
form.reduce();
form
}
fn pow(&mut self, mut exponent: Mpz) {
self.assert_valid();
debug_assert!(exponent >= Mpz::zero());
let mut state = self.identity();
loop {
let is_odd = exponent.tstbit(0);
exponent >>= 1;
if is_odd {
state *= &*self
}
if exponent.is_zero() {
*self = state;
break;
}
self.square();
}
}
}
impl Default for Ctx {
fn default() -> Self {
Self {
negative_a: Mpz::new(),
r: Mpz::new(),
denom: Mpz::new(),
old_a: Mpz::new(),
old_b: Mpz::new(),
ra: Mpz::new(),
s: Mpz::new(),
x: Mpz::new(),
congruence_context: Default::default(),
w: Mpz::new(),
m: Mpz::new(),
u: Mpz::new(),
l: Mpz::new(),
j: Mpz::new(),
t: Mpz::new(),
a: Mpz::new(),
b: Mpz::new(),
k: Mpz::new(),
h: Mpz::new(),
mu: Mpz::new(),
v: Mpz::new(),
sigma: Mpz::new(),
lambda: Mpz::new(),
}
}
}
pub fn do_compute(discriminant: Mpz, iterations: u64) -> GmpClassGroup {
debug_assert!(discriminant < Zero::zero());
debug_assert!(discriminant.probab_prime(50) != NotPrime);
let mut f = GmpClassGroup::generator_for_discriminant(discriminant);
f.repeated_square(iterations);
f
}
#[cfg(test)]
mod test {
#![allow(unused_imports)]
use super::*;
#[test]
fn normalize() {
let mut s = GmpClassGroup::new(
16.into(),
(-23).into(),
5837_3892.into(),
(-0xdead_beefi64).into(),
);
let mut new = GmpClassGroup {
b: 9.into(),
c: 5837_3885.into(),
..s.clone()
};
s.normalize();
assert_eq!(s, new);
s = GmpClassGroup {
a: (1 << 16).into(),
b: (-76951).into(),
c: 36840.into(),
..s
};
new = GmpClassGroup {
b: 54121.into(),
c: 25425.into(),
..s.clone()
};
s.normalize();
assert_eq!(s, new);
}
}

View File

@ -0,0 +1,251 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![deny(unsafe_code)]
use num_traits::{One, Zero};
use std::ops::{Mul, MulAssign, Rem, ShlAssign};
pub mod gmp;
pub mod gmp_classgroup;
pub use self::gmp_classgroup::{
do_compute,
ffi::{export_obj, import_obj},
};
pub trait BigNum:
Zero
+ One
+ Clone
+ PartialOrd
+ std::fmt::Debug
+ Rem
+ ShlAssign<usize>
+ for<'a> MulAssign<&'a Self>
+ std::ops::Sub<u64, Output = Self>
+ std::ops::Add<u64, Output = Self>
+ std::convert::From<u64>
+ for<'a> std::convert::From<&'a [u8]>
+ std::ops::Shl<usize, Output = Self>
+ std::ops::Shr<usize, Output = Self>
+ std::ops::Neg<Output = Self>
+ std::str::FromStr
+ for<'a> std::ops::Div<&'a Self, Output = Self>
+ Eq
+ std::hash::Hash
{
fn probab_prime(&self, iterations: u32) -> bool;
fn setbit(&mut self, offset: usize);
fn mod_powm(&mut self, base: &Self, exponent: &Self, modulus: &Self);
}
pub trait BigNumExt: BigNum {
fn frem_u32(&self, modulus: u32) -> u32;
fn crem_u16(&mut self, modulus: u16) -> u16;
}
pub trait ClassGroup:
Sized + Clone + for<'a> MulAssign<&'a Self> + for<'a> Mul<&'a Self> + PartialEq + std::fmt::Debug
{
type BigNum: BigNum;
/// Produces a `Self` from `a`, `b`, and a discriminant.
fn from_ab_discriminant(a: Self::BigNum, b: Self::BigNum, discriminant: Self::BigNum) -> Self;
/// Unmarshals a `Self` from a byte array and discriminant.
///
/// The byte array will be in the format of two big-endian byte sequences
/// concatenated together.
fn from_bytes(bytearray: &[u8], discriminant: Self::BigNum) -> Self;
/// Computes the identity element of `Self` for a given discriminant.
///
/// If the discriminant is not valid, the result is unspecified.
///
/// # Panics
///
/// This may panic (but is not required to) if the discriminant is not
/// valid. If this function does not panic, the results of future
/// operations are unspecified: they will not invoke undefined behavior,
/// but may panic, loop forever, or just compute garbage.
///
/// In debug builds, this will always panic if the discriminant is invalid.
fn identity_for_discriminant(discriminant: Self::BigNum) -> Self {
Self::from_ab_discriminant(Self::BigNum::one(), Self::BigNum::one(), discriminant)
}
/// Serializes `self` to a byte array. Returns `Err(s)` if there
/// is not enough space in the buffer.
///
/// The data must be serialized in twos-complement, big-endian format.
fn serialize(&self, buf: &mut [u8]) -> std::result::Result<(), usize>;
/// Deserializes a bignum from raw bytes. The bytes **must** be interpreted
/// as a big-endian unsigned integer.
fn unsigned_deserialize_bignum(_: &[u8]) -> Self::BigNum;
/// Reduce `self` in-place.
fn reduce(&mut self);
/// Squares `self`, modifying it in-place.
///
/// A default implementation is provided, but implementations are suggested
/// to override it for performance reasons.
fn square(&mut self) {
let s = self.clone();
self.mul_assign(&s)
}
/// Normalize `self`.
fn normalize(&mut self);
/// The length of `num` in **bits**
fn size_in_bits(num: &Self::BigNum) -> usize;
/// Gets the discriminant of `self`.
fn discriminant(&self) -> &Self::BigNum;
/// Computes the identity element of a `ClassGroup`.
fn identity(&self) -> Self {
Self::identity_for_discriminant(self.discriminant().clone())
}
/// Generates a *generator* for the class group of `Self`, given a
/// discriminant.
///
/// If the discriminant is not valid, the result is unspecified.
///
/// # Relation to `Self::identity_for_discriminant`
///
/// This is *not* the same as `Self::identity_for_discriminant`: the
/// identity element is *never* a generator for *any* group. This follows
/// from their definitions: the identity element, when multiplied by another
/// element, always gives that other element, whereas *every* element in the
/// group is some power of a generator.
///
/// # Panics
///
/// This may panic (but is not required to) if the discriminant is not
/// valid. If this function does not panic, the results of future
/// operations are unspecified: they will not invoke undefined behavior,
/// but may panic, loop forever, or just compute garbage.
///
/// If the global allocator panics on running out of memory, then this
/// function may panic in the same situation, but it may also just abort the
/// program instead.
///
/// In debug builds, this will always panic if the discriminant is invalid.
fn generator_for_discriminant(discriminant: Self::BigNum) -> Self {
Self::from_ab_discriminant(2.into(), One::one(), discriminant)
}
/// Replaces `*self` with its inverse.
fn inverse(&mut self);
/// Squares `self` repeatedly in-place.
///
/// Implementors of this trait are encouraged to override this
/// with a more efficient implementation, if one exists.
fn repeated_square(&mut self, iterations: u64) {
for _ in 0..iterations {
self.square()
}
}
/// Exponentiation
fn pow(&mut self, exponent: Self::BigNum);
/// Deserialization
fn deserialize(buf: &[u8], discriminant: Self::BigNum) -> Self;
}
#[cfg(test)]
mod test {
use std::{
fs::File,
io::{BufRead, BufReader},
path::PathBuf,
};
use super::{gmp_classgroup::GmpClassGroup, ClassGroup};
use super::gmp::mpz::Mpz;
fn split_into_three_pieces(line: &str, c: char) -> [&str; 3] {
let mut iter = line.split(c);
let fst = iter.next().expect("bad test file");
let snd = iter.next().expect("bad test file");
let thd = iter.next().expect("bad test file");
assert!(iter.next().is_none(), "bad test file");
[fst, snd, thd]
}
#[test]
fn multiplication_is_correct() {
let manifest_path =
std::env::var("CARGO_MANIFEST_DIR").expect("cargo should have set this");
let mut path = PathBuf::from(&manifest_path);
path.push("tests/multiply.txt");
let mut f = BufReader::new(File::open(path).expect("test file missing or unreadable"));
let mut buffer = String::new();
loop {
let bytes_read = f
.read_line(&mut buffer)
.expect("could not read from test file");
assert!(bytes_read == buffer.len());
if bytes_read == 0 {
break;
}
if buffer.ends_with('\n') {
buffer.pop();
}
if buffer.ends_with('\r') {
buffer.pop();
}
let mut current_discriminant: Option<Mpz> = None;
let q: Vec<_> = split_into_three_pieces(&buffer, '|')
.iter()
.map(|i| {
let k = split_into_three_pieces(i, ',');
let a = Mpz::from_str_radix(k[0], 10).expect("bad test file");
let b = Mpz::from_str_radix(k[1], 10).expect("bad test file");
let c = Mpz::from_str_radix(k[2], 10).expect("bad test file");
let mut discriminant: Mpz = &b * &b;
let mut minuand: Mpz = (4u64).into();
minuand *= &a * &c;
discriminant -= &minuand;
assert!(discriminant < Mpz::zero());
// takes waaaay too long
// assert!(discriminant.probab_prime(20) !=
// gmp::mpz::ProbabPrimeResult::NotPrime);
if let Some(ref q) = current_discriminant {
assert_eq!(q, &discriminant, "mismatching discriminant in test files");
} else {
current_discriminant = Some(discriminant.clone());
}
GmpClassGroup::from_ab_discriminant(a, b, discriminant)
})
.collect();
assert_eq!(q.len(), 3);
if q[0] == q[1] {
let mut i = q[0].clone();
i.square();
assert_eq!(i, q[2]);
}
assert_eq!(&q[1] * &q[0], q[2], "multiplication not valid");
assert_eq!(&q[0] * &q[1], q[2], "multiplication not valid");
buffer.clear();
}
}
}

View File

@ -0,0 +1,100 @@
10000018491751458060893889018190756675058808109876974330719629294415871248770716417843542202672894233523533522085426391611508488462673577289978500560291881560964103822003262872704649110111368415677918460552197008588860300461769848797788221536509692873112178498610293735717449110462487732034905273446995235572,6192881975696225786035966982664995064937044822044587534644251299449043731778362309709151420033302511678628887337754750911692576543520793791684926797453257880919340267222510512181015985728296989735175472866965866872698457694161211487470544291337368825900113948256559852781942460432108372735686602775132351861,447562623961213317971342646547297454284223350038133828902656285846421695114449573517005802064814603287280139301229441755696758326577197667784458131993559071961595818908854193681416803619972011522725445624820104005456169532111411278882533391024720916070194718519556110684723979632586634811370262763099820931946|10000018491751458060893889018190756675058808109876974330719629294415871248770716417843542202672894233523533522085426391611508488462673577289978500560291881560964103822003262872704649110111368415677918460552197008588860300461769848797788221536509692873112178498610293735717449110462487732034905273446995235572,6192881975696225786035966982664995064937044822044587534644251299449043731778362309709151420033302511678628887337754750911692576543520793791684926797453257880919340267222510512181015985728296989735175472866965866872698457694161211487470544291337368825900113948256559852781942460432108372735686602775132351861,447562623961213317971342646547297454284223350038133828902656285846421695114449573517005802064814603287280139301229441755696758326577197667784458131993559071961595818908854193681416803619972011522725445624820104005456169532111411278882533391024720916070194718519556110684723979632586634811370262763099820931946|19255554116382770161579383715714909264782708765539029964624834623077914838241374452996111823462588737699221151887520236764901217774034554643488538519529924118839366411749516259835028878669578401436677730193218203890014064720579917095034628468204338354122803225577022412929359504950608508400413031048217497926,15092837287167018117143864462870004173493326087323162483214185994683512256473920528820058682931229518373567536566141901399624393736734616696317492646832399845295961581562413238135817545423153806714585874605091134049460217739322207059368564835209958877374166810803213938557201936549078491894191793263450700347,234893006768044042788914260913118901546740453084924505628085298368208613193607118822477736613870586900826160773678687890939302953916150044522278344184471658898873737893277827322372416620559784208443693756270533224257971092005354126278524692768704444715469609790946460097751182675767317515935452615150233004184
10000041052183522790242850644893154590720039288612095879016416132777489378534703527529316376767361213758229530778215090392226004364711343494340009516684351602465954563523094253968698993441741189497557646486818525059302740665570749018871945434231968929038967533223013692831944903924891259290137962329173675618,1902993169831098968408340994163042640289698812843652994188396853325597449053613940738900681358483309978075948057374939279288006967407927201371876070720282077185512088102089011109098339510946105167168603912904329219763993441428070797711607939058596983469167495985136256807429373538982995591135613664471290691,648679116947253221704188706776650677211463611636395838310356904951972039958552218839434071543988637793619482253205477878855250277635662749169650536657554110192985236141029049474956216985923614316507072329807839408341849104680142145376380471455107520480114830913820742685234228885993868983705228973767491332409|10000041052183522790242850644893154590720039288612095879016416132777489378534703527529316376767361213758229530778215090392226004364711343494340009516684351602465954563523094253968698993441741189497557646486818525059302740665570749018871945434231968929038967533223013692831944903924891259290137962329173675618,1902993169831098968408340994163042640289698812843652994188396853325597449053613940738900681358483309978075948057374939279288006967407927201371876070720282077185512088102089011109098339510946105167168603912904329219763993441428070797711607939058596983469167495985136256807429373538982995591135613664471290691,648679116947253221704188706776650677211463611636395838310356904951972039958552218839434071543988637793619482253205477878855250277635662749169650536657554110192985236141029049474956216985923614316507072329807839408341849104680142145376380471455107520480114830913820742685234228885993868983705228973767491332409|11014730391994022921548019318564443238610906141262076480168925966763126765751815894971319798676750825680596366806816953155468468927850506963854768575341863098700465049052526243803093026353195834059474734029876952052212354875982568724849333989940233032713622829273608000126280643959163722728068472850088622786,10741667368771260991465304819723549356187315169745538829427954074292104964386739024958802023185700235860418655331632400858711212007319896932342251013222776723172845936147563193613725240374195945000924112718166206035243862199173787901602224623957181722190890413718871860292878014198837725481829866947825981913,591458717193488352905603034790202837072660316706237076413003353962226001987681937225165602501036312777007571264636495875979803481147253392478958512772229202313701414596984055959140281478236518410326724468820458881999271606689529119264353275033892327553507658401114443924515886686374958949587811834733084613494
10000381915681932465973261183425742883776417480816046593820159088331265076946313439425523314444345253320002870252043057595684488140407211015115892705028395378796407813776706176594457902083795049968208905578343034404017956993894296039160788337679442024505335413399442760803039586109332233036553257459967307992,4817573728667361865336022581228097408185105735439009440346088109945423944514625700845976724084897576632126538284617885680024575350161902075565426943435359103696435860065323384485576321976518692508202982451179520762630115309722600967720404130152140308793673263051352095721900258702511325402177650727880246935,669873650881721761367318894015191721808238052876596531632606045247446982615721443478227885999211090819818334947786875090863090531638122013530669226521626152920347047659485744946461307259365312735407042929006458450763753134816736952808194188478460912675596404179851630644942038849386883091149385220764843706257|10000381915681932465973261183425742883776417480816046593820159088331265076946313439425523314444345253320002870252043057595684488140407211015115892705028395378796407813776706176594457902083795049968208905578343034404017956993894296039160788337679442024505335413399442760803039586109332233036553257459967307992,4817573728667361865336022581228097408185105735439009440346088109945423944514625700845976724084897576632126538284617885680024575350161902075565426943435359103696435860065323384485576321976518692508202982451179520762630115309722600967720404130152140308793673263051352095721900258702511325402177650727880246935,669873650881721761367318894015191721808238052876596531632606045247446982615721443478227885999211090819818334947786875090863090531638122013530669226521626152920347047659485744946461307259365312735407042929006458450763753134816736952808194188478460912675596404179851630644942038849386883091149385220764843706257|15406883651839353468888340788129827256524366500559993343402492794080742895081542466902089892082975781941021139173750937371748781682695257732868858255213590996446142784059996942302405311028161097993332331718537383888482114789770414489490580461393020737016788325059322912336073066124099655242000162998144490191,4360823987526422964670528620808397080272081276432190896883401768539814490180903410645821165307382339042226562722529652661460320310396511517028476587614669988004410806997734064375576646534713644939599630073534432499720811712867334091133681123961660738588960398432344316577526812821260889068523826290764750305,434737123855318232136803285518736106774596594589476825779021338309188039202684276728719741767739900154018854551253981210446831263812934806367418646532886786527458187655685060926749423401952358398253824964655841491692769761412354811289837062586506164527515355144754089246394187279961001728737349715244065290684
10000382084844819863091735393428537123796094124029988695624509543701671917373805547793586171907452267004536696714359178508237591675470611568215269390130161491021123479579310299191808477715227540644280867131359924216029489859205866802370878621090778893635118109144685744213704279596306855259529008805569484738,-444155911792016461297666514223280647275019670279235098115904524278820479908555182212414682305357120850467322036353999623022556562078881846242421627622835673248504490647482104203937046492778180626801172318868765508903156634858880238203680354870853572676123032093150013906751911065758499256507194503286999359,567054671672969689387757610046141412714538710354002952292665369546607156429867011238555624731427279061383543924144630291236714076290759079492403352598432624404020019598559946194717566760077730429172494635087510893397235439040191683342313758118884331110227782487142203190483880485876667351431228811762752414559|10000382084844819863091735393428537123796094124029988695624509543701671917373805547793586171907452267004536696714359178508237591675470611568215269390130161491021123479579310299191808477715227540644280867131359924216029489859205866802370878621090778893635118109144685744213704279596306855259529008805569484738,-444155911792016461297666514223280647275019670279235098115904524278820479908555182212414682305357120850467322036353999623022556562078881846242421627622835673248504490647482104203937046492778180626801172318868765508903156634858880238203680354870853572676123032093150013906751911065758499256507194503286999359,567054671672969689387757610046141412714538710354002952292665369546607156429867011238555624731427279061383543924144630291236714076290759079492403352598432624404020019598559946194717566760077730429172494635087510893397235439040191683342313758118884331110227782487142203190483880485876667351431228811762752414559|25233315598122077418065976820332071042466787077699487654424387918664961172156179342884760885536120785360009215201873305025819279551843543582105904004062292352688557410351568671077765651689593128194982886401323218888273326531345494420553999096902303332712335656165115841742118280506588108873800795844703864919,-21589572107561067243363628128888045942080137348693403707950771695641329996718935854060105037586070646944119604332897696206540905887323628203932721112852139156892903280775223036949323848394414919310082155940615053363132829628799672709557839434529964085755781777411447385312731490258576057970445296620960747711,229349228584333455202515805454481561086661761655883453088894599746824713549123206719584169689814830025633382253625181015273278307916408839487283320828823538420290774632766998050162873483736921565586622385485530453983863042070274251829142359266901387980967335820672065096008596106715431022577378179753339164658
10000535283948766913969186677763146947350893764133523013624566402396075467775122389351423347627366996308717336970472190566686266526440447170486872996146388310569838407203380788397656952824650289706008150444069157387402604479170310815759950456001810768733293842505752683896727400110806658910272623240889276302,3517715128667026666780257130236186883393464552180724243651182669587910084592324227192755249223315343739548139286489599592680626480533511441942660471947189354661549994487257423179947475122454624754426244988595239282883275819687054584105503928955994194464535141072191228405010641132986293339925974908519502951,570034118010650587062470713310391834950695503036920240298132931861980289236162947574989015145270228575455513419386383991154247888350856213235253786311087987346865298158646949041224197372582390632868027286119802250763817862749191433673344918830453654023465432067298969962772419746088402608223812814936545467246|10000535283948766913969186677763146947350893764133523013624566402396075467775122389351423347627366996308717336970472190566686266526440447170486872996146388310569838407203380788397656952824650289706008150444069157387402604479170310815759950456001810768733293842505752683896727400110806658910272623240889276302,3517715128667026666780257130236186883393464552180724243651182669587910084592324227192755249223315343739548139286489599592680626480533511441942660471947189354661549994487257423179947475122454624754426244988595239282883275819687054584105503928955994194464535141072191228405010641132986293339925974908519502951,570034118010650587062470713310391834950695503036920240298132931861980289236162947574989015145270228575455513419386383991154247888350856213235253786311087987346865298158646949041224197372582390632868027286119802250763817862749191433673344918830453654023465432067298969962772419746088402608223812814936545467246|59075354970692991755903146214605554332637224507205941847466515241658938543685224447213353186403252887052183944064961699964728259961938411627544944845776708313892390437907961447141588832103578886894741951168483053303302416173045780507296127716028825436246283574600092245162214148065236680479535423660537547914,6142586061770095737227904853540455719428485301510321654081360726874454746843797212863006221294314976215484969948774214251692404250673117267549442037815482195083213974160653516820675375995512277154295678704255795063545010227709473438581077714090470093020228882800682332012139884210689872621538573295925265993,96605184581646361029373732724432135349175091555904351927012123488431445097722589746711095342410196584277564279992867684018993498546178659279293376777551513451631505380655431533215245951077120355215801949799249196142928522335615942042353764886891560316955633828555662725473411497902686741832487630568702990486
10000992092359348487480681816729833858083850458212481718635084324812805161168823645716695515173763020806162121153711923870750015861003941980870964102569907660333270160386745314618020099129085566179786211585530303068327607946822258160299176181360948584855686949828385515610423848592364973361809055890165682387,1387707194943048769069000645578034755727575677682880147095892736572338185330919801102067876481652092034533316677281336622039276010947331496276488954193596489132454018768653574924396409513550904384989555254933742194365096022768325215822785577085941233088045260998209615597763890732713200353258054623633203363,717334904486111082107761816895355357018690502858423612748563938578649989943228419203563081094256539563484346776479991186971459579979441405718434993605445911043337999222596585935065011724285592737227690661183256354762587476450143021573235732571046140183664111033663616265739167081365443050278073128430130275044|10000992092359348487480681816729833858083850458212481718635084324812805161168823645716695515173763020806162121153711923870750015861003941980870964102569907660333270160386745314618020099129085566179786211585530303068327607946822258160299176181360948584855686949828385515610423848592364973361809055890165682387,1387707194943048769069000645578034755727575677682880147095892736572338185330919801102067876481652092034533316677281336622039276010947331496276488954193596489132454018768653574924396409513550904384989555254933742194365096022768325215822785577085941233088045260998209615597763890732713200353258054623633203363,717334904486111082107761816895355357018690502858423612748563938578649989943228419203563081094256539563484346776479991186971459579979441405718434993605445911043337999222596585935065011724285592737227690661183256354762587476450143021573235732571046140183664111033663616265739167081365443050278073128430130275044|46482666589787057164981427600152979028584675170625944424946407599960201881805307116957471661211638766618134840736062752900079748534826618093953946800313092285412874757225443617416186449293441503680335786478712016820930243711850679772176006938838607901709770799483635364697553013258865109416434882051210741449,3101717798468321538599785648396208464189816894621339325506629294456148802654755640066207376362353269286149982363784579708988481769754035006891067923386713257060529140906313751403507998251605485836475302614223762235407657418301209467207199741940328204824018102771458491705342260612142478146285653246057987987,154379792819937466421655387360779358004857339117994029103954006768201464432625988196022580370956875717212647779858597489967018623693936133011607398083022906238217469025231498041115162395196295497816525433748189786409656276394144968660209259259055129261299657708619246489632848864169630941858852164482792598772
100016993550415829135262361263254459069906572411523652885898601946150332160005753209165983241360621518247046578246408973951913750019427396230791395391900464740479884371689964652672891087059763533492805056734857093926525888370387953270730195624561287530833550654825448807998575583518751690880145682614320134626,97867808093652711513661030354940855898834960524171083907471520733521588237588575528935854367900557849089129501606401645574828485643984844895342166280487749477320616345326562522776423978127616648618120061233592736634312164206210712776242358394865817287600812334839844119000151584498625451416447766525556737091,101546865178620340984298080630771114165409461904937118589108835750643335026750315119287055941177105859697880165662377691746530085636458948369814197349790717060438350144172923110723731589639766266300381349821152919234474715235659078426677984814293485454727036020005038295982154861599467045526190910921111647828|100016993550415829135262361263254459069906572411523652885898601946150332160005753209165983241360621518247046578246408973951913750019427396230791395391900464740479884371689964652672891087059763533492805056734857093926525888370387953270730195624561287530833550654825448807998575583518751690880145682614320134626,97867808093652711513661030354940855898834960524171083907471520733521588237588575528935854367900557849089129501606401645574828485643984844895342166280487749477320616345326562522776423978127616648618120061233592736634312164206210712776242358394865817287600812334839844119000151584498625451416447766525556737091,101546865178620340984298080630771114165409461904937118589108835750643335026750315119287055941177105859697880165662377691746530085636458948369814197349790717060438350144172923110723731589639766266300381349821152919234474715235659078426677984814293485454727036020005038295982154861599467045526190910921111647828|38112895924354771000755967523257705692975308805226188158888846989042277994318034233632572801944291367363544635160689172507870767350780603573652174702847837195353422410303076999489362677424810242035375507542324255582549804459073498689456734177829753341266635299826832746075600445484602669454902196797110414268,29514825972671498452469428270002667581396743351651746797469797047436108385118786112979101930068512381300796319538713657519350359618509818562580593402643136639943548729030802553674984090829042397520519175389582956780710082733565916489480248905811215441925467758974481931055406921284703112579763389522667256173,209369197456369085510398489829077224010383063845121124974155708663637684112727148688124840116395472316273115362880530986565561714461662746456509765896943657967931982155109566457128704664240543108345283001161566864139257311910823070822151712032036583892036613154176268529246135956533435036580269691993608092680
10001857278272414635783742468687626112156223003835485801536389954295572560863634462501676022563000509436968020300398791815574826898175032553202096799719821296404518525211113962533485614199031043964942385615363652892938675160040173449995570062547675787656647030050979129677693759900885701969029983016110814344,4689276451232458601825639665209988136946233783317430787463374655024892705415877731372938558103104801918261384975590626995047805878141047994265820723310810966786623993284261416684874325742989563037963206467146622805115830511715873009621433988190289268680824928937364349844265466118648518849937971040073290847,417151168234058306514924962236880342366392470330250088900617117412557071558608977094869379187282436222898630224671275148160961737937513168266914431807498623302460140528881877180166348694674662748849360025138764269398178107070427436885941278328572218964052739099341639294288244256170434477924203033934350673327|10001857278272414635783742468687626112156223003835485801536389954295572560863634462501676022563000509436968020300398791815574826898175032553202096799719821296404518525211113962533485614199031043964942385615363652892938675160040173449995570062547675787656647030050979129677693759900885701969029983016110814344,4689276451232458601825639665209988136946233783317430787463374655024892705415877731372938558103104801918261384975590626995047805878141047994265820723310810966786623993284261416684874325742989563037963206467146622805115830511715873009621433988190289268680824928937364349844265466118648518849937971040073290847,417151168234058306514924962236880342366392470330250088900617117412557071558608977094869379187282436222898630224671275148160961737937513168266914431807498623302460140528881877180166348694674662748849360025138764269398178107070427436885941278328572218964052739099341639294288244256170434477924203033934350673327|39512406098482423779120312488933213318036506673065796538336022993655638182250527755522829589375917826833348984821059004871245970343092490834408525776732580142621174939994986501353324355190007207510458548320626445520306240377159533568686613898702507848891809938754441261902406274233712558160571614302439957131,33458680315871522230740954658476053975126560151398110919331173177225767029941330426356821906446363070251030468052516656211641983986229753635879608148342626307073260672093693099423083101538134818421873088154104042575469404107414196063491342206675483762419581621360672445423968155195195983917204254937268665705,112538323552595379512976869360963431325956968605739748467981199043411580278581204995308070112281536994589175551282469490999392089726267157369534414758432876571069898487221813246689682731800084089695271351717243345819033451481449481940560204129785884663224360555776373560572513249146398346919605386672664225732
10001885848475688153826124264809818246080666151576830718882253306412201821167674972767046901596625026072385280166547579462646990262300818624039744400633121727773879619930855094164710044647150456604915949836019563376717637829785627004484641494826695600821088683607312916171680087163211415876920408834836303184,-6401849646396930994521658626667447090190354097997530993450466589091600058118189817231880440719330366452128426380645424906405833189843064340607355709362044588398581812540592198712107929843518387144633043143678667045861106413931254718474764939962100744640406024944116893338624373426827575556627557030324975185,729010733894420808263762284440227341447693348621882426869722779163540379242011358298248405166128119693780872987746515732812024832371695093716504877119416045933332381529307504733200317114594647306152268108402837078447121693601055930678151182644443827620435481034522157377127949376404692708089215142290715182147|10001885848475688153826124264809818246080666151576830718882253306412201821167674972767046901596625026072385280166547579462646990262300818624039744400633121727773879619930855094164710044647150456604915949836019563376717637829785627004484641494826695600821088683607312916171680087163211415876920408834836303184,-6401849646396930994521658626667447090190354097997530993450466589091600058118189817231880440719330366452128426380645424906405833189843064340607355709362044588398581812540592198712107929843518387144633043143678667045861106413931254718474764939962100744640406024944116893338624373426827575556627557030324975185,729010733894420808263762284440227341447693348621882426869722779163540379242011358298248405166128119693780872987746515732812024832371695093716504877119416045933332381529307504733200317114594647306152268108402837078447121693601055930678151182644443827620435481034522157377127949376404692708089215142290715182147|29744618895999892950369062264736486891947372089326189805787662049365991492371249728993520356943689392647109012744687302300685788536119433016012855224253957313263294648625309856809103016565484862180956099939466843259337398301571034092060768935310042949815131108676382925915723778520018870120465703148469427226,-10209285996871914054868241646783255177966316197845761911887894869148957597460422378515655227929008210712234487944652632986850515682880041083632277387837772452379138668071836676947710588769042538916436601704393264463866941375385749221300434945563044575029802713999893603873804815268692854499670177122342861333,245667750146427110150677187685482906099978771660913415239953145936955067540313763536644215438217145059701666728130321490946010447912027178133916738527033418368981585094936292739042791746985193177096407440545894318127458296684680664341938696795502212145624334822453802110708189609055956050992529688916696742439
10002016107047298540914373810554280751018084476212026169532336244000095667290766720576480147453702781819098831501724861337484902920323127318735651635800283580581543246660775103367813382337363027395892342097619966629022106712471908155888170784651450900253429516651100879214540932985016853993115133868182018064,3932953570343042122021312972484149360925874859667466184891542534824273073163448674737029662190753442883970728845641115381889397609743429783435425637213409939798177187589001177019943245975437142488968879145205618985792078085357316999616817143927979980310665100836939307474346180730761675171280731347158671449,501820428787763072597412186811130523406055528535842317937667844140331895435375780110188856271616785538949009425271158566975765518229735762290911833082144356638560737127790858277137050097833066958564259261818227652665496782587799644931796940046040067871968056722480981736692953918030967693251282638067356406145|10002016107047298540914373810554280751018084476212026169532336244000095667290766720576480147453702781819098831501724861337484902920323127318735651635800283580581543246660775103367813382337363027395892342097619966629022106712471908155888170784651450900253429516651100879214540932985016853993115133868182018064,3932953570343042122021312972484149360925874859667466184891542534824273073163448674737029662190753442883970728845641115381889397609743429783435425637213409939798177187589001177019943245975437142488968879145205618985792078085357316999616817143927979980310665100836939307474346180730761675171280731347158671449,501820428787763072597412186811130523406055528535842317937667844140331895435375780110188856271616785538949009425271158566975765518229735762290911833082144356638560737127790858277137050097833066958564259261818227652665496782587799644931796940046040067871968056722480981736692953918030967693251282638067356406145|64735528603519488065780804878324224417188886620278284672701068126880574848630151784368770212266476848015707656767389613750457721321054695685260658278678665196373574627583845291930832489025699028328049591231345912341357077706665618380075933900907723135182099099317242925058024706513979297237254597076227095551,4676767511975502628189775967741301363073348373643615464321451471292999156583060169457486234222367809825517380380305131875518326506653500784620820595247817795436795668446618561421217197076229074005115884048096800861583629462266306937502121558685767398985500271610752282597009278306418521631471902811873963535,77558909729073708624985274700160896365175589183029958928607160881016530406365743721430360419631842295388705380922110512036514218268293799548453381932743351256518434510701744265175175287358735767897041689462764452869200380851139430193325516047764774954110200096814808839955087651569998366318539183831351467636
10002034549022819403076408239222347017099550415714472028923655065363879242538082883332046406086443448767298655226522786685511031384602322251464988942315474592768020948704552969250388174426697733005815698500285576084348657180234667772665672224649309035191988841439951539719672753703757656633080728573515972292,2010796810968504378931299158317582090146742925585241000850486049458701149088072887117382202081460750175074877155829037914121263394655667323321997117300425990805089503958548860857023509792455388955490579562907955528791083522774450681564161379845706643578690350999966442870934289738064461129972772676090524913,558321669961648887847428632824052548431625768519625138834794746205714201508858412984925892097351057558062620149468106508584560558388430324467000609767675063271492932614039773497135546738436362846803805003389182782828963768739992366197919348230812882254139576244708687275965273358081737826555824405654768290694|6826578859626734597480939133878569229694460186644971629457853526114421649076835335603573751879988329839397104649987465835398566386002039755592773568446984903389961798459390528478761929712163120494037385730792909171532085167309911050308445263496353865937264941597436020907055251736048076644006844409202248304,5916703632910582851125880793132408903816292476260991242513549737921610794279828040608017189829216974970365350284663821730060215581487763067707193344265376739551991053238254698337087591646614840450823227220261123886424801128338724411047128491092060105475853943890821103779036774500319107460531685286202841441,819164879939066316247739921674596158995075399415076526828586576697986820808489862654252316603348700696267835592140978359698748448462852314742485570195189002909951418034161212683212111469166114805395316595157859568773382000204444562394625047968122644730117571140576687713835978983039148632840884180063353321919|24525593055568742416097249604269483346856874441455178370798633512644823613408551383898889724136436641596007886888916843304556505396562460452498580122367837296026711996552032327466172455184570034171840642876125912558571322892683749487069829210684821264854566376842632617791479252532263566234814371052354893484,-1533308789349159850456496166928278185899248924637820082743446320631452265558278807739507468009525157831824183682096795742851767532204899527778707496003773066153051313109361171305769881696175185189326727846932831915940721252274125841396183853650527186995865126146441484052102425089961043364891055445991541807,227677657081722376213157149142023336288707753333770972277638057778548802624067098792373455123375286502620159760351354502534495438446400227420867854824820469572948638801811562066346273782346907474917163347261714943740349452378338981756888788776146521650040273657711500699241321825395413707817445618060462480902
10002074125017355975599743151046242846511112798798396053226619327592735057422378177948114365284430939135093491265336806767482478919758311098907293451660632908142687429542305038471993566061112091142254674235636984969318093242303552823770654042157452160266396125764144057012639465935378258561790879307671193782,-2677875592705731980082114894429792995071386706298929334230749772186164127600272370546755010431170895608048375369668020170159823760294147973474095537503850192302837032131733237064875342982073993793395058782971441692000690573793255526540716486233592692407763281116363187020386252791667246848349317822548915689,648635985571325401692595356147567233561468612108663071405974903212101924183730392746938934107001054497457734923399698902258386855829500228588241165821030031659482670628135844118612829510920403042586089191580683729603024542404607259365592152472123612035976391470864076397175842526847201114587386293478162448846|10002074125017355975599743151046242846511112798798396053226619327592735057422378177948114365284430939135093491265336806767482478919758311098907293451660632908142687429542305038471993566061112091142254674235636984969318093242303552823770654042157452160266396125764144057012639465935378258561790879307671193782,-2677875592705731980082114894429792995071386706298929334230749772186164127600272370546755010431170895608048375369668020170159823760294147973474095537503850192302837032131733237064875342982073993793395058782971441692000690573793255526540716486233592692407763281116363187020386252791667246848349317822548915689,648635985571325401692595356147567233561468612108663071405974903212101924183730392746938934107001054497457734923399698902258386855829500228588241165821030031659482670628135844118612829510920403042586089191580683729603024542404607259365592152472123612035976391470864076397175842526847201114587386293478162448846|67949938415113064293161178659030590691132496955041316494045733862875749417850747302562113500007310852668303846586641135508462313201852828769777121178050596003427926460422904475476244906898063142012649435038037100034350908875980928269206397866321214852019966694130786407505714074230941338096203488261864055662,53288668959102688425004591339691466327049075866255869214424335604117440952293373897678874847548640712084573721941183729796456325294146528429835461394439973255133211226526484818899123041166158632993340470979352834271983572524972059884357370847142645448863117621210245351327485761671145696210503054900410821273,105899036571802576293359771771735244647493044658191270723159384029727618422730315689072753328136534522456073200532359330590111785906447289835484981246848193838501538977975954024004079425925298710095769756420575788761877694146481988831153103750420171232975154220500803062063592047512891980560706613446433318602
1000253663479701075381410901780503799818388911512704954335021374915858764824090995263167708417293347017273433263645587016366542848367626143993424043714190337762737334693150155289579305664876408056173092807453213218218789600598025704962632695206955492435575043105375877466941810990278101450609180156411393563,66294252873466406327783927757894402143872047742685585398248434686370376436933447604037129338463580005900665059990247763362159976852149607009612276330769317942643706356713296053874697713940805071384498697200382739281769000631492714220560824564622672983217861541737814215572898066821664279189734871952442485,7449081821920052343907585734636804107890073716887030220252146886374375473495388497829441955869708386804952455148603275078999958645575875758803250484635047415319443379977946970239132988474813562402674036138638943113227930164450433318295035974410121827732702738775533740738542926454278142700154894632584181276846|1000253663479701075381410901780503799818388911512704954335021374915858764824090995263167708417293347017273433263645587016366542848367626143993424043714190337762737334693150155289579305664876408056173092807453213218218789600598025704962632695206955492435575043105375877466941810990278101450609180156411393563,66294252873466406327783927757894402143872047742685585398248434686370376436933447604037129338463580005900665059990247763362159976852149607009612276330769317942643706356713296053874697713940805071384498697200382739281769000631492714220560824564622672983217861541737814215572898066821664279189734871952442485,7449081821920052343907585734636804107890073716887030220252146886374375473495388497829441955869708386804952455148603275078999958645575875758803250484635047415319443379977946970239132988474813562402674036138638943113227930164450433318295035974410121827732702738775533740738542926454278142700154894632584181276846|24568037830590216352984530012697330969024585773239190902318728852976076281369516446912320948078334220155283803919583544158932277992855289960471883436534381687899324079630011764816867889328310023423094633012275199876596315083044545869380586009580913007036860399795245680314963399389559624688311082823805090231,5319068676363461453927187061672827259672166236556729558696928212559807675749791870496620364221934584448485936117599756917409724038460841591469075162277678937851596763739958878425260723977292640004766308405052660448827954872311329092739598965306131405515429262746842239243566030717413542127898656259746125971,303566913138393892567904204367686915490068122814370585780506941778399006742359108535463859108136357801343091343038391472615790503246239776473238906631454625779972045236751565874336398670607783613554147722203607531035833062634596664836955674449545888313212125443460195013735390947268982347767364377764736422042
10002641226772515081987795211537787929272477458505554463354638964352971364408874452069546961937801811210947177338408164991078687591091465516969203874900752888301636133298179753283838003443413422949614854305289101035884523695670918489325845677592608946818353360132477183288514801318828834214935649039394032252,-8793160452550363276528664072517898739234784407606709040941098303790678596260001324417462973553168029853952326856848991111004093395583096302100461452777142804629182141499607986715453131122448708636069213611853518781262192482364818383993101471525466753092118188242931192181704912063647353300605222746836800483,492078265126922274690434467399394077805701275647322071646319840779745006934618899651871133218190471317339124114044099413606811819906582945782428482112475530640807894231223382852644187084233002016394775416098135698147532762509163053201184493973160623592655199338520312133914851239167130412730662124292772722504|10002641226772515081987795211537787929272477458505554463354638964352971364408874452069546961937801811210947177338408164991078687591091465516969203874900752888301636133298179753283838003443413422949614854305289101035884523695670918489325845677592608946818353360132477183288514801318828834214935649039394032252,-8793160452550363276528664072517898739234784407606709040941098303790678596260001324417462973553168029853952326856848991111004093395583096302100461452777142804629182141499607986715453131122448708636069213611853518781262192482364818383993101471525466753092118188242931192181704912063647353300605222746836800483,492078265126922274690434467399394077805701275647322071646319840779745006934618899651871133218190471317339124114044099413606811819906582945782428482112475530640807894231223382852644187084233002016394775416098135698147532762509163053201184493973160623592655199338520312133914851239167130412730662124292772722504|33269093498653459355911056721677057317009942094586213583836482429509057025072754420372439736248690513834971332175814464148672813487558426999636798377556094849446738441259743858358991688742216573871382813744898911570710319471125784318155373816902285919608190930249032332855663246217414413642466621378338134637,-10949330241414165733888189262458140426986707558351886540903470879800574033213186052244846799127577601176842705714647638204280400911455131674484085082600626371557414203990940725212684526037217982855212341310843343357217588085473017983047320842712153347738590477893040712557903922232099275263522420010197087053,148267471797952946823163847078479485183284021963476657656706944246030488584019895488346778002211592139277760491813666056346782934726026456786554441575227882221237740554377749215785707126496176370984922985820419829339644729974154901755996939823200818910973576565060260711661905159023290114040762532541467088824
100032603932113584190385248548088424648269645571686859576017823592423034520849963520508387815309023735382902503732005885189155388332561494704539042592634007656219743816845911733895132144423102052942452746877943975353248517709377531317937542644854604549820822373960740354167669496547979026679046866602436687763,-99537978095529356699713913260068351078290498972088228356731296595606062051578098868796341286417844471545193824704430742131836251590438154579238324251435089098889846479244366361006756968943661462663756515208457066560709300104052348033879750430334191090716067038009316021882909761152311655341491437691827562957,100461141672958569681488420113742834080404730978030677210672600173957843011309217083950874294428866093615815291020711039763544235459696431813304652678133959812856917140520431023445877504376180839416510225066460002908711498876105285713692498849763216560421523587971326926569083287005470828615251682690932454480|100032603932113584190385248548088424648269645571686859576017823592423034520849963520508387815309023735382902503732005885189155388332561494704539042592634007656219743816845911733895132144423102052942452746877943975353248517709377531317937542644854604549820822373960740354167669496547979026679046866602436687763,-99537978095529356699713913260068351078290498972088228356731296595606062051578098868796341286417844471545193824704430742131836251590438154579238324251435089098889846479244366361006756968943661462663756515208457066560709300104052348033879750430334191090716067038009316021882909761152311655341491437691827562957,100461141672958569681488420113742834080404730978030677210672600173957843011309217083950874294428866093615815291020711039763544235459696431813304652678133959812856917140520431023445877504376180839416510225066460002908711498876105285713692498849763216560421523587971326926569083287005470828615251682690932454480|83415806280351408759589239958761219329310176984650613508633653230456890652830525586600995644504636518476026029385588047137454270096528621205370620292951275504650266248010650846690600983384462303830915876850693795019055500604246841544238285169828416374845816289496545562107780789460316448092131365832361151375,-74625562140946530658296843057459607794092129677035083950600450768713067569753818651802415894941493999582236546770594323673470134033058099517659971836561944651594028658674853294680303580112276880640835753725828631472628486095723473976221487197988748307970291488083264976555432132424815586850501052682570560083,107469811246399151523671670639445335406080264077456915839785825558020206498489889359444002816596192076606675057819088885526103113392920720840544571898931473254561406865074149733521627542981016723238264871496686055481103379945620155327472162297506458535202575738651893005921523712726080367985636694514383291872
10003476324006195750203056589672528920142608070881173628253070002202847822896965018507956629750620754180015153597378490052619698657641883238019501085375230761464051022240631149609917748136390010621917552270797301343624990317089853119601059038653584566960989367701622621948512038032835888249299441269693147481,8948477894687501835769347042476812359286265266925800130378128090450514350343716170849427570408163707014128103924229513747579348337292452228930399170228437675863524232253003114523522760158376999688617602181401251377230973508602086745348949552684443228687100653278976227886870750067529496753791759215379958009,452977737155070764205462061852384767406000511527628419268926246340664360293838298755195741559726771936393803381121945775594031166662560564547853061983512305458290529662211961236299108870033900884457317683226459798783650763565076645131166564022405125204306354508519035128680777341173496414054336245228904798396|10003476324006195750203056589672528920142608070881173628253070002202847822896965018507956629750620754180015153597378490052619698657641883238019501085375230761464051022240631149609917748136390010621917552270797301343624990317089853119601059038653584566960989367701622621948512038032835888249299441269693147481,8948477894687501835769347042476812359286265266925800130378128090450514350343716170849427570408163707014128103924229513747579348337292452228930399170228437675863524232253003114523522760158376999688617602181401251377230973508602086745348949552684443228687100653278976227886870750067529496753791759215379958009,452977737155070764205462061852384767406000511527628419268926246340664360293838298755195741559726771936393803381121945775594031166662560564547853061983512305458290529662211961236299108870033900884457317683226459798783650763565076645131166564022405125204306354508519035128680777341173496414054336245228904798396|5651402082864001341383043857276519034370923662130513841623791595519661596270558403629904832806805434101124739144545597592273345291679321664787896528184481483087832442891723960004144034071036416654549567647433046035924426144596821847342448417665300158067728473706875334422169591609969538712389716925515442159,1090636869023214934530000512317584955330428598448445756182897777909589608376391586933678383330159027516570062459675025398064909568706408769200853022274439337235651672149891920445243421589467522791785184925567074521782213195039081340473683210796200673383772228925769534634646704414996683315287011695982045215,798320586788500330131894474104550120349737015590338005277237799938184156294041064946603812109197024144698401875127120433554460509300984485272200798966972702950997831115495437993447800151856526214460125938349981191215783025651707239371732305323555609927700663473758594406982664526774948117622844814657936546368
10003857993456427654260743531593175331844381828365670865226962439897092670436459982112189381696267158765639464830025128699564487196364496581401927783840749033897594251479939418637644343310965529659395490594160241233118920895398385679767173659034336248678548857485551806702464695049628038493630764757131936433,499412956562517742917849279756715433309262335746117865845799881793024584024558389384536935608560698495018673505480555335883339312289660314988198774876439555916228389426783735627572745304130362478355104078356335948823975431983850031098878540627311553089477219658101715631431867688289331308014437329410794367,428065574132217643458625663050023831718642242887566540643235772550790937328471994487142052675941441071975523602876098842203000859003355118835451924426231099194913042875268766884651796522017073832982218720474562973379560560341143898312656272368395693435837758889298389279644428917154166725285871991579086938078|10003857993456427654260743531593175331844381828365670865226962439897092670436459982112189381696267158765639464830025128699564487196364496581401927783840749033897594251479939418637644343310965529659395490594160241233118920895398385679767173659034336248678548857485551806702464695049628038493630764757131936433,499412956562517742917849279756715433309262335746117865845799881793024584024558389384536935608560698495018673505480555335883339312289660314988198774876439555916228389426783735627572745304130362478355104078356335948823975431983850031098878540627311553089477219658101715631431867688289331308014437329410794367,428065574132217643458625663050023831718642242887566540643235772550790937328471994487142052675941441071975523602876098842203000859003355118835451924426231099194913042875268766884651796522017073832982218720474562973379560560341143898312656272368395693435837758889298389279644428917154166725285871991579086938078|5985067419244985135241171028798929574240680468883302468191968098879216438700233164875805694297003438862738484975665356224507623680806342430269752869889205306990703427045634087633153837909332034829737848013329051690528535659192743560129505700514703339932109459152656849997168043791609090148125676966411164474,-3013789663785982033470828503772197819235935022596925513202295899674251698616743229507943605240952571134961898221616756365279257136756498538053825862952363683344784599061589171181375336294364884944425024815089748650913141333142482818080242503626668488451409454453378105252995530177887117956522924628476106577,715867557387629444794828253143137494171652360384349041477991757900406478237922421388389881678979412011018924778952400351577186261046593876844081918575484239857072969176632122684840733871691016063878843026835488228409619596420110671483199617250854032506474798364927317129700200264636864303167131823097056257391
100039629164915279615632745626755403195135344051296300065703707540722103090866387847978086519807842461360227602981314815898651188162817881999812578911179147999641525372151514639575701701027057192828570924656410854140601616073626299097374452319600612002632648030238739679305929396591878384845108611708173073473,-99956757702796747144330474031362091634322580823618978945421296776762235722820502139320048823797118970112849105309821058917042066320137328941305079762427354700730983116887319872947138001541985096571674792479594585340751798952938060950882542376800246430517653157385999869147535721348848735105635711972964679549,102428094420528235210038473992722778047449595066683562474358311327561453376741151333873834215335094090938635116665776111534217214948922896682406927145735733279560659220902423840693623822669973775960053647983979336042821226775972118591820157680473747907152458057697531888053067296726895267408102940444171410942|100039629164915279615632745626755403195135344051296300065703707540722103090866387847978086519807842461360227602981314815898651188162817881999812578911179147999641525372151514639575701701027057192828570924656410854140601616073626299097374452319600612002632648030238739679305929396591878384845108611708173073473,-99956757702796747144330474031362091634322580823618978945421296776762235722820502139320048823797118970112849105309821058917042066320137328941305079762427354700730983116887319872947138001541985096571674792479594585340751798952938060950882542376800246430517653157385999869147535721348848735105635711972964679549,102428094420528235210038473992722778047449595066683562474358311327561453376741151333873834215335094090938635116665776111534217214948922896682406927145735733279560659220902423840693623822669973775960053647983979336042821226775972118591820157680473747907152458057697531888053067296726895267408102940444171410942|59758487461561694442379025688208789272805646117766841371919206129104643340187013959248829747415979662207515324483234883850993532329266696739297473585807619628400010464577117227971680163239657561855113693233183544551556435408658445465178524557249837569329921343630595316681776567395248915519114258200940556334,-22671153376331064045596883212849524458683137875144383539728632975135493675352244172470558064096651200683764074233134897430860850593927295220691708458835598930765635309529560060316074048705829611628256591181426206810132007799209323907835404383161225433151628885627129593154801395506335278453552670824539376361,131822706075099232761447085662042248387269214384273446870979850351593187356535380305031128889463232587293325792397508871970239127171842305342534211852386333093595103295196214505820601536505750244236747510387243858827641299979267104558491688743963318805624534666949772263803599250156326714304699457238299478944
10004832714804908103723742535198592770160203517705805986990840545592954373052531534772757807185128680232142411531940850138353354052288042367716414491900227710660117192168358032143450533265736882961031789512953512836372805323721228539257249690634554067409180163736018674169229333523619015614939108311094404955,-4106122534013672070279170985250180991164806091813516237606357362858804809149171076685686783446662860787711693312632306442369721226548746949829113367814838200945066703674460902843843266912498986340273761329459609877828321975866552396500360382623866557971900410837449507727615090091955001901337773500512564083,735528321490864741305341471765335107420487103909921951579694743548116478766357351448185791472115882125120532716552174779001460694927011404974670401193452353207309236668713919095870342289746072100419468138261516298395168201040490324057099586440436334562163475983175689744239719212727501982130267247535538654526|10004832714804908103723742535198592770160203517705805986990840545592954373052531534772757807185128680232142411531940850138353354052288042367716414491900227710660117192168358032143450533265736882961031789512953512836372805323721228539257249690634554067409180163736018674169229333523619015614939108311094404955,-4106122534013672070279170985250180991164806091813516237606357362858804809149171076685686783446662860787711693312632306442369721226548746949829113367814838200945066703674460902843843266912498986340273761329459609877828321975866552396500360382623866557971900410837449507727615090091955001901337773500512564083,735528321490864741305341471765335107420487103909921951579694743548116478766357351448185791472115882125120532716552174779001460694927011404974670401193452353207309236668713919095870342289746072100419468138261516298395168201040490324057099586440436334562163475983175689744239719212727501982130267247535538654526|49571248488801947323762143907209086317313166403240424924024453432101823875387693931106394388064932448674243115016411805337571297304108452331736192767907165219921775519019524307831072755876229558621548399009624087618962075649066655387832586784423916396427426550173498305707525522262009377144776100617511504479,-29828959784506381554151288596212589266056524896738496309595862456247322273883550277461362725785642216517361460931008602989968457887994880159243708746757201494721079152033527869271494859280160324467867179845744346034683576782637256359631403582150391967236780147449482496203963125132702633751829108018063107905,152851999786112534607728017818026345885853920855328921975341927606898018268835818661916681924713268354620755264611816045133624308753790454966902035653944158070765154497702110731650604894939030177902410742021315843443639601716505769494787447868225921446367758854610060178076102048397807948745556177069401434816
10005026798525081885012940723882427584501711356233986451433820326862561577003483273848888665415005023331324845917111198606297565890343057122006058437816088078150993643095110440273546307247953190370321453395387856022986496964659738868016549698302294761145902566546443562453064814285197415999088360521895892448,-2012773415393071452341702894100369945009950648974284842979647951404344133571843387257391629610481617222572984474542523680934261770552452770758419481294248980432288030428538457156536090278813518012614750771478130023297469887908317305397718948039728500945544029263259198696111632370324283021118376979818613221,535224191733498084376882360698126323023228440191548650672747703583096856785431353632400792141685069598130344590929419053715450660967162173014581599286976146407034427713180051638727241035734570695485508350936098840329272631647750135734419630658939038108543820389342159392044477918576834926838103968922627914592|10005026798525081885012940723882427584501711356233986451433820326862561577003483273848888665415005023331324845917111198606297565890343057122006058437816088078150993643095110440273546307247953190370321453395387856022986496964659738868016549698302294761145902566546443562453064814285197415999088360521895892448,-2012773415393071452341702894100369945009950648974284842979647951404344133571843387257391629610481617222572984474542523680934261770552452770758419481294248980432288030428538457156536090278813518012614750771478130023297469887908317305397718948039728500945544029263259198696111632370324283021118376979818613221,535224191733498084376882360698126323023228440191548650672747703583096856785431353632400792141685069598130344590929419053715450660967162173014581599286976146407034427713180051638727241035734570695485508350936098840329272631647750135734419630658939038108543820389342159392044477918576834926838103968922627914592|22336292342012135551012779505885821083546735296581603650297115029465681138287871430168423025904988089547671399414611655350486697669350669877738276496552244732628186316333718561702084292478964766694437983324796248956801158028485684181499933232337147261336601523192790302252474972512181980447183622505293176152,-11674427075188626733931744428592651339949229796533683950532721050654863919331228509781516498261584604218739331608896593403871873856541410150113580209210756699310754431102708096662231135908839829374052715278169746619957236796967122303020947804850902024480676480363166504231340429878256710974972888619078138229,241221441172507985920847839600569201674621990755660781190984844223834501365279182693592593623964679309297220103180052193705500388401906318363940879681334805954355205327811300356578283407461158222974345862172435329520610152326479352290565487656045066487426033103805627728579179611865031310778705197856088085583
10006672794990347502279526000879267078734551177313370372283212271611928222796898904661389050998596001740140300896360857122349676163698172929644657861948036337955651058773337605834505825285215111994884147090626904932283811767278804138486301736275150746935294318794069137540121225700303083939876242601120625682,-9838237801085818249924597009069669407425270661770560087620729925196161025957715438545136585598174869667669532449305460474170293173380362768481774634876936899174710462784386243070041206971463923591073715195084153396862556329146939171493281676244388685209328525900813769124322086835985741784348578408662428059,491155226409710325351546145673359292444301383692142579605004960553566299358747456958419756937691174297624212871558627081110141997099054271399339089662075140351079784991312987158527194379830582795343003721494456884032748354538831215203553329779263289722351779436025499608302937937453427548391343898256662436681|10006672794990347502279526000879267078734551177313370372283212271611928222796898904661389050998596001740140300896360857122349676163698172929644657861948036337955651058773337605834505825285215111994884147090626904932283811767278804138486301736275150746935294318794069137540121225700303083939876242601120625682,-9838237801085818249924597009069669407425270661770560087620729925196161025957715438545136585598174869667669532449305460474170293173380362768481774634876936899174710462784386243070041206971463923591073715195084153396862556329146939171493281676244388685209328525900813769124322086835985741784348578408662428059,491155226409710325351546145673359292444301383692142579605004960553566299358747456958419756937691174297624212871558627081110141997099054271399339089662075140351079784991312987158527194379830582795343003721494456884032748354538831215203553329779263289722351779436025499608302937937453427548391343898256662436681|31407608254280798910068647236171832681250921019767339322092058225211898617080663268645257485291372241381998253211825069099135787304279471888561584499577479790815455728926265455210044341705458408895536936732959677488304976642419035897631658694309182269500334892813396007185893728237634667266625229835842258012,-22092195466303851660176460286320107196721548719910482849923927669374860570040607441847880914766942886335893807802817619964909625774361248243281497972957437956640995020582500875700785617741050040570062784832399237969854446892064368205401494750753136317996032567462911904310221537322445611817601703460856421217,159599806073129555202146898538117276396235868652725582464386632067108341746813360586970644466851546908557689300426749066266037355857824949308514825360431584985378792225819436535456535877098069496677684472533670862820828085751117871568305588734769334428789980131666205325600082215182496839515396421731764800737
10007655975072154117483238977535537637081635031134550457387493208328357153313126763724056490057039627482071052486779071595119245261713445964779121986765033599055846695490518512461118572219672259974233020703702627262496120864385268977830794693731299984872419878272800221037178910859958719636556859814167846842,-8361996877393239419962455468169075798408150795370677399435249551651328619535668258497248839588331109071829636371568824578953377032648893445576430394495769342785817892484051892349027624952023346102193243274713308717688268734992258026540569970994360123565176304254781068869111211172521527332383420931814632155,527575030718114283859783398581144142162250986653324445494333022369741458612967189239531512810665999743981788039851897018720856433180698951454061341786291502239652788707044944021930279936172715091766668769968367606820938741461139670556714129528610125247077397188304136573449554427712758172626387820770141650206|10007655975072154117483238977535537637081635031134550457387493208328357153313126763724056490057039627482071052486779071595119245261713445964779121986765033599055846695490518512461118572219672259974233020703702627262496120864385268977830794693731299984872419878272800221037178910859958719636556859814167846842,-8361996877393239419962455468169075798408150795370677399435249551651328619535668258497248839588331109071829636371568824578953377032648893445576430394495769342785817892484051892349027624952023346102193243274713308717688268734992258026540569970994360123565176304254781068869111211172521527332383420931814632155,527575030718114283859783398581144142162250986653324445494333022369741458612967189239531512810665999743981788039851897018720856433180698951454061341786291502239652788707044944021930279936172715091766668769968367606820938741461139670556714129528610125247077397188304136573449554427712758172626387820770141650206|34241072322144183964883259292388971270387490908021459682602920713448556112203521610314068181522265567865990070656464669642401927077378188525809052299062988871029831250362663444310773841166814396928628138166361702759595641474414467093470838454994055079747035830130336863078894622890889652436509718402679470062,1655044484629008994406707658240182084237566731635262662670986570402287449045651466425429233810999012995111207637792772902737734854633738760139439026788661518884592067665179528199667479368791803292009159500093938626059289257062277449763464663360562677734593664715953368375153510854218241931074507165471380277,153704107279914282661047729774770107006301606465000116416112632832793659221845961744254897413922500063463878032418234980336383112232225712099359203910269544199247014938285831933417628129448739918915220344920675471322163945672122675565456045357008398369947791399948189771245653263744530465795945375711800221494
10007966435478170058236863959453072022400241955644959598691575049123018331553853255192930054734316870465371869338898000445140839711278341717767617282979890871322011741629926128943966839416929813730135095452717804664810492420201325502018871240152164282158649420833075991948508448454814819879697083763652090752,7668231477440831839423530692551370703245159224024821557501520508935072774934016430350932340192015949812739085292897564854127442271354000519287430094037838940253057942410525639491576166138997981100229304259461266977184946214511723634011266273522059488169041964372462366036564169749432744133670979109152595493,447718029574060000854039425364603339241323607028045749886344661853336043472604487444001370995744392053933719052361283419535725001600963164946166051448582948801443754508763343722896658178932382756498803522119159379373755295799841416904795415386643502857959662236798809639975132008241096398997653679085633708897|10007966435478170058236863959453072022400241955644959598691575049123018331553853255192930054734316870465371869338898000445140839711278341717767617282979890871322011741629926128943966839416929813730135095452717804664810492420201325502018871240152164282158649420833075991948508448454814819879697083763652090752,7668231477440831839423530692551370703245159224024821557501520508935072774934016430350932340192015949812739085292897564854127442271354000519287430094037838940253057942410525639491576166138997981100229304259461266977184946214511723634011266273522059488169041964372462366036564169749432744133670979109152595493,447718029574060000854039425364603339241323607028045749886344661853336043472604487444001370995744392053933719052361283419535725001600963164946166051448582948801443754508763343722896658178932382756498803522119159379373755295799841416904795415386643502857959662236798809639975132008241096398997653679085633708897|40511141969971494931196941724119791194752303140317604712667802312789797258087471388916305711860938934695113621471555129205767772174234194577636062024449049659844773057153826765602668788474097413358584157199226050803019714953337366130977602640661927789662051175267419967969752702153115129111296636218703221612,-10457935161594282983478001185436442312204066321569717319909561123122508532580035425990850447859762708795499274494409851573173766858979090795797351580839052039648316518437023326040967891533445612383815607198257699325318317220032705269084861881246335591645639989108557010113256147197407668582018981690523309277,110917353905486580092614272588489684725195855203152146381960572034045032865176004516881779898341056044802327638909692940931520745099129277448149432184154526338845672459752333598562775198340962552587031950250223610238795938815226253408453715102541267901432200534831078606195360844918970056237910632079232669397
10008244313737062814090386880777002042274406310106728621588663972235471114422710824990333652789716385198940169070112715764189602790244309290680116655115170883594213904067142922764109544956215574952085160301875958128721493047843010586892757750339772804652221926614373576181872540979939178502806140149454950631,-2481333037464667013966629436643252131544342493286852105020088420979287811035788180793459525355154058635281869829040750298007562342275673082167816644462962921681726865943832615136603374637684966019868013077849325437190351276393203980513956812271998916894664710817164796538864396449149557648172823426916063171,517388856778664723601259064328056938198839891258102587545663260307743028813773980886782766877880248247356976487931222165792012525513693034189039784629831615801247177080220119155265743113547860287043754078724492811312457109356002302194457816150319735657096232303313256118001093875043014711306978887626524797260|10008244313737062814090386880777002042274406310106728621588663972235471114422710824990333652789716385198940169070112715764189602790244309290680116655115170883594213904067142922764109544956215574952085160301875958128721493047843010586892757750339772804652221926614373576181872540979939178502806140149454950631,-2481333037464667013966629436643252131544342493286852105020088420979287811035788180793459525355154058635281869829040750298007562342275673082167816644462962921681726865943832615136603374637684966019868013077849325437190351276393203980513956812271998916894664710817164796538864396449149557648172823426916063171,517388856778664723601259064328056938198839891258102587545663260307743028813773980886782766877880248247356976487931222165792012525513693034189039784629831615801247177080220119155265743113547860287043754078724492811312457109356002302194457816150319735657096232303313256118001093875043014711306978887626524797260|64779254867032834011440641150787867084487920384040666681242863744168381419066139445297813847374258248415619741363374551837200937516385938256833819108665346550630274436247175069020139650724403378810927075885582938267576954742862532587966930483553143703545329576408261048628895456023143683431401990598479630366,24927519754546965921961831708915463327214053646451495956699845075284971443847002280078538714647321447563383780925628397892739377674787824980025060340980938596623558107083184245064110657008379362919768477366918649506291628246060968841505524504481964062641513562929769991452205428879332678008403472520391251145,82309686205222727769575596923556209136176331852352419263671129190093456370915941776219688571948801625823542691573133895930427074460493264530457559070546811793879069016319253690636501038391024472030629593224593147217100960263693987497514077967804017050957134551364124670419141176242216681820543629095623072541
10008352850657920583191404584913972319002983012580386292746025042416454380781500166787911252581886951373899680476686789855174455691633284341038191233672952065406558892215211615248443825941676410729187290225060888418790745853338806784833379906941049072152726050837490871126796612653775780560679723194628349029,-9709060422739575026005372809573612137660920177893029425373199378974797630708961048789082569968621509437270608151157000245230087521990222886335775421061577025607819009612244487407314145511220306148818899675596604132364981950337516654200767452148218615182517964628917157152074917236803799933149738760713914115,671115082942262350108425488433280481526339397188879799636007596624691786030758042881307602706684291172315374822828497006497958099138318651797094407888149790626224845978208367284081376364107905539290535619502916118224586762249253502377439399087435554291997555942600131361589961111751560971988821471576625969886|10008352850657920583191404584913972319002983012580386292746025042416454380781500166787911252581886951373899680476686789855174455691633284341038191233672952065406558892215211615248443825941676410729187290225060888418790745853338806784833379906941049072152726050837490871126796612653775780560679723194628349029,-9709060422739575026005372809573612137660920177893029425373199378974797630708961048789082569968621509437270608151157000245230087521990222886335775421061577025607819009612244487407314145511220306148818899675596604132364981950337516654200767452148218615182517964628917157152074917236803799933149738760713914115,671115082942262350108425488433280481526339397188879799636007596624691786030758042881307602706684291172315374822828497006497958099138318651797094407888149790626224845978208367284081376364107905539290535619502916118224586762249253502377439399087435554291997555942600131361589961111751560971988821471576625969886|16114275461489124968204609015452254643913218363912153828520620336762113684215205643094736684144935580728436126433843432822838401301502605946365466722979644980151185661620762014580187078928560591048729719792010275975517300898462040047538702188845074821092289043342754604938854931775373800424648368644203310763,13547284929895770484441101131779787363607604008853234716726800689182086390631494419380414868563006093483607315075063367989733593307441496946636597309123175793027336201138908596859844194042146843338047555922226658114601025214153360367295508810902077991437858537936819515034120605401664389985997179289268252367,418205108772032981216907044691421436420223410030163644353520139623926934302604091399665635789664245218369914570143791026851295152484545480995319870729672449287479092631425718630481935403940901614139408947960419781742920397934070995211934874602805252466775364873888815295833211854864682623780313523183909895620
10008513012069041332156344897527216827073553214887592180214088737934259014714007486627977262733380816543933881903835772165306652083392244023687978336905351870998572186485570559256669905157006164174099943880073052263685924132434457096891529676454801384608866315724043225840413063557160938985851639441472622874,4312440429846754396035977404383353442711216523950513352151701783462030788529545110163564186199448542666033789397218053312248834710387435083551347290942668449155398673665487605130911092851155993391138549740383991056332072450757325017931588809593307558375428030693435084458386227675282989067613496797817920303,522058710434436061847099419719287842052400501259816466826452187248685474462894015989166683733824910524432920930163132078895575756633553848962708405953874665062957204347147145554667232000278570561581943016274309565656027423053224928776350261510971295444303769013653510888595366416887399411638422346190508715452|10008513012069041332156344897527216827073553214887592180214088737934259014714007486627977262733380816543933881903835772165306652083392244023687978336905351870998572186485570559256669905157006164174099943880073052263685924132434457096891529676454801384608866315724043225840413063557160938985851639441472622874,4312440429846754396035977404383353442711216523950513352151701783462030788529545110163564186199448542666033789397218053312248834710387435083551347290942668449155398673665487605130911092851155993391138549740383991056332072450757325017931588809593307558375428030693435084458386227675282989067613496797817920303,522058710434436061847099419719287842052400501259816466826452187248685474462894015989166683733824910524432920930163132078895575756633553848962708405953874665062957204347147145554667232000278570561581943016274309565656027423053224928776350261510971295444303769013653510888595366416887399411638422346190508715452|56624718412625747746001342620243125157932460809156476585686153252078788391585133765039303843105555487145302765475232301210334902069549060211140618709834572969221737838704380629832808447436726398836532031324189279819743594568958857642880728907272717965484249241620624993448126533648876371412676969976240808091,11251560979241989333315174860442827950692807971893794693178074029555222489351465658673586544289854384482236484135520000810924047294537285452423708542539424019529971512734796753346419671011832872098038047241101770150064698634673955572614027093346044433647412285209492755021945840975963737352969268461227245507,92751569706316371333649854241258112606711033359078430605766627827390581284909646252513959841970681664755979852330064323247275252913920697545008377769665486889671185641317526987823359091775252097776601502427528886408060350050959249578998479135473207338710170069765535652326679605884886200884837141964865764438
10008863920545293758159888428446364046156260276486716019468090049016703539043486840953638396736429084536043888977532647111473229479529562166982909202873868243789742163658153824593686536088450915373691535781953841623992587097366077922476705574496276542011226471851020760887612018025249445972903686455787297913,2645740853855108763896589086717998001934973089513790734148937968197932490008236360599464772889429848037464262397763532307275971891237738829761101393275168415676294997564886931379267812086428886706751772215615432393366054082725778686112559307784475932288658665407220266586240637350907136870607040913290590611,793400754874236243676721564968016542454513488899050997526586540816446069760957715423992612546686769171106427349384375943641326144133116588670645501231299064478777846694278704641598622565613076600211712243453441442617903127555189233115008530187155578099336294750097716133611190867259168037807083105588642566246|10008863920545293758159888428446364046156260276486716019468090049016703539043486840953638396736429084536043888977532647111473229479529562166982909202873868243789742163658153824593686536088450915373691535781953841623992587097366077922476705574496276542011226471851020760887612018025249445972903686455787297913,2645740853855108763896589086717998001934973089513790734148937968197932490008236360599464772889429848037464262397763532307275971891237738829761101393275168415676294997564886931379267812086428886706751772215615432393366054082725778686112559307784475932288658665407220266586240637350907136870607040913290590611,793400754874236243676721564968016542454513488899050997526586540816446069760957715423992612546686769171106427349384375943641326144133116588670645501231299064478777846694278704641598622565613076600211712243453441442617903127555189233115008530187155578099336294750097716133611190867259168037807083105588642566246|27460683971089209913632788439277008206698726108421557048449583612748157436343375175859322164187154644764726127789104341389062435393682455959407312665088265825287372841830854948020646918675509930411197475014852013755108095396665264198600695220092526372517655520066812589582003333706156211987354238157895214440,-18754257799889030610388359385148211437538401837086321292345976113516028840634213460141894145979065231860481969629551490782467029876512509259774443102990636739699402915097564612184570929798790707857065137355337741260683852677325380877763634549633686621832440525952151518844155190936539038380094790162128388423,292316854113502420768516012912807278549304319263771926401370626456917590670162968070277533769157336622178624301667258725748409713154982300194605653065586096039574795291737865145837966259393195694514901162748686464295686525957546330665390520676177065848461958642958875916650558856747431365214941153816669348325
10009505680139870683354483014980979080857116598143181111545123603173294088551257446784978515102956309603131729036042239470868522730508351640411841336927180142285333130556003408088825172687266397290471685595705033772539426652454509785808561354205994913107889793645231496289597484325916247643676615653797810040,-3204245228048542338423395469208468824364162898707311656951717207097770099550386735738728259011638956652924858793824233816950950613612534337274326306432643930039092581092193180132506302083387198832944317276664858711681950020725043153356848379502277900787129851654969895020729278524823784274520152043485072291,452691911613679447746063326513639174263793060004909642518772775706171480163325072807358357220816303993075973139644460675947299910587502105955195991864534504547078402941938298035649970749378328953718405749778603278187778609058449113337901162098857859007739511955733974919843773983479386171581120876366473480535|10009505680139870683354483014980979080857116598143181111545123603173294088551257446784978515102956309603131729036042239470868522730508351640411841336927180142285333130556003408088825172687266397290471685595705033772539426652454509785808561354205994913107889793645231496289597484325916247643676615653797810040,-3204245228048542338423395469208468824364162898707311656951717207097770099550386735738728259011638956652924858793824233816950950613612534337274326306432643930039092581092193180132506302083387198832944317276664858711681950020725043153356848379502277900787129851654969895020729278524823784274520152043485072291,452691911613679447746063326513639174263793060004909642518772775706171480163325072807358357220816303993075973139644460675947299910587502105955195991864534504547078402941938298035649970749378328953718405749778603278187778609058449113337901162098857859007739511955733974919843773983479386171581120876366473480535|57325550832595720002282991260198520855619892385753125887287449562869890287547556782700649421653735594090065432438621527792246214244092693717739414731384442034231735428582082971424584764012096459469280873967739009228670210741931717901688698237272251048307176343047617528247235108742851430347676100126914108357,40951175564652222245195473979961933400303424050552593889813171845223826940735103640121837889061263540857785714549429721536079825338211400035410823730435714524768011703151474601155984454456549759808694516594213778747991012336774365782807914607474811422076337673527879293888167855766653181026300408358374972063,86312387529619002943462127766854108620725875072481894074267557421849877085810739137001331161310595596779531729111999016553742317053715695938778491822422663861385491102185170957066107188324354310777066756950531425606616940837381593339739089909995724195482868610730939023987110641593221757790669575104910938446
1000951516029909402241580153254201911805533650981363847468064026947791885513152190496939080952901855372998038682278000380636609527998130327379270561313029246942896140134101369621908911346125374976926115893278132230058065500703131104226075681633220114919188893134454475954292791954736302126634675741318978601,-932129972046203740107893826647984861393190609401184260933369527488206703962436872059299754006964658145411135715285131543309666916261147162906324852866784469362588174806798886084835311322495644384917815753456114043848321591684728503353583125390553182460085266457044328481386164295062361453557198381234996483,7741880922056878066612714130026240867522108473639420974553105203701418374724364127305856418938534523230858044879263234730427059699274843010051016880192588782731180142670836033616687676672699018701220814586539096635490574816118709819174615703862984275251303192202153140463446907523629847791487096446425558516238|1000951516029909402241580153254201911805533650981363847468064026947791885513152190496939080952901855372998038682278000380636609527998130327379270561313029246942896140134101369621908911346125374976926115893278132230058065500703131104226075681633220114919188893134454475954292791954736302126634675741318978601,-932129972046203740107893826647984861393190609401184260933369527488206703962436872059299754006964658145411135715285131543309666916261147162906324852866784469362588174806798886084835311322495644384917815753456114043848321591684728503353583125390553182460085266457044328481386164295062361453557198381234996483,7741880922056878066612714130026240867522108473639420974553105203701418374724364127305856418938534523230858044879263234730427059699274843010051016880192588782731180142670836033616687676672699018701220814586539096635490574816118709819174615703862984275251303192202153140463446907523629847791487096446425558516238|15746368080076547639613112548931198412928034872598867786846558772081390410891968919792236071990423045407820022126215168896502300352310051471939494022340800892491023480415508952796942181491516127339639471207019480870149174572084740672853889392694282271865099892527052018243852819055812247442628083006705785149,-1817913436531155250968687681482056128774282329369952888473920830262042372654938097136436607889208234812116291336524382413655603485552821293038078939629653209114696856829043835764482596948782168253580822692634503701439593841617763234039276530741649509861202111285883608345674200240173376261557395276050534745,492167869580416546150864341469450817106189778801161330939305290046708175512988010176297694665433672849671984872726657705850871343875774836983621356338570200418265577466209423429850230482380970478840847989123705290014954835386530282830688430538273550828822069628430975922343455045834201595340872511606366704728
10009614232615212022005150149343932420969657134336251266196874043830583063114875468409344410544755395263952674188421355541706476649104687178621105860662213481607819203924674901060643908339267017280510002551378392012520463262809409257654601850085574494274200629627329653203473234690149811173235149360768384838,836267856629353024976937718074908246524235283001080657657057590803147642759710349203535369107634985057019274642907780561827986871269168282562729482602832882014993174240061797035451659603107102838592209619951864142851506020290496133563766536500833473922797379921857659870104796371847757654270012370698502999,784213921791375719854653276558811892255578032965532623567863494564671611248783758720878204565462346000781224582747048981949572160149632172258392213554094289354008679022701865566865099047150582908470578815534139684037571258726801746576984534581957278215217261339431677162978264928931155436559875241964125506266|91259641317840920388592572245493602418223311736654347455817117920969722081887399519379251381184940824844626111264019221904601665534920622151118371387906395484279959508114917794568416938471005687918332893135141888811509257566326226278046422522746020345472499138217410394253037717517813153026786742476211897426,65560628471815349730768404773504307627679453655870244754876894481952096786914419991524915369113837577161059316635270325176467655387763062001209403412378388608286732350937986269983898741335821089925199082458466627097168531389395465235586971316043725352106687336132311388859476958068300601993983492409770068953,97787509018580500559531280765247530593654008165836933101614934455794219747727474184974783904602569289723706867556213004773348953706945069163461128745310430174496134494281188144065521418637123474052338785100571778752720085930925320282428718659058820028049740359320116709840549247824331580105759766861379891210|75062088452630474843888448210053283462706588708992115575383926339301467347310815006622009334498696501710113137263962332974627478074375539845396462501277814094889463218705190380441269364077952749970929670210201903809188825244244127139203763727765293010747505303529125943832432756718681546490336041697468666190,5541281329506174033291380410034395388042944047800558435987093009948507724655465795692214345462752044394730637949505190953507095375192582819240934021514991426264136507386865262105651669874195906257084096658225527132816732104755767839079135854552727988309212343735183861434005237105894184406202983254934534757,104675750550793205502943520352684154101269712315945996783868759572927470248283594480842218327785617106312969404704918354113342765451442832450177716298160659447475598063377646514258038986139271814855804490712610499304684910754302950004231911223315677097295880861233808821150324765848314271787214250899197923793
10009735080309013514440203870605983374104835055250399704317172848646825795572764221124512471397022599041102696110601760496809311877056400885225531243115647095694305859001567326435058426543669680082356076887117616533496794600222886637873441727978976019755009690240085029104982970925792121991104293242809524644,6716504442878527910519807778046246423810093302344836517925018933141102172400301207571530237654753113978791017298256211048865142019514745459130820608857728114059755451415522450033212605102272496818594519931368393561070233092047087381778868100623694505448318327728934167707696920045126563192647607794472189195,721610628334648695598193480418084731432879897882901829331594044580759141755040057210356863808123513214754128306537665937117531576524824114459745892010308401743734165555223754018460218362992047097741240949227118743681363740856040612578898979577195958019157067541288613303223475902295909138865214617457058483843|10009735080309013514440203870605983374104835055250399704317172848646825795572764221124512471397022599041102696110601760496809311877056400885225531243115647095694305859001567326435058426543669680082356076887117616533496794600222886637873441727978976019755009690240085029104982970925792121991104293242809524644,6716504442878527910519807778046246423810093302344836517925018933141102172400301207571530237654753113978791017298256211048865142019514745459130820608857728114059755451415522450033212605102272496818594519931368393561070233092047087381778868100623694505448318327728934167707696920045126563192647607794472189195,721610628334648695598193480418084731432879897882901829331594044580759141755040057210356863808123513214754128306537665937117531576524824114459745892010308401743734165555223754018460218362992047097741240949227118743681363740856040612578898979577195958019157067541288613303223475902295909138865214617457058483843|27431399959730041618757181598450126761864467783308250953166653158864868050165660437728250584906458406104160649372946064796764756251284036703521851065427172085011598154374858106257477054034049690307574700876194576753048475242472071051384544187235302865991596395901667453599382886279428660852987448092730327814,-12178152192814077151051956033210165813331619111090720689608458837738277955478946125067643676733373652534546194632007566276305197498317660468910084573634326652156582085984031315753626693903214933704476608819110626280721237157346811918265527840918335083118991187163668918374733603234110068582400025069332861471,264256662843741154538126874284653325441730644362235064492791411891511464369737085603945845443869261733906715033378896197504349395743395072323232105722154314007209047495860245950090828739984743068229024820070744102308175917924790982043751500738655732108120833669083027766207125418432774798887679934336031211189
100097767925729329322181122349613179670027446504792908817095637890752573498574361347439148152051968207056866825997618536117991814714859714673883034645066867063812091504212589938420469209673745687587262010655197327448038749016704401923718318821311108473542621283106029369259039074767836862058509435455755610726,-100049042457569505632055807384899059068938967940837318894350268996535213352709148936435708901083176589583550587767198440304487034715449239754368855557475044885723026390661018171437823688972174609609018769743817618355306963644565862125983532960059011062792908538954329635940471395263688377520252608542030523093,101825233069512741038457795802309532831632092007485080725676678162290037786417230184436300741781748657320031840082727976574819880666874823641143033563613526015930298529985774382970686476257558271965201142223855170907771875249088691707619925926120372987467772228909661019762594761741996613700919454999805975044|100097767925729329322181122349613179670027446504792908817095637890752573498574361347439148152051968207056866825997618536117991814714859714673883034645066867063812091504212589938420469209673745687587262010655197327448038749016704401923718318821311108473542621283106029369259039074767836862058509435455755610726,-100049042457569505632055807384899059068938967940837318894350268996535213352709148936435708901083176589583550587767198440304487034715449239754368855557475044885723026390661018171437823688972174609609018769743817618355306963644565862125983532960059011062792908538954329635940471395263688377520252608542030523093,101825233069512741038457795802309532831632092007485080725676678162290037786417230184436300741781748657320031840082727976574819880666874823641143033563613526015930298529985774382970686476257558271965201142223855170907771875249088691707619925926120372987467772228909661019762594761741996613700919454999805975044|84308318710770953640248175476462028139373764391035194691231680218526343685551415536853656437464155941615590227223191821309564306137129412203074445224501367988293836354108333795252385654176431244360276218862523025987282479232565449230085787098609814824691928891608841637881937218976744434331438048491668714172,78229471895771291032128733343240907956513700512674961776679342047382405281968278678548353708794851883965121941126776164617402656831058062037098035411278996202926380143407188337949264849125051865072631849969234447888440699755954052452126159543200468837557873802507174337535425627611660644229281086936050355075,109360363649395746265656497473367613906192696966623732296103764282264963662145240362278977792876351026988778202744708027814748063715992412060773465595050876884872367497101878287000352814221891140816680001766329736587915177644869655423120132329944663172310205372239088325795595410385678741576083941746461375629
1000990088197024747059083499592558231720263720277516776155079181049136503434198702340667607714363713879340855424897665647049377714485771691188931707633550660945052279457196551479047254741496420585602556120439906566870228385196796680534214981451257503126475671546702014976009092407415021171352670275245814728,725466386677782932169006961452587026457506864587404408874444216403861787891316322821563900402539391905854377725716394516795127638578550566829765062852138101610829715414344025748861390095121907615243675775588453320217679236986850051456109259336757301010447881360582473998540771452509411313781955577190588933,5517508390471385461294072894661016222336566054567430728481305159339660984012399389945095200514405410813099792232460346983221900276173777626934161693012967410321899909279792957271372152068664807744591895618427921351514391226515490690862669088614356482368865242803422288159831017511240290921861425877221350767081|1000990088197024747059083499592558231720263720277516776155079181049136503434198702340667607714363713879340855424897665647049377714485771691188931707633550660945052279457196551479047254741496420585602556120439906566870228385196796680534214981451257503126475671546702014976009092407415021171352670275245814728,725466386677782932169006961452587026457506864587404408874444216403861787891316322821563900402539391905854377725716394516795127638578550566829765062852138101610829715414344025748861390095121907615243675775588453320217679236986850051456109259336757301010447881360582473998540771452509411313781955577190588933,5517508390471385461294072894661016222336566054567430728481305159339660984012399389945095200514405410813099792232460346983221900276173777626934161693012967410321899909279792957271372152068664807744591895618427921351514391226515490690862669088614356482368865242803422288159831017511240290921861425877221350767081|46386382398471210654004936862977280764038033260370855702299152174715903684807635787033726061221737095817373565974565953991423132816014499962739297327315390959305555345973541148973281098200177613839273688191655843120140926599099288046020383471244522466342336148402764983519506510433171993666037668400990623062,30909786208868059159308250284546387617592958673051467586322533557805038169619650467442753505158926723729781335720702109207080121759415266351938588413071223894526233303271669156163543157906212613065654926067039001367294657463422342698879421926602847752406836893005886958919719183994605725308548242138957881171,124210879529497457542798731661855988692615123385567383434289407838970666113795793650595394981286850762118704131523110658152541154934468138859842609878663166338576053338898592108554591614195107201143517584467526852469899754023757894264352510613574752993978429183938806214485060920755151052534935466538850750938
10010004064090651409010594639848304417245586560948860214310742766846249258119176243618948796060231286565945627267454791543296430719743208401586187196864109595450365240377376347430379493062158659135705093920261708675191488141331016387425285934969492844933812420736541635790559026628543841128935951718908539896,-1498575286639922441240963650822632036400568058110825911189335188996116649771598943688044499782411654295552472829397529434461014441578505662359180553723401992140786537396607735356416120600823531080136067285152784381639454281243980298334520221160338176676576774798710776186339169032737324810281860916038070823,768468744922072210410085870438045813460934852024069843981629956982064663744441536899640311347039303574749086761908444837858696612124820590763553776868490058405671131188766507451909827840059264627966884129949211264617246300058675643121776631374263858887287691658300066890342985411108805960696775940061827501049|10010004064090651409010594639848304417245586560948860214310742766846249258119176243618948796060231286565945627267454791543296430719743208401586187196864109595450365240377376347430379493062158659135705093920261708675191488141331016387425285934969492844933812420736541635790559026628543841128935951718908539896,-1498575286639922441240963650822632036400568058110825911189335188996116649771598943688044499782411654295552472829397529434461014441578505662359180553723401992140786537396607735356416120600823531080136067285152784381639454281243980298334520221160338176676576774798710776186339169032737324810281860916038070823,768468744922072210410085870438045813460934852024069843981629956982064663744441536899640311347039303574749086761908444837858696612124820590763553776868490058405671131188766507451909827840059264627966884129949211264617246300058675643121776631374263858887287691658300066890342985411108805960696775940061827501049|28314042997988233306636589016992476577770908296597830278146083272521268550372497996517202454826620755010065709821222609305573779332296860088326682557505516615132304908709189030516196077907461669993069872444768482204126654812645619744037494119483770734571472757955818228427379193994724836630122637837874512512,-3910830326710790111629753186982470489266159472894461132493344186147852161393575078274643639038642275689976708947162470525418556533103511874282953768387384089989557162835543128542264012421515524615699954054931189762734554550136613958599656445264920707571157499612722532218838749658906057952745224391208374423,271795782638036641105135359411824479015439355083041167763715963674151201738370794758665358014925962658456682314365819593590637317922383444961883165716906142863933218099402568928834160919844733051508148071302780085990761872080854429570287769745420760134784589649743625063761926379339662449726354233483569572692
10010469709639397131321593392335940518221591944212653476848636010049901173327189141010003266402662587851391795365145565853592244249890218572600240492819519129624586319882991468883851157495158734614747790710618700576914513912845835699748008363226744953360119054075282875557290214809856164142199477757165509164,7505657900398833324827399204281082596119737445028635348485466721806081208043020690125518041418692182505619967598743043368451311836537618411006688337064144530591029793349206581566058245087905481171249541532084530428115422022022771262499445387394812364092046818720427959757560293344117843608115308687123143421,553113242511887630245562923692119334560619363555162251614925548023827683747558857060226873484593892808999168052131745589052836855443167606888604202950573221560622773360660465500305832700518144444548624823481416168401044677399877530532448619602616847965589554700283201541685397541240490155576228110029131773379|63201743899616470908035016615759783248572310773988939570648682086965508954735585744990615463863202134213890574490859916770336808958389758836363215334497075053557112818568576204445815232807749791417195377923291221271056534552496867547808556556792554364734430966783089440150789750091730879530896624414277659061,-55856955103087382729788364385235549210397677016869607285896429414455503436682728351867754944498329815149524455764192011560832811681933262606199210273482312024649522293283703849873542800068494104680666316436079341962770915103078184937312059708038123793720277348890693601123206211567358221715195838805665244815,99725721230004762208212433032530958477513183167215245049998941633413237167002350956483975841846292547322289722635488222088283425749457741260773683563042470151127137265045721725293085765918300826804733069413639039496778512157339321750973991239393851776816288547058721349853339439566413417882881431596395398482|10058483900212848371336105395105034597443877759659095074874545915088017898536154919284167493951088960283199509655255215299440632845548287448716500241460028925186589031890037337660582657444623147488470508614291087038125788600526809670994940639159256871538287711131658514500837340353796975836990505301624273881,-157799394991431658935500911446539445587307591494655221580870826914115793039596841571933100144135016253304167518063315606333327146563644719359095984750603598277704663545389186967829006269785943764149594510946914419779083189746476236548753466257639182993421200334901817261951648692278188884421732061466347929,549073390680838282030926276806663190640362547475399531148862958328951733805907419890212210186161292258493318221366553074237370828617692229205217240695895636477792753409007387702564155250318872755670718485591591748806803837858464359711143468897253705933551825195496604931204015549587680036788025676123194339726
10010496751485016737255498721953568674323163915462879922384146496780957659766649785727318078913117215770623612059774196084160730194502430474210832948012098222392905483059314666266093994762308130821733627116456649448335020123456572070799012785074345756980230844151670979497392292798505519219012749959532875338,799688122820510610823764584829566759424107985411345815493636913295490164723810636027858758547620320075665083037412723404618585417481351642215686069179403481765070501469154817238059870792625025657772680475594951623612932084444307492923899340395814785386177783715246947669812896758158101579611206283404125383,756465676775987727565397432418408198121332665761199779426305954315978948084770158074763521327096161584122642931162604561074895576932338265005852611804594502809713943064130145585384616864112057298562543101439879468994210857521510834193578678095039312141817959445372442666042645305218271194929494814070515333525|10010496751485016737255498721953568674323163915462879922384146496780957659766649785727318078913117215770623612059774196084160730194502430474210832948012098222392905483059314666266093994762308130821733627116456649448335020123456572070799012785074345756980230844151670979497392292798505519219012749959532875338,799688122820510610823764584829566759424107985411345815493636913295490164723810636027858758547620320075665083037412723404618585417481351642215686069179403481765070501469154817238059870792625025657772680475594951623612932084444307492923899340395814785386177783715246947669812896758158101579611206283404125383,756465676775987727565397432418408198121332665761199779426305954315978948084770158074763521327096161584122642931162604561074895576932338265005852611804594502809713943064130145585384616864112057298562543101439879468994210857521510834193578678095039312141817959445372442666042645305218271194929494814070515333525|88526457805417802579401128655636200680578875592064917653502726799402631022732331707242469404309708934422669188417199074013672835521067841289769648786519913947468121765630841991231363845393790849492596901524640146832343923907202043034825750225542103503647484110551329413090031876302117118017242617457435270440,-55270872554503717308092985383981103433537850547649491053003970562528650386510337748001788465211336165026556518877922750831164872435215600571701093825986357449663403092607944719717658773706993903771608486872517959780200593880280040497747294339054563275578214457748886755324708980839180036767067720944832209613,94165686390158171873356770999242344439144784888928297429784348143756989501060133555039087406934644294830253094462126060631940792293289142829036758298101067851753964448066092115935075783351846337421975097419550731994478824011482838934049698582968608287926659413694080435137971696387627102349753238458722293238
10010579112627452164700751672418124874438960016155391309411143579238371993812216949415371161492459719515415809121706298625750585115724165801767312632070537335293199529430577590690991572481217905708780746070115008642386973910356482808275744430781549387996153714070117005169542728240082244119738613459581149403,2350957735421970008675187616979703886327431020247822920032684793437439591770682963150195069182216167082120247951141628182676139493494439884424368912802413855370850694844333281369444099710260137140856858089878674493931790511953123605380418199403899915269505474711266010465371671818915910810005642457030207323,611423654589890839284741885001129722618409625326976389817674733477626186444470464645132913394627656053210319902647997769502456733804852681598112059600692683589494771437615834703370743285630660946188840487388799145726650756609808617614030574039934664771328233896579676781994740365464050319193605788676121096976|10010579112627452164700751672418124874438960016155391309411143579238371993812216949415371161492459719515415809121706298625750585115724165801767312632070537335293199529430577590690991572481217905708780746070115008642386973910356482808275744430781549387996153714070117005169542728240082244119738613459581149403,2350957735421970008675187616979703886327431020247822920032684793437439591770682963150195069182216167082120247951141628182676139493494439884424368912802413855370850694844333281369444099710260137140856858089878674493931790511953123605380418199403899915269505474711266010465371671818915910810005642457030207323,611423654589890839284741885001129722618409625326976389817674733477626186444470464645132913394627656053210319902647997769502456733804852681598112059600692683589494771437615834703370743285630660946188840487388799145726650756609808617614030574039934664771328233896579676781994740365464050319193605788676121096976|8039922802491265414309990967793279613501148402448480465019122506003939256870540144853780285033203931808455458595860030453208550342558408097242925918803433428637982781245121194507511100106884732787332881816376538778408183713312626895063525916116529477067428617194552870724443468826009500481151973572267660629,7782542056885878734681190877592906346631460224605439140627247356888850052165135682978538906914658013311431434956582299659243906965976772069489496351182726287233109256230929112390639759813836413367620416284403736856845659506160807594525033721234682734219240024280033734701579761670420320393555156688458386939,763000498381829086301710784279931419423976764939217073711509076091719761279556145759370750276614372372724227557071534934449510558501017918011817000937860419860520748646784487080323157808376840620794576624474012291138723116851111311356377966880000941424814810860193927148425226557672422373368027666445875216544
10011186832308679529580531778689417394449477080570215256255872899524060756354513251052234139190381882237674326102549194541918465150411281044342531791718191209528218579215954684479017629118919205540336463087633388203942961094184672710469514635568862008937176486425382826532999400454876885123467677882356280867,-9760739041412831860016040329300538464595968662597654195818825742388623357499061055114241473465244979572894681398742727120008689894660036669893911021076723092236596538937507422477033501397620347314916527511417876669224922540378674704881346598392965888769411037021701309263621236037226524490335501235413158317,618797456627391285757491837806082074086781183030320963821992656495001963414332567515207750538267219197978733813073360730643354769504354220428586481088489050423524166052003546758616279336334294024003134192912678054276268653141558092399335706944717740861723542047714673114465932057975066598256237991004833528194|10011186832308679529580531778689417394449477080570215256255872899524060756354513251052234139190381882237674326102549194541918465150411281044342531791718191209528218579215954684479017629118919205540336463087633388203942961094184672710469514635568862008937176486425382826532999400454876885123467677882356280867,-9760739041412831860016040329300538464595968662597654195818825742388623357499061055114241473465244979572894681398742727120008689894660036669893911021076723092236596538937507422477033501397620347314916527511417876669224922540378674704881346598392965888769411037021701309263621236037226524490335501235413158317,618797456627391285757491837806082074086781183030320963821992656495001963414332567515207750538267219197978733813073360730643354769504354220428586481088489050423524166052003546758616279336334294024003134192912678054276268653141558092399335706944717740861723542047714673114465932057975066598256237991004833528194|16023810805641333724336357094511552886496985977223317205804900540875359074549841799895438359675279197334185032768159914670757201278192258514539721858337894442748764924011517017369466984819970583389409069776399176053947560735257602992978470081403520015409641979689232868403667818818613535419071872687266278871,-7532673756475565262302348084703438182578166716950696747316478761861175843795966574151023129542515752521204794815061142348575304950316771972303577053107419061405627955596801577300288807854600908796497666677601605740930719732644371749303298593761133443055158847238113190613766743442416892398264321417028494683,386004572289283022539377207289773679498488550299986782511093221618938108821853499898482934516175608928422720022347987369229961237741779367136076661442684969604660313702194515039707016073494920297591526290529740277402244949703587380758181579357976708139982649833967127198595634906215849970601175752843362414638
10011352260197967961196723001882777157351136553686255118590538903088960848511094106778638364952379274889738636611531352467905470187088001978395724543759615578178012440339389212117360666565610883522821465968556183822388268042856072812425704980952391373927012924156734141733616109526841203308615171993851798580,-7221676671346271775547094631755878098073875121922187404285664906337078018452572717764275630077273635227060270555255283560769931807823554231983067592327106941484374528295871153247243771907559825959222732921231505238074239141672724791953035282099263068621712554135551648164407808630494744659356436708196075003,491103641942430897255353076452858177434280940975186423223949785500010643311551520732003340225232164561507795653594281473147298622615199173589020255105363616020518202959139902358320338695214760426102498591057589117988289772846024859991303086757574971564242450863802854515962057480781826855732055129393601722620|10011352260197967961196723001882777157351136553686255118590538903088960848511094106778638364952379274889738636611531352467905470187088001978395724543759615578178012440339389212117360666565610883522821465968556183822388268042856072812425704980952391373927012924156734141733616109526841203308615171993851798580,-7221676671346271775547094631755878098073875121922187404285664906337078018452572717764275630077273635227060270555255283560769931807823554231983067592327106941484374528295871153247243771907559825959222732921231505238074239141672724791953035282099263068621712554135551648164407808630494744659356436708196075003,491103641942430897255353076452858177434280940975186423223949785500010643311551520732003340225232164561507795653594281473147298622615199173589020255105363616020518202959139902358320338695214760426102498591057589117988289772846024859991303086757574971564242450863802854515962057480781826855732055129393601722620|47792242549528045573835222090102709180753366247917233792162207697772127315858077638348932444421521322861739464396186442116808539325522348191328660258855448870212049194866543072912231226457359914737534217070905308248553545640574239424386722275092722710319161088562287826715987711727881278079923845948791676890,8254269885969125051120540706292376386106399376632912551223385556280906209369492834220174830708813086153383708455555132979546664334186800724505969898808175578003259356450761612161617233904190263463404177018953974392386560633539661122851396041321655235390273818809845177966554527106703090511634271703426366333,102958270685953367083211535309354861429334576908033521565612066728144639011805671376037609804664223083707360606267980895711740633481159521495849279040716328723662579233841335201356070651023351445332747117601073346257424542725915546556026838056238556081287286460939074972020327613774707117438966240554700925838
10011859648773232442448733215609838143695842496672408041181163963731715385957428830906426802116840506850796500226397482148532808790741216756533590408501689411024510944680051255986998627975919616236379312627952364824369227089618523233361113970064976301643797723660966748317498805671195280559795030489377669812,1389268097793948084201915587623858469968349389719030883277892933626050552994624565080658001697742466760286196070343106937791393185285082388402785127475337008454634105961822228566730985518119778298380464943436464040236734762976514693785454254940058632017513195975469702286256915116671279121716893380760195997,798259439380551890168577021365722645610234093426080631569938818141778075039283575889046619146360005141391892307832892070793699590106322160142086889812498495186005607708401945977916695847229243650515563078729723204186390753029064543583093290363210178756937751032079469629502953157831010865389293997646642560816|10011859648773232442448733215609838143695842496672408041181163963731715385957428830906426802116840506850796500226397482148532808790741216756533590408501689411024510944680051255986998627975919616236379312627952364824369227089618523233361113970064976301643797723660966748317498805671195280559795030489377669812,1389268097793948084201915587623858469968349389719030883277892933626050552994624565080658001697742466760286196070343106937791393185285082388402785127475337008454634105961822228566730985518119778298380464943436464040236734762976514693785454254940058632017513195975469702286256915116671279121716893380760195997,798259439380551890168577021365722645610234093426080631569938818141778075039283575889046619146360005141391892307832892070793699590106322160142086889812498495186005607708401945977916695847229243650515563078729723204186390753029064543583093290363210178756937751032079469629502953157831010865389293997646642560816|42206894030530619844844137895190664968269730414499521872109243265156383878372533066719066634351278056931106119952256575854241753055519807843572490047146976978089248439736200704784039417511594978273239033477711961360762067155137236184651290217781497985287933853456015958183471535758824703982061917287661765041,40970642478148233733033585114396071242748464687693709425944631778683899124773146938566992970029345645063087493796799166205427214444613129772321140093187953348169602638764727669726146858903079780374349625954437240902856681427277267635228715453381995681831199770224812459964590952867744306421769761996026104513,199285626990423651406783664663645910990492228214328517061400776387771491511391310851645339521126305819574623301901411324234792418046438608476979083398394165188934652648732128312553721596148859379616564443828216278968549632096439205379175627317399435861673444161870109940456991316291287290279435962880377080302
10011942112859072995258791154733863477789940396938883213028206575320538554823437297402241742896497695874369416027516907850508925314968512498072222974096801648178807861791486753853486254133021354211722209138812867027895370716192265840613761606054294753819681190630045043947858812851889188252918713433862450937,-5571668968866828804921046721301654575883923332633233994134906673281267773210784380932788963105885600448276206900049033963090555880641132208787100277713410661373854250945949489885604664165828601242508315193830303811886340805084372525080806602568264342555171074951419758002241352180046540480238252242954050299,447717522759824444351173111605711384841786993787566688069178368722388364402515540644758414533643421974927299526439953604872416797996604293432960735663438930460329264500528581210531189312463600150764233828882749159851806734992346380036786298515789780808132282396713107095426662454069422796780131140784450873310|10011942112859072995258791154733863477789940396938883213028206575320538554823437297402241742896497695874369416027516907850508925314968512498072222974096801648178807861791486753853486254133021354211722209138812867027895370716192265840613761606054294753819681190630045043947858812851889188252918713433862450937,-5571668968866828804921046721301654575883923332633233994134906673281267773210784380932788963105885600448276206900049033963090555880641132208787100277713410661373854250945949489885604664165828601242508315193830303811886340805084372525080806602568264342555171074951419758002241352180046540480238252242954050299,447717522759824444351173111605711384841786993787566688069178368722388364402515540644758414533643421974927299526439953604872416797996604293432960735663438930460329264500528581210531189312463600150764233828882749159851806734992346380036786298515789780808132282396713107095426662454069422796780131140784450873310|27084975518223203685159476564968667757147005650320881882446538924664746760650597697153771281773275150298344920435750377585362202361041033907635631944580948271756519774659017735803323446011519248098440794538345241902148398434473456015090213973679829939390143526742895252747749904765235510343943624603085395760,-12790519385524034711380512698893130061457017090294213212099271214034680483663421242204264773620969593678221374876014811278470247764306480672296083402927981473695204988274213121345880281894543363725179804965957322222445321774678314607579703404237389600553993220560492758375020231080071561518133534954466259951,166721966963161057002408800656254458745347212698279982813080522419206471402712564010508086006697422863841361930966373632778322663543126671570353059325275245779405843551444614505569300692917404907917428765459530333591345110277642064762234238705296425159456946404870175457906061825086330206230526422507612458697
10011955414042796957539613462833567748978021174979466353940011258968857683495843510716962870026112990120612239420094468274757074371715099897797764809018818677244411173050607051965491060861928470702220861911485527125770697960299381766502895029523905888655809759985815187019718331529320273577105879315557816044,-2903598288233181369386909069725761325455718972241715705067575929894098338713960225913955377920698582104810776546675110854231130224088963639880575858411672466883767586627134811452446768341259728766799505769981364639560814489840847334997666650046443822662727211952763808116443820225341403833059567092278686013,716711840847237503666263684416016435149389642949031161572660687058464860752744538837256522716160171257335781518708196625364621151126528577774399883526209845714231475374012476325785739496418344991482641972669482173664514234171584896006659617692101904655946713038460582513645370686741753929246439907983936752037|10011955414042796957539613462833567748978021174979466353940011258968857683495843510716962870026112990120612239420094468274757074371715099897797764809018818677244411173050607051965491060861928470702220861911485527125770697960299381766502895029523905888655809759985815187019718331529320273577105879315557816044,-2903598288233181369386909069725761325455718972241715705067575929894098338713960225913955377920698582104810776546675110854231130224088963639880575858411672466883767586627134811452446768341259728766799505769981364639560814489840847334997666650046443822662727211952763808116443820225341403833059567092278686013,716711840847237503666263684416016435149389642949031161572660687058464860752744538837256522716160171257335781518708196625364621151126528577774399883526209845714231475374012476325785739496418344991482641972669482173664514234171584896006659617692101904655946713038460582513645370686741753929246439907983936752037|83377818300427508414411209474182765418541299931790991979162498055814470115047955070666996621536705209820738216257135146862349180486198221400982101436215575798938096836021071281557720129695222554778979084677391347787960453403954349664348198928269790759939576077051077722913333980873848885097124565249932890109,-30688215255611971606034471669429848439589330363616017559694024730487742561639314516549592500671986661135255749032859202031979689977991786343363266117721953715761747898795102634113940122259396542403236218273245556434610755838474462460273735366438965428724794482250645649141152999575795556913839603294733616297,88860815315671630897460232604076507207530961201107386907073059232104245557771716637121266612833291311086440284416177092484049670682110328081485080434205469417936503447466464463362446293805166057694349242947508206617775986775538756539497474332372390720218420029346868304694279430904189373022716924576015411382
10012228673376152026567450992902390970336864997567041834794435762949115261281228493411090141625349816927161690458296667158108080969724709444972658280448694411038715631967371509920701285876643071095813601274276803568595952200658716678278724478871970783503276566469041579910541903097002012017970816393023705126,-1525621196152714906745704861653134857598506051934926836340086172347518826544771422485438019089512861580045344082067612865732790885320087313117232977161635917848068594652072218066650842997301426696286712170439049522381084448274527064469835335059461198790200539335886996343589558210546809155519571241608841115,566490489998797306378193876913958339109032806676495000099448643263727848667893470101258216128095777975779077696408017781065855401798377205019264716443061687881268372472869438487229092017706767156974596159933038800310353717032995999433855144018018195220506116678554717313645342356609548972497509792111447080303|10012228673376152026567450992902390970336864997567041834794435762949115261281228493411090141625349816927161690458296667158108080969724709444972658280448694411038715631967371509920701285876643071095813601274276803568595952200658716678278724478871970783503276566469041579910541903097002012017970816393023705126,-1525621196152714906745704861653134857598506051934926836340086172347518826544771422485438019089512861580045344082067612865732790885320087313117232977161635917848068594652072218066650842997301426696286712170439049522381084448274527064469835335059461198790200539335886996343589558210546809155519571241608841115,566490489998797306378193876913958339109032806676495000099448643263727848667893470101258216128095777975779077696408017781065855401798377205019264716443061687881268372472869438487229092017706767156974596159933038800310353717032995999433855144018018195220506116678554717313645342356609548972497509792111447080303|43590031232680232081751882157307176889837208488946678228473969287186808910765585247541543237267000539198165783309913805801898560564494504170518670105700488271939383325260531063287350050801106407955825720824399992214830540252117419097263989404727460007269455161541372200543947623309137659512638261713267690824,-14075226919726761245118463757100097494169008867441262054574698130139530299753414803053777844415814847468435199262862690860015506966052100586678181635131495519430715844772863497248903106204345001653326109572317033217334530762155783910231739525445183612742122146838723561339801552140211476495875670393868085081,131240521940112916676543723913094551994900810880147949771730918304609983182487804507629012504949522364314455047343021279573082629269863237002108329413796491307563278912051552679953053070493799302202693873331428377723854674840449409246578209307981263784655485960382622975619701504230119584672038533695429676088
1001288292714450803721216442216625955625371798611921786124245018047248562264647981975960215285171753909781321204807230585425114478278803844011930274438946371170816602064333453376960652483578633927890649034364140705267107257789492504807548712851379509812488664968862197781823935761608178854275129769647589581,118977223991225808492576983063622698908224268079465629025347336989392083161221074952362214752172730464574518166801398443928377167452950936101606770394549907364810511870992758058622270316795961219734709916323416843582267371642230512848102350867740488489154654911017481701711273952134350507762249130961129603,4253782247854217005640367062054391551273020323289717198551116404593406680781947315659948108589518702797872582317228254446273819182123102223859859093093126618316964313793208051942159218633324159151062222504543999694994085787779078206117679218461273671966899590739444942724001001618068559652898782396232628519674|1001288292714450803721216442216625955625371798611921786124245018047248562264647981975960215285171753909781321204807230585425114478278803844011930274438946371170816602064333453376960652483578633927890649034364140705267107257789492504807548712851379509812488664968862197781823935761608178854275129769647589581,118977223991225808492576983063622698908224268079465629025347336989392083161221074952362214752172730464574518166801398443928377167452950936101606770394549907364810511870992758058622270316795961219734709916323416843582267371642230512848102350867740488489154654911017481701711273952134350507762249130961129603,4253782247854217005640367062054391551273020323289717198551116404593406680781947315659948108589518702797872582317228254446273819182123102223859859093093126618316964313793208051942159218633324159151062222504543999694994085787779078206117679218461273671966899590739444942724001001618068559652898782396232628519674|28938807607695569686193558386017186559599585089880944105080644798657187851944851177349121001670507484268388813019981112914318210410185959709469975835597908447130200721022330232315439534240435891776843814205222365393996713243986623555128903274366840091822641672516816965782305494688964249039137567600077936606,24347068586442893587653361936682544233359974224524919385561963293036974216353969467745312829316424149479715944098504674533950906586338239024243122404600846692591968993298391467756407074710363297328032595080001517924404972784909440292445668484007116372818768610926770836254572445727057593300358575616247842763,152302535148483948223815371530668367432578267200771233287129083802472440010529096619024512937585549897229409792244544585546299937914900082139679373959823145377421946865824314455823557999559223736926801877211472988708620154393053288483777738533792797643686229459318486035573754517579909390578108894692032268889
10012892006475941528884203206760641995368133321794055404979199342382084602756352644705532078779012887564604213637869579074484075768567055417796954674356138026767547529561933792018043105730958440781327057508393480700527196787164950646236383499370902496883935791129999602941562207002549251300455418372635519273,1454009605238489140114391427335527519147008275556174452371701295849315335234637169205945347453687617440824028465168238395128115858746597274081455839498538752590048744221995446875637484166488769782049750872805524958169087781809205120801537577068712904423342748390795604976651954642488089689583155223913397665,647808943230731060739626381975524675037163647891128462337945233305926315404323308376753006196333731632781667393569616294591379982170007646969372304454389485880137478967587874806562743050788204733473153064889810620961745850926397404102543921057382519028198560438333275110757811110797391594327323261044640054976|10012892006475941528884203206760641995368133321794055404979199342382084602756352644705532078779012887564604213637869579074484075768567055417796954674356138026767547529561933792018043105730958440781327057508393480700527196787164950646236383499370902496883935791129999602941562207002549251300455418372635519273,1454009605238489140114391427335527519147008275556174452371701295849315335234637169205945347453687617440824028465168238395128115858746597274081455839498538752590048744221995446875637484166488769782049750872805524958169087781809205120801537577068712904423342748390795604976651954642488089689583155223913397665,647808943230731060739626381975524675037163647891128462337945233305926315404323308376753006196333731632781667393569616294591379982170007646969372304454389485880137478967587874806562743050788204733473153064889810620961745850926397404102543921057382519028198560438333275110757811110797391594327323261044640054976|62940556237396653206223780718542562667295386352158429493270469961690767724114029222148067827069562399174914339449248246366326268552997433890745884344199015208364859348865726612586847277646257664344896903583225600388420348724002194132332892190932637136851080726053181726410409254132012307744554948406613929323,-48701511676436282890206508014619418354003032902027055232648782348677470406094053907961181547187251236573045647699655583258566497581891423764342023041779904338115306722370857935574573523817812044494597510209680776289279513137149479122384803569185846747971729826779306714510975413862168549755168167117700353327,112469164343071489234368373987004423456191302343816707379444012274611228263948855290569720261858996544051020707105809245289927202553907369725233852283792575569835413308417689095793467463934173594106404637573580430116767215310604286894257928685108943559541701617509990028119392117707508006024253191362515564488
10012909351086759965456044227627057711408098785482672328633074337493434448564318338609803059310568728348413958910299881715937715018572879175542723270961874435550327968633029584188957768139340259030454592302362749027465867807734115139476094923287105973980458884201581736181829195017361330152871853820144480008,4004735351364710265644908449319598352103612215188460925760295665563484237162745827742855116753659687319941982652183152982522805963387540988424745778802028813186258777373064074552858455437921359277118582292259532327491507456668283228943221341315392967683928177537547570473748486481294902027111753951887811107,625070500924631773027293646808528931297961990338169633089637061010766445639876245993583660254312851352153995204943188734825803541904480394551165674837469282411059121521375161737576421883549419892239480294917943542161102975888315623576549465990742662361177906359742645436834392762941048730926726541953775339985|10012909351086759965456044227627057711408098785482672328633074337493434448564318338609803059310568728348413958910299881715937715018572879175542723270961874435550327968633029584188957768139340259030454592302362749027465867807734115139476094923287105973980458884201581736181829195017361330152871853820144480008,4004735351364710265644908449319598352103612215188460925760295665563484237162745827742855116753659687319941982652183152982522805963387540988424745778802028813186258777373064074552858455437921359277118582292259532327491507456668283228943221341315392967683928177537547570473748486481294902027111753951887811107,625070500924631773027293646808528931297961990338169633089637061010766445639876245993583660254312851352153995204943188734825803541904480394551165674837469282411059121521375161737576421883549419892239480294917943542161102975888315623576549465990742662361177906359742645436834392762941048730926726541953775339985|50884288706475165946257509654999208555658693396648687044835752784386552584102384977309647778026166442592405819250800637374065583324042092667913200394806282864115429746583280943890188029227669788614986056318825797041482189685920834253378958370006347565609320222176974991924753600658153514244660657255122224708,38124750578737274821917753227232162791003089617481557231259566762030985520934492451354616032457170217275564281951330766101660738724598191687885679545346283525262542724874642642872748420737930473130307644519437933305026842012536784886496944579276550709211116316390318564020889816097235068462785319614865578597,130062522389522343683740057432381314776477134408262105090740417520527750971142246152091337403925616258740469387086918783120971977871460574454924803144389152275224257452330149332865693355986252454785361887191345579925263888502541640915087986171712168495464223258466766753612088491549102305993177855419426172515
10012949731508230844521554364973074187572984168621445800774150709798807735949381704091845966274845524513566631062798752350499554699759712145607818652191568463373664709797900265336143905874117568859521742454341137224521191983729963831041097053387797083787709902762145306866562987693831491238763225325353128845,-7151999616242866495807184767334673387014110620932054515899434747323053830494035687486485101495361247552977403879925385683437335608704813457204456533123612810231681288244199329093278043176840326889166441056953674708680650112341950599518566211501622893081961748190383051196092405691509055911825933224776999729,728959856841002416924230811929428724002543698647639902715200337469187398607311841753203087774058534727465005007422722827247541795373827101651083024979629054119806748202357685733330535940416577507509240075110229140018035405816024445205831928017961602089222683008780078758377712656395593651285944681456109357272|78605684766061357400507779695495682929810684632437884872357120089392494231881706222602069457907886449103098011256954019318391632581377073457287658351584831830230683661446071913790640516272177525020187886119102997352695696049059080937602038841787771510139456284931095360062636771451048097974369276252684666749,12001075534855282519055781006726767731199194746822836204491410167536180166431388377323739159072959927587441133024108242424202303987846968293631866746295774320809136575432861690259530718674237632206265488487198601880322884976030897140623633254152458705315742157972429278484090634288310049511931491105240527901,93151749819352486101012886560489221249552002889236789406862251708880381277922290057447780576080950571200028266859881169907512608303652032886801146810143008245384785580165444902988038417617761865310968792125862316413739796643982228185896004498606219961899388723793207292461251691711779811000343374670531988570|95620961524949716684140097524982794699249535271050516669544121744125934159117898820120095869213277316814159636331359612088008309956314498753337898007810553303289522178449103493384329227781778413500531168007453332099452587335790687068580171335323542117871903087433014777736086345342400718427907876478857651725,93982690612240904950679627999951286744516720026289165825378439518867065181987722717690665329424786689958612327347934970490613914683496125042910877240489318265091859294188434182919729530207613831730142844292090902152344156800509267822168626995816691703927249712872762026654985358484494213663737589506902782009,99292425117587212531473852181491241954331600716435740239461638370783102438068248269577051049726048567729703659744591520045688390816935889052570162756642088994924462717034854539966002991020871080627249804440896263676225604896518999268622239261793212314602300584784534836058487675621509713476733501463323785340
10013285697697981291514875192049827757071760177573323421009966878146856227693938310986650067592898605619488251263628358029535725840627847357496217367653253065239804661689467675594407401100934372130923704422822224913415836705341468552018728686468194407664564227575182128302559705354560745061529474614082985076,6561642167054255252332139226189226301150630422474494620863616714017817447379372804603010573956570809208555270847201719676149529315047658055027624866235618098171962008631941847341271231615706090718182990766223922159167490454724094386151343698580819149354278973243680974477529170554988807127882542455236037061,528470097447394031501467541165507900676972213983504375431777006857690508074506764381712795328953309294516807977445847891975262681647237636757123951794958241571326610288116591734368211279530252114133992576937361883752806300690109922381969083425358175983601420535008716582685323406262131690670391327047692590496|10013285697697981291514875192049827757071760177573323421009966878146856227693938310986650067592898605619488251263628358029535725840627847357496217367653253065239804661689467675594407401100934372130923704422822224913415836705341468552018728686468194407664564227575182128302559705354560745061529474614082985076,6561642167054255252332139226189226301150630422474494620863616714017817447379372804603010573956570809208555270847201719676149529315047658055027624866235618098171962008631941847341271231615706090718182990766223922159167490454724094386151343698580819149354278973243680974477529170554988807127882542455236037061,528470097447394031501467541165507900676972213983504375431777006857690508074506764381712795328953309294516807977445847891975262681647237636757123951794958241571326610288116591734368211279530252114133992576937361883752806300690109922381969083425358175983601420535008716582685323406262131690670391327047692590496|34436981724331071994857876336695803178232447897168183469251879445354282383737983320261577504714614276116113259188008664067129808039959751651485877586471601565784430914037035998508212337945584341667506911125463475285113792006322617814372685212577273915390962094210529917778766692621996665878783549527139893242,32421657027122874777191628085590775058881834171831914535958291812982208823927027425208685420460283486647223529499620732980942837410329269106357656112224843439688604221190662744374320594231296457180058248568608247918397639378809724702503728912863511608290047988244839274296444657984762607288102260430546556327,160982437047557923662754621724904101004108273738876884592163845288132647289990060919034667221490978793506721749816537966400403944327808168366534024580437483775879522831741601830069730429889808208871000895202628107312664119771131677027106136972021612902580949354880064038858290748071858588504931122717671875719
10013409568078797146570807857755720961248912529367151061974511181033586582464029378963193763825696350496154303179345126636835517120186897096948192379786846194127995559270109497428813513500508574813803534331316886434340387606885978254975074973425350503976585044856706375756665039166645930515210729176181994797,6863076338634175024934436723026392698236823689304369693969685928390616820215350991816780229964708018996782742906430454861638727991380590099557403163016242141034822837520016392592164770889783961757225608245037212056737255646000577024303400659319142788815209178052443133447533618473993771130005829940742472843,518144219445747450843112374880923475954988909716176430338161904285754222207619744119028881545602958596524518340559183715691125114950676034953086100367357569860971147170398898521979791627387469550508096062409978585338647803044577182942437027156401628087522267601972713267759073787404132654921721043098478369296|10013409568078797146570807857755720961248912529367151061974511181033586582464029378963193763825696350496154303179345126636835517120186897096948192379786846194127995559270109497428813513500508574813803534331316886434340387606885978254975074973425350503976585044856706375756665039166645930515210729176181994797,6863076338634175024934436723026392698236823689304369693969685928390616820215350991816780229964708018996782742906430454861638727991380590099557403163016242141034822837520016392592164770889783961757225608245037212056737255646000577024303400659319142788815209178052443133447533618473993771130005829940742472843,518144219445747450843112374880923475954988909716176430338161904285754222207619744119028881545602958596524518340559183715691125114950676034953086100367357569860971147170398898521979791627387469550508096062409978585338647803044577182942437027156401628087522267601972713267759073787404132654921721043098478369296|29934292569471815703363755226997845073545738667501237803957680847283080542129475423696483417806010171923751057450372494361758724728289501602492090448848706266885172109480272010048281849170055027096272553904872380723830007840644079815126735090510221286243662888112310922242506575820245103502418648518037684112,-21627427564859692871607980544502391995135725746472152647532172629071699503752589147589008201502208786678594136605740253912219755939688067145589663222363251747851181456245722891111913772396992196602024806546104102083185098682262204868868794139167512528524369543939531083241005579818092881356982615423576691605,176839029147532789455522785442738478049409371224700882039503756023790320876676330359714505430586793397649436855899139335082011213013721973064579158662211626800445041202290699798718862085318933995294002499387627536860514923891246937832235709964008507131234282169012371627871115559920941075179401745449676837538
10013439159433989368964725373563382887574891949489700677050044742848904863973460805304293375442411192907083507310299969395983146408589524560833202656559624127327840001867965274370013167539210363322627273718141213894086509619780941576547772641539573210833142422223317097724915074066448586076045470572140906640,8310509330265721057433243761087295977033094222529694041792873186617167079529403730551603568975196878825930300295178836012162497002423788954615523897720318575793014458944774857654309162161287534450951840479782552544416928129945375223479302487034431413802055998746646446418560576461091628250104710978988283711,729371463016273963110544177662324936807730201765611306002068268068668637824971025044896789932884019488152669624502699796991126775679816762002628560217169359562928488795097209366461843162752726085374841269043547767926070040941464791696126630730708190840765048657149163857767697743125679328771823496672841634424|53070231924347082568804835060631378289496498123832644772276016787246416299549861270518581840230464146779761127524498364504195386387182521904349896158340177993161553682765729098600652803891496382298875979768509788803608935382898072295003870146958848103249920622300892108001270267505518700281027764636096833740,-10417045904363157434661773205739749791733323923523249180794936274249482583161962687848890485454386657190132561052636607343240275768181642068289523597327390757351630390400726183726689859598985450769013120294233573698641240921187000189001584616004996169093549349734180954432033587699679729849675222478884233311,137805678896928752296520072917407826444192224958002583188528402832110905130383122933446618731410797305667977506853537200263986333845054038041545138300862253525372279908216585177453144947870717454801757363277754721032068341587435554423804921498405475740879440309992782986462772299747827377706986933475774033684|56482649708459145913698445611252485312060512622120077359133908474066254680736347932747096146010188731146496181655662751016088725094095969432429720148408144169456178462601187248728823790080612841522193324466093276526908124707660336237710411213793152471895601301243018110500181075901054216803639852864737028850,49500528206529841911957152384541310290857923328806104231198472543790151686945922117895513040239668591093558926952515368216015961042415506812499837082111798870583213244606704215667322437109994138978691823955863634369767001231824513186587618556524171225612093890634215231765102523588484540352521700864775908391,139845177982276960575270039101197150993163035851524438788484301872591911839811648314287998492505051870128263318114638169162126726205946284015475459749582002542133038527256092765477445685371965587948783428628744556595668607565825917211361759008178572918967281201176709071648799305995083323084664578756735938622
100137176306265990029733961444031383061223366889811053704411233166327830634077756142922727010656909223245031237249254709133350667800868491437148280477941194204587700926281351055456250199609042270725753605165960788792303060065875576152280599302149022622498012279559937562935558359151996671916418735428920407874,97779166460841276445850871197751897473918068054418745266060401791237288238653436085640513289818870139139618919771865928628062692360137571273452019987828179736062700190532592747648476510214800565987627353502647292543809222510700867942163153624606570877663088964161374448935565221244874684751958995844140920147,102256681515788126438883260779614224655986266663397201843001234522477597459794964756711032437403434184534404583233460968937962164574558546102488980641209149336930446800149993628815025349402768080588150480797996340762754608056907877670259116917971852689279794852877026737551375891068290636218096081379871615065|100137176306265990029733961444031383061223366889811053704411233166327830634077756142922727010656909223245031237249254709133350667800868491437148280477941194204587700926281351055456250199609042270725753605165960788792303060065875576152280599302149022622498012279559937562935558359151996671916418735428920407874,97779166460841276445850871197751897473918068054418745266060401791237288238653436085640513289818870139139618919771865928628062692360137571273452019987828179736062700190532592747648476510214800565987627353502647292543809222510700867942163153624606570877663088964161374448935565221244874684751958995844140920147,102256681515788126438883260779614224655986266663397201843001234522477597459794964756711032437403434184534404583233460968937962164574558546102488980641209149336930446800149993628815025349402768080588150480797996340762754608056907877670259116917971852689279794852877026737551375891068290636218096081379871615065|90230316563580194408667213300439360765549943827123723976699582813489678898952655680387614045807099591452452020884059027873359796950334151880947386773848115789736943898016681027189561282963394481712553688761042044178529870890932063063291912576811880180339151930033798900788177324802354824840693823677567948727,-51250096968515553727207440971544562384114008768089106206247467547899665759345213630706768471270630937078525436219387041016063211534659780348494492859921683763678230787094584046438254568966852960609578580031708027705688875405694260795850267621602038107210044773776590144869507841095128986805399917716889737097,94271497992835932562874103278757400032116756041765039747726332995183554964390204442288393334665236335700063020174534799860251424117225874828741908247259400897208844068836969114844343301370484015148786737029807531127609578040269356203181806490127049090765570457173053771731322678344641402857532580837050951380
1001395889265586485395767421092943095772484906688205160639025138850588355434167443569518670890639224060287615982046173119211466447418875356487968111638376610456681184419174307282534045999642719677458693603373061246804412063778941537663208494251233702824916937867260454282227810431834716831538058300952240529,60445540632407873888807630431208524230030823670563578058253542014522089940657440267941912297376844686920437735513309169811551129412183931683096248710036617268265519243947751270645191479229689326385715524956466565650374324873653293511970021452999675894489762841364719216977754928108945414058693987652866277,5401452543992462314517473547060846830682300053665170002473827326781788915141651047957910827411217522592705590143110487190395657380723574363184777022159851917393607961064987992588915644654812213550360705959643031621136573608890274219923270810168453305278905475435769643968988593393956330128341342800859836282482|1001395889265586485395767421092943095772484906688205160639025138850588355434167443569518670890639224060287615982046173119211466447418875356487968111638376610456681184419174307282534045999642719677458693603373061246804412063778941537663208494251233702824916937867260454282227810431834716831538058300952240529,60445540632407873888807630431208524230030823670563578058253542014522089940657440267941912297376844686920437735513309169811551129412183931683096248710036617268265519243947751270645191479229689326385715524956466565650374324873653293511970021452999675894489762841364719216977754928108945414058693987652866277,5401452543992462314517473547060846830682300053665170002473827326781788915141651047957910827411217522592705590143110487190395657380723574363184777022159851917393607961064987992588915644654812213550360705959643031621136573608890274219923270810168453305278905475435769643968988593393956330128341342800859836282482|43569972642791160005757596858255828258440677425601503825448806514649923603624018287716685991744061240705340542732331922577472226472918231509238166036331218027449035406029770845535194662631393899654058445399116462950394778843477054303490660149914576382156352231393154632904722395547296167018467287872528029256,-25416175075838450919641769013264410597729745958193362136948110865397498509541978552163608664910111097484344111265508414674502206468095426484449495661952091027512836383946952942259134571474962916748153155124469369237399224386694894533985438381306408742628779331072259662078374717232763484127547679303302310423,127851513581210146707222534812462714415549658228702116548129323569875687997527570139914376876955894345964691178029394628745573178902316765592327648023513178993717765546280790932769863585265709550819660882599525799584893587529991012504312937097442098858522399473806578431530443021404617174701716319817659510588
10014457466865501413264699180995213607651643403581155351850240885586127254516466035686557278805989563280873217997386135507560429328380625332058111008767730524810617486297285562994007263758369576890950982876431843971907525378186076190945281470031905336296565482376151661355756246367703162199805483942789509516,-9493045169000225624825724585241654877107258957466554573322941788423005986836702078635071088783742277452705183557515581054220105186163500969879785143181676844657120253295906990349839818041129525896218008774011956975336293108128480236859770511279248182237458109627660116415432972887068943678814730002774447323,568058498128347562017983106577404112679290790118077765226872096344304166614495246835964393367142362074124393647429278191341969083397190437238809441291521483431836555168421336650034272837791888742028164348356631901893675815620388348481938896223555723594783353067563133868242273893775394833482067029611721906579|10014457466865501413264699180995213607651643403581155351850240885586127254516466035686557278805989563280873217997386135507560429328380625332058111008767730524810617486297285562994007263758369576890950982876431843971907525378186076190945281470031905336296565482376151661355756246367703162199805483942789509516,-9493045169000225624825724585241654877107258957466554573322941788423005986836702078635071088783742277452705183557515581054220105186163500969879785143181676844657120253295906990349839818041129525896218008774011956975336293108128480236859770511279248182237458109627660116415432972887068943678814730002774447323,568058498128347562017983106577404112679290790118077765226872096344304166614495246835964393367142362074124393647429278191341969083397190437238809441291521483431836555168421336650034272837791888742028164348356631901893675815620388348481938896223555723594783353067563133868242273893775394833482067029611721906579|53924208564494923109968517258991384333718615783597634502228353963509962336751805354923463494565719411128406689879296751392427452179492575502279868846589843663305526485431433798862642111241114809566645178986499564696116126963309686958809916838000470566457881788520159467305886335238376585070031885019107861839,-39165088112891919485404645022206551911392044983195122526582505244941571614658605614311191813725723193620640489676510478992438060577861340792571425647895723271516089195795031639152263494946222662918005100610385322895768473350699779206361702599565733658715228168714169147264299885332019593127372341848528310877,112189763824528641217468278574322392988954546777239131658850758660466358827365295080995339889134329849615042048060538504294364321483596732194229239161149447040110980960983657967678809117682823152517826486688609621632734218254085881353576474560418869461310902870862203604502294697766172436420730459846253285376
10014524612435081655051402581388141399758826121078479680077428037590919760198044078469208114625992172565561472610137633731570114446039320551421576820201144498480274752068507237188168464666743295560743051180514619150806895664325776982239371917265280309982409950396003685063877356037007592827997650696359708648,-1151946584820929060448198375444913319887694243637725495546164532401952339142382368891700429417009398962503441132652463153588614606824550308747271936296460648801898782148675402610858915130433609314541230955826121143276189468724039832396682232064702428868374548095200287491142543410829209121388657552507539861,755148183880958266120452185655234110618667867205538459331580575221728013160051641776310146717168795492323023035012567121444609095123943446710618919745199683082156201032014589922592096239933647413759449971964484414757026090967529868635390069577397530636511831668757182454799405458183267048363982001659170207347|10014524612435081655051402581388141399758826121078479680077428037590919760198044078469208114625992172565561472610137633731570114446039320551421576820201144498480274752068507237188168464666743295560743051180514619150806895664325776982239371917265280309982409950396003685063877356037007592827997650696359708648,-1151946584820929060448198375444913319887694243637725495546164532401952339142382368891700429417009398962503441132652463153588614606824550308747271936296460648801898782148675402610858915130433609314541230955826121143276189468724039832396682232064702428868374548095200287491142543410829209121388657552507539861,755148183880958266120452185655234110618667867205538459331580575221728013160051641776310146717168795492323023035012567121444609095123943446710618919745199683082156201032014589922592096239933647413759449971964484414757026090967529868635390069577397530636511831668757182454799405458183267048363982001659170207347|46183360432532901454553912811649590320395866004347241196844991991079215314437275037790647677890495653136878666779844887628869070006778207117633836660092513861015319661569732287838772799418674107359979430356246346034550280154482402202513605341927486676571446547869725605869822695502032982833841088921112910317,-14839171560103132001614843311520281027921489422034665235320812512225719145369465447283012912841921017696170329655940078247191555778130550993274994429848671209676820244675419866031667103832358269654123112505016252317575238332509399397558348115029597533711563469431946692326093523953990323828622920869190596305,164933181779897671999712222932130083401866004577771560343160060853528269308468525452931360567865498324819919495168385048274257865546801611749112060417208336526645794766502287072279593583106527746581118239327199774476900334621937982627978739872164479446504941326886004356233761306601172587310954186017120057146
10015153163121593836478079113660124757348318592530821165639828390191159358973882062973457665510869038410016978521906069415643885467466803613263638452835291035274253082105374798431579187029855868716866951698965254377198199868261126247017409456764474165861037253182443325274363795830109568972878953062238823520,2382294090568001333199894323474279123934374114667847405540440750564854209907703388935432920732110218963078674073256448624811505546395497000378710736855311825351193195350046490926404354706980500837042629648272073851723169837427468358824989832884534921916167168920876623159906890551519514875606250679556403973,773658465692173962483130527303229646901934499596511207834787839028928145069426505005504820136922810366817841934360207193839133022641619097494932108724559232945611195348726835877676174729010759098808115181632361389730445448407363060843805088069390583778242530477288002693827656348092952397617162960252636436602|10015153163121593836478079113660124757348318592530821165639828390191159358973882062973457665510869038410016978521906069415643885467466803613263638452835291035274253082105374798431579187029855868716866951698965254377198199868261126247017409456764474165861037253182443325274363795830109568972878953062238823520,2382294090568001333199894323474279123934374114667847405540440750564854209907703388935432920732110218963078674073256448624811505546395497000378710736855311825351193195350046490926404354706980500837042629648272073851723169837427468358824989832884534921916167168920876623159906890551519514875606250679556403973,773658465692173962483130527303229646901934499596511207834787839028928145069426505005504820136922810366817841934360207193839133022641619097494932108724559232945611195348726835877676174729010759098808115181632361389730445448407363060843805088069390583778242530477288002693827656348092952397617162960252636436602|2334289880943001376407857326996263570161383789108737840675851906077977981768540714248105544895055900962482225672861273136265466132609608331964249615854131927898907957201650301595252550620756829520427054784019840985991520693282395588941752214974743008251596421642708049368885083348322205731564243670420111453,1451720076983591598762998723081545117923198868478265830640664361188690301293679623937617406037087334975387230852094993435248087727723628228521184122895045650428549727009619829664472593953602490826316016345941727517760259061554173070969494032097919619747777129170826368624036489935713881661043471800066640125,3318960568956834644312274599956969298741234864897695465866703354170475923995521916039531437101483638236150279927673715871252637092748519401149230098061946550109095773979423194478592673363716301124276065026975130628863523060647342416992862735921072287765667600233548851774826575592417995450427441845506696081388
10015239581157875832393535763226085031936027674008799231064578015529654192320817181717861924169857992310709531421935508097069554814977182072669044193680614850544453265357095259368437732015348877933787885875170804438256215681419620514332393733243248548151757671725579685427667920968624432291421418590675885300,5094068907677575740286879080674249533942090145311835759008798415694966420126408035500684853222542571817165748053609110326610732625612063208376418866488998532875479258993000620044826461966140228426897339103003926919606128736757098245146058573375685873266553963971816210554103991392539430164989850926128708273,793368698167290739626939845245925598679004619304386735598558585912760256279890735283141314660505981777266664338091862952502183635644778863932176282239208069911448671090051312086285039683208751050938084831532228722294544316547609430035555984901118374565436615559075980852757981922632778527357570396074193505873|10015239581157875832393535763226085031936027674008799231064578015529654192320817181717861924169857992310709531421935508097069554814977182072669044193680614850544453265357095259368437732015348877933787885875170804438256215681419620514332393733243248548151757671725579685427667920968624432291421418590675885300,5094068907677575740286879080674249533942090145311835759008798415694966420126408035500684853222542571817165748053609110326610732625612063208376418866488998532875479258993000620044826461966140228426897339103003926919606128736757098245146058573375685873266553963971816210554103991392539430164989850926128708273,793368698167290739626939845245925598679004619304386735598558585912760256279890735283141314660505981777266664338091862952502183635644778863932176282239208069911448671090051312086285039683208751050938084831532228722294544316547609430035555984901118374565436615559075980852757981922632778527357570396074193505873|54841829397576178848410586601034860596951681568779361478370108261032921497569280442168530570346157404440784855573637229833444102498053726559151577392605738325853410653119896676062193149054976747541732412004218217068288550127184839213667255982218678702854737220904918059908451831872125006158411607941690397052,-13987639594862577439517093919564754940146287009709146462369986810150221519296281298521622497304190878362220137401179604871651085725669668566995040192751337189374220954170616856835063054456944563624013156491483611079953326833211481288513306777121436082074004700443915242579221138749893848640705537321387708809,145658957896464652977038505022308448361415349923894631554394890309500215673949920864830014124570888235622920757378372327525946059952077895236293799705256119864823158645268515234330467061529263252614881624406296566043408419602845128600163566622927193489899129202143975708704672075445501568437520798105023647844
10016254093062341091793169016069728267098466973354611327776341296362926980734885768145505535610323176943330336454162903286601650062616238131379152236760546371204482195908361542328829078490793642835057146484428739306586521325328236448343779367153378279828280298660045704810418678221790320328995853516877961219,5290291792844776128036538578818355234036731339837804827682257620535756451822532868533550409363458436730292692155637706486234356872153487706954079157252741244973963860424508734267445638531496348565715559236158994920739250737957339663944820624379832490664101888239401802029497939684558696213321821587965089165,649562196414599732260624464563141423074514382020176141033151990702926870363780837252385965871530682720560442789827097838322398249975199460284454895932864056555126156062190575895999061116214790474483579500239339070750293285631666586984632253828693474154470829221739655058926181416125562534958534381263761974132|10016254093062341091793169016069728267098466973354611327776341296362926980734885768145505535610323176943330336454162903286601650062616238131379152236760546371204482195908361542328829078490793642835057146484428739306586521325328236448343779367153378279828280298660045704810418678221790320328995853516877961219,5290291792844776128036538578818355234036731339837804827682257620535756451822532868533550409363458436730292692155637706486234356872153487706954079157252741244973963860424508734267445638531496348565715559236158994920739250737957339663944820624379832490664101888239401802029497939684558696213321821587965089165,649562196414599732260624464563141423074514382020176141033151990702926870363780837252385965871530682720560442789827097838322398249975199460284454895932864056555126156062190575895999061116214790474483579500239339070750293285631666586984632253828693474154470829221739655058926181416125562534958534381263761974132|4371923964825216081284965901486251829658920327478160330494959761785570498729926171763697403539994609514035386549444286899305836316283570402957212167175599769519526858160920653621106184279087086218630872059466833612874880235324503114394586087353649281136173057014948419793113247251617601913225740371158264594,-1777711233855585326424402788112018092969733488690398670027508570423282261674718543600694888501454195345939794788269076453964223553057248156896791027286117126036185606587718958830247368692129308590218482424190086311842595428742140075700660885589198113766412954745249944832418277914084817045523687626938171785,1486753504481531714235052666066139608869409848938074431937349188798515713076253106271449862728854109674272536360912828894345019832890057397353770574425655506024994198304163182702822689738838001321557096641997078734385067590564038418788081682782254559978113888414124552326849527747130706995014118004294289090507
100168933817004159727571823870862212374515071383247163682233493029515956409883385367746187285740348786673303354766599662884032925310153869913659930858915269690815416234679514078167380783771768659750083394948158950008326340270387586985723448583932705818464704601214600293828130344813737095058092807371622380596,94832715670637342331954204053963565603302480280224254821703778448479787031215111088413069986664424694762700821340882966261664606716747356784210807087846121536668261049472463334524682357378613143974178468771819549191894308095591279746614292380149290609465170348542192697415722868093623009037253233869856957249,102860441967964242444445722269341757702905607863364253263839843561869841563005656247302036622183568251273499262767768690361280263007610763737074443848261770701568579600837276156244861738658629562432640564576786387713071777708265072467592751700403901387393831303255944800743982818455033707731784929932463764787|100168933817004159727571823870862212374515071383247163682233493029515956409883385367746187285740348786673303354766599662884032925310153869913659930858915269690815416234679514078167380783771768659750083394948158950008326340270387586985723448583932705818464704601214600293828130344813737095058092807371622380596,94832715670637342331954204053963565603302480280224254821703778448479787031215111088413069986664424694762700821340882966261664606716747356784210807087846121536668261049472463334524682357378613143974178468771819549191894308095591279746614292380149290609465170348542192697415722868093623009037253233869856957249,102860441967964242444445722269341757702905607863364253263839843561869841563005656247302036622183568251273499262767768690361280263007610763737074443848261770701568579600837276156244861738658629562432640564576786387713071777708265072467592751700403901387393831303255944800743982818455033707731784929932463764787|77074101972769923370658023573461029047908280864501436531886214070884695444419790476920141159581106162534554398040667029684395317753749995140975694643351101153246406361333865778019332847126758508398386399309944270422140994351224794089223904030644354844471144608782627152160492615030406249102513998568586126653,41985809674026851301068939458342266766093613320697544468890621111459064094913132603897896518617407840492037076180430740254366932298578105226006922522339189157081422030305375009727018508446301230399756872145212262654632874007091596766171377732560260349745066521408866260391195589212337788533541057115385883425,110229138576369926974358954548772667512560757802376313780826844717365768043167923353943051327604684088175403151021231033281660580097059744410859188703138886987578267563448651782227630417696079180690392826925010189611494463744920925421564075513181916017454497019126236913116432477001913262238126225201422341436
10016905787587129103970068378589209223718079791180726370802218768976971488497998963132244508629494308529380628538141221743580243393344335649567002150936320257090927900467530902572471077942584896593451110546304416815718151825873142786318484895510554032583903064792109176935301749381314577344473149515437073560,-4606191417439560848418163571752652850846391635765859587403508494460979835111500495993727812816590518091323150783186546267331220869638878833615969103418728210432746474134652280483753966001415196686238333974286033749286862708642243562674370580850529480084335445537434013760930078201975018692661527689582576651,605629172398620500162437997408160351967898827176789386195142449064206069917749164747262079121234714184955198496120255981525746584380916729025666697652941726995464456228081635615903549843932017595245592861355354651584306759089064045480854767640497444940703279199283744488071666641763271403206424800946819221209|10016905787587129103970068378589209223718079791180726370802218768976971488497998963132244508629494308529380628538141221743580243393344335649567002150936320257090927900467530902572471077942584896593451110546304416815718151825873142786318484895510554032583903064792109176935301749381314577344473149515437073560,-4606191417439560848418163571752652850846391635765859587403508494460979835111500495993727812816590518091323150783186546267331220869638878833615969103418728210432746474134652280483753966001415196686238333974286033749286862708642243562674370580850529480084335445537434013760930078201975018692661527689582576651,605629172398620500162437997408160351967898827176789386195142449064206069917749164747262079121234714184955198496120255981525746584380916729025666697652941726995464456228081635615903549843932017595245592861355354651584306759089064045480854767640497444940703279199283744488071666641763271403206424800946819221209|46304687373394436931218438666336335256163483212484332920442711829320278593351077938042811198542492407186729960199059393629663370119443451307712349370714705707036441431251782566272288509732854919564985572759872505231639307883389746522852343879592729064407291688011480357040596643477509242715875322162180945750,-27559962602683142671407402152656684625711978340483108455301920226275039655520624691717381412007576185077377268485337641259513780832297300630514833099989822452624240349981167585374487019267119021970798715861631920467292530317231419988216997273247875678528676583110608263771292353047679830100015076536212572871,134999594026951253395775325545499481323026670784912424362786946325493588697203309584859459643146426717172468824814166286260797091069281816967149658244654968987888219904891951992996909324931101736714925044299968419433398393443198400917682271553527341988170608553689440600718627726318712053029382276372293927321
10018204832407485307717168433283551951171211565712475881182623460525924044598415564148247583748572210844295784844361310074903318189804960966908772513031346031383059069976302114174587533940128565286800673190990221782901119861314311455679210523773394109738879256410739142961640761546729001001316019848803176862,5319904375533742100925641023534751951391638893478820023967035481652261436239987131193126434052892185984232529181792190920674907331089418651303709226767934571557921846173913244300134187483219524696758678859856206200663423378880336983240402046185791279466371047694436246549133924131892629303395892591776395187,649443554629399472805877307531888884997294549224205118199170867300682218925831813905978113513120968194233947187441042861450829488125193696091497608405966874500722600331516590109468259720034716473854550338705028445661682847162605116427138852824514186119049574433700978648124399292078009263486664308050317605762|10018204832407485307717168433283551951171211565712475881182623460525924044598415564148247583748572210844295784844361310074903318189804960966908772513031346031383059069976302114174587533940128565286800673190990221782901119861314311455679210523773394109738879256410739142961640761546729001001316019848803176862,5319904375533742100925641023534751951391638893478820023967035481652261436239987131193126434052892185984232529181792190920674907331089418651303709226767934571557921846173913244300134187483219524696758678859856206200663423378880336983240402046185791279466371047694436246549133924131892629303395892591776395187,649443554629399472805877307531888884997294549224205118199170867300682218925831813905978113513120968194233947187441042861450829488125193696091497608405966874500722600331516590109468259720034716473854550338705028445661682847162605116427138852824514186119049574433700978648124399292078009263486664308050317605762|2096824613311195474736703091933491927179118439681576075463684305365113996801091784928235546455105051723066941197368294736517297176841884535935805063900042702255946184765201041823632273617760317603104813509978347996857764943233871467178918416729927262302333533232369242879390413535385046393166248041635195052,106494743809548339750384465880660679449902990323530191499768868050880389213560457433755933556230921885636912867886887645004590062925256300108980851523487384554584007694663026566980186001150284697993766392145530903618307059918756399086400576557720952521322359177695970013138988731324890614696675530003172189,3099537274480186341907264372921810635861168363663532429504499040028118656288725100184032700559268063816635775634703345843577214400172811320277070043994325333354476328328682954931303645039746659585813529747367061450073478508564524387846459195219414272058883943010351216728564728313947382708438971484753032540491
10018324718324265352080889354041349230495045650756363847859249064826167700621077306379636998633382620068424485758426219639651755498284131150741688356919555549109464768469845299901089390604198312107185124929799165529332689261450442020302769382765032211061987664530506790585428478002180255625233322864976647458,-1506556466689461719964363510118987647616549995746954868616471745983245113792074110437071688516535364802439931589935160320446594866789971924891832800418288544496229576060497571654938278590804451001178571222736016531030712235951293438712713277945256316492298818368402112911658258565046390998975710669014707937,708633648140842422465025989226402132551754445128385378651747216241166649232185357696677838986015643979480257385865744447602978939236447538983280973796461564754777224324765925807967303202117722154439166886733422154436177593473337680099402130518111476687602398807958385973240844776043934886139211712396905414373|10018324718324265352080889354041349230495045650756363847859249064826167700621077306379636998633382620068424485758426219639651755498284131150741688356919555549109464768469845299901089390604198312107185124929799165529332689261450442020302769382765032211061987664530506790585428478002180255625233322864976647458,-1506556466689461719964363510118987647616549995746954868616471745983245113792074110437071688516535364802439931589935160320446594866789971924891832800418288544496229576060497571654938278590804451001178571222736016531030712235951293438712713277945256316492298818368402112911658258565046390998975710669014707937,708633648140842422465025989226402132551754445128385378651747216241166649232185357696677838986015643979480257385865744447602978939236447538983280973796461564754777224324765925807967303202117722154439166886733422154436177593473337680099402130518111476687602398807958385973240844776043934886139211712396905414373|27695493339474189059880649994786373673681195258723034498967136263221174895242876882887946040754182923842018399590448977999734476968405279409965275664350294423197625592498762797252651752487096596479518881899735472134497736489815871889587384160668070191112126826489102305651218385469424433736996571142100268141,4244952032054732923978416579691917713463067102733490131769022354718180777349838220573662792933493750823939044158056520471214587505994364897599832929831064732609354344151098280452640031958247121275726298011899146169585223669027857229201360814944532694404419990370729211245101258947186079227140704211123597077,256477087542010205875387979681474864287758986482727894664413009819175948644274490742191718780565989800083756066810584023109412061717270312386676508030363737098913494555400729954736934622756650518307368707185355806725304278546342578972238562139946071381611959969612417306120634997866733933066171286156441897864
100183725937805337440102832154923451468884088040067509735031176134138272029603097931029532527171620687937178427853408917605171373483732022096443082050272616813579999826937201905718430121138104894761796713162794983612090638008542903172271321979734531328047767185223183894705715872373581190063338544430105324944,97967360545064065581782092795782542381718050317435898718948431525445051912029574864522929506831468927036372238440312318277489221772379035158891587900186742286147138092170859279721424649522055176445825889170777870731814816272149484567390197282747308726861433765864290861778135213069453090668850681241158130141,102026058802637364547431940124628332383045736950389197653455431566764985503089749509318465184383586821649550424369391712983254618997917250229615538329822378126555642981029789087346297188093481472570239624171949132198549570384613605722016512646835562730355439782372504448945801732597394795504733391497603335093|100183725937805337440102832154923451468884088040067509735031176134138272029603097931029532527171620687937178427853408917605171373483732022096443082050272616813579999826937201905718430121138104894761796713162794983612090638008542903172271321979734531328047767185223183894705715872373581190063338544430105324944,97967360545064065581782092795782542381718050317435898718948431525445051912029574864522929506831468927036372238440312318277489221772379035158891587900186742286147138092170859279721424649522055176445825889170777870731814816272149484567390197282747308726861433765864290861778135213069453090668850681241158130141,102026058802637364547431940124628332383045736950389197653455431566764985503089749509318465184383586821649550424369391712983254618997917250229615538329822378126555642981029789087346297188093481472570239624171949132198549570384613605722016512646835562730355439782372504448945801732597394795504733391497603335093|88007552516538570862938195555687347843271125145294862509637863339852312849461683699513427251868777755449793173646890377883712394792262777503483942996934326765981582162423696391672000556247247431253370862284402004050248548817767631668543644528300726312835546938100615886799945875203418182610947796762957426066,46229538931090505519067196461411597385016117678710797853895441617844339335997518932818211184588127766146461427860967017470462043930326616555616035492326025837765159149630918451827844844437116744925433303753825438769925710637787423788344940219740545569047456022116580673560308925831201666938083175493702647671,94949150488319392606413346466333119512866765599276437121309157049458742789511630485348500087618567561361017601972082423173906361345987933875129792711583865107081204947273992176380167405635064486260061816002217859656028475745573246943400761862339441042416462774614661346152692808807449954694367626488600259377
10018622993047838712433185410421446815061984959152870777572656734193435222251946970691795794836467121595552277401220487788714277091933394850502637162917792769686767139849624312881217655116086523917779102305498425044983500792458780789534783880422443059521517950075233845690825129430658238084704480639376209109,-5642888291743578132708587871691433542854601085995709323535797030150736747981212204721414421313379808144339701595994626772514328521365374368168430420450149143091140909885716813202658261033852230689379211692039890782701731228409652608328076923100699005939261407374626950263084881921749869854247192520776393467,584355741641273221932263410866659097943618996328052690659780811632775391934038170008705223727517700749237903184431819452649538607172642783739379843963426355234430525043677403033326216332450474494227299404505243469315575849027861412999876408965870212198057391050926245137105584182883631254668161360450853213630|10018622993047838712433185410421446815061984959152870777572656734193435222251946970691795794836467121595552277401220487788714277091933394850502637162917792769686767139849624312881217655116086523917779102305498425044983500792458780789534783880422443059521517950075233845690825129430658238084704480639376209109,-5642888291743578132708587871691433542854601085995709323535797030150736747981212204721414421313379808144339701595994626772514328521365374368168430420450149143091140909885716813202658261033852230689379211692039890782701731228409652608328076923100699005939261407374626950263084881921749869854247192520776393467,584355741641273221932263410866659097943618996328052690659780811632775391934038170008705223727517700749237903184431819452649538607172642783739379843963426355234430525043677403033326216332450474494227299404505243469315575849027861412999876408965870212198057391050926245137105584182883631254668161360450853213630|24492216963212266409994030118552483730975075727585752220177989563872338705971497453471962798275543072636175655672560120906290569324009187038649563218726182874757477950170840864973817320145411108769238293767323154108926503045123037222803844779103784397763216133236290396907058542243428101056150879809315089176,-17735224044627622852810014209171696937481849587925646605967048837801771413294839162751742330787917315172217980725109761639973896911760524548506285715284414033504356013230406678376141516049028049732948719065205234900025147050216480775931691209693009856949654955944471263615211623003442072374457069595919699233,241918233622395884761827246850514897219165802162342296635123580790888932192977763833922926853355444881644755349323889380463316458550630788255600843973415342916444918642659362862569058232566277775534472941540495721557558697754452057639207696448965752690070221361062821443638513586031328286832012283835743514220
10018933732727277902205269315771289076593947560040587959114941078087116999373425488340685401505876624281584630582917353725134238041079746342415896279966203184863826892445916822683268888700587092452305745538315423010290563725863170080340035065039975298577793326244665530455537053974727163555479979119191279926,-2305656050929911594001774361902538333750937712118410383814661797948886130836022054225957304174319742645328482100663492843669952358370802861270894168816436326458990297136526459920949376942432261379981780315229778535749028029896216855337892147060100885167806805043764484945583720350824386167496969085180728505,426903073734578001112620417146509321508736309565051582451873814142074420259405364041324675206078055851221135785335125834745297538613608978468731354815366776968439807098716134814276564770795992539739869501301828055278204465499226602180360134210119244471648153940999928351968352054963731820177407885865927236658|10018933732727277902205269315771289076593947560040587959114941078087116999373425488340685401505876624281584630582917353725134238041079746342415896279966203184863826892445916822683268888700587092452305745538315423010290563725863170080340035065039975298577793326244665530455537053974727163555479979119191279926,-2305656050929911594001774361902538333750937712118410383814661797948886130836022054225957304174319742645328482100663492843669952358370802861270894168816436326458990297136526459920949376942432261379981780315229778535749028029896216855337892147060100885167806805043764484945583720350824386167496969085180728505,426903073734578001112620417146509321508736309565051582451873814142074420259405364041324675206078055851221135785335125834745297538613608978468731354815366776968439807098716134814276564770795992539739869501301828055278204465499226602180360134210119244471648153940999928351968352054963731820177407885865927236658|26579833924289520389972900117950394438805828628221899849785251193277262506904016180015838661767033925903809658684422106275456221210787145479887893793178117616282806012189342470201902133434844784106437109753666637085736679857929223320267986046560553880930252162405414807068330327382869655263308507921578124762,-12071122961357042682227388807856025622183781701383406123339407125622773263556987057807120839167314088703384163940961495607053608272112660158109007999608142815575559883680071225874610842202742230050716632165554413346974345932440553672309803223445371844345386485359912292135145947019769810450457220546043659979,162236250544606905260439724773080091403174351417582646687611423124289071438608418146998192800378143503443566522030518800544598083530735564341780541276153264296511032654040655556029284610154943880012602862804365596003928006715967740792065055405085248350810462900711904458160412653922105321414238780026013533451
10018948288270418016780081341685235002997245256040164792426543952818991311558791493453519174957285944783722833865026222848031081817691340856453828555107871396513690880005707344898646359417008593189440903277104626759357903337151059344508962185668959714673026792114793015152022487676173726198202553281736763192,-6995555163054430382942870868581755160069395592106884274460542261252343393118569480209218511916560630596078206970035597385154389463448089846021818488631352733935369530889081823095829009383638648970953617256944401187962256866752201837099775227177656065063350644379695273754386677388279021465213328634933930909,721042528909917874686430575245079781825221838112029624394686069315349560814178350680306853206143047638999149938695007663434153092166743090545673695580676514178586788701941454964134693721185647384090760708127649587795147765724504088383646300322664057264796405575462352962768416720670014119545119956267157763268|33152009177899700335521286237987596749114678289874326434440918518081126413178191723162867529955418655435996482622593235632019894996887430996202492483564865515014035645906573982414795827153656592748272697286574461771116159112804016039989028059075628750439940373451196506327787093378094310321443683918398305578,19078728942670828368834699251746230066071047051172922041653025393624623551743744386999716370764191631344442619983012078124921474009852416209669177199713374821106687471027572426997637428928400364743864020836844501941937756570061589022465875716319591910681201998018650317776190333584438330413688185262916051155,220283868712478416207788658621383280997894846941561822444891957123908778028879195278346553006033805168466857198910274082404942136780954015736899511278911633428569844883635491399257549871333616419819287122510218677255768780334985075712076521491595155945026941146633288297234150638278140903654693829381901681364|86660112777924566325641144753803400410997086305075442702977432289312131972915955256795072094482313726948480079751898750790544713440908592818334342498838917381523558133222779818572943010979268307136948067185583734409642160207725489813897991564467762533071090190022128208402492072833343072675416905847421692846,-52778887618554305290105838041380262564458801465646670949464065301477666757134518520029567230285725793439487930254994645696418125229532386083964770290005616954332222417663293453485136710527439679565903814537080125880293745499032607178356596254426977323351345945596998496291222195474053846483056964155485024969,91256009874012914314189895519654249139544913048606429213352879670217368386794747037392624823085153501261342847050224541672528576684432409807110715865396865727844957353872518329845940826549252426734698443465027159176074936925639415490497467627459134074448093109088470713684894800193345119623601342741289991431
10019019997781066559943515640881506642517558843222778169026234770851975313720579259773361086779089551884331113250530982852069738010518159622349375335824689350970737457654843734623714224913981064444982445158390435699719229301999181267314607899665318687660691355693147862987025822541914292231182646321427861873,-3157363997717363888291408594979293600171398541934051160356171159608233287859036491344319963143369936444410446129850053542356863751408144208404845266526711359417425663346085658910109244458752728340593138106611282955961606114280076234921423984338932045399865574815874428373668830300085650219459974701588901291,427660300107522994538791232761616142662131142234945666620460681757069587002421636449099874675218488912225359428713775902235016576565531397345002001166527254555699729200052739867740788272516457497859568251192144704431298212101856469342734690447583085607097591547685515622397916186942279884556709767139560196364|10019019997781066559943515640881506642517558843222778169026234770851975313720579259773361086779089551884331113250530982852069738010518159622349375335824689350970737457654843734623714224913981064444982445158390435699719229301999181267314607899665318687660691355693147862987025822541914292231182646321427861873,-3157363997717363888291408594979293600171398541934051160356171159608233287859036491344319963143369936444410446129850053542356863751408144208404845266526711359417425663346085658910109244458752728340593138106611282955961606114280076234921423984338932045399865574815874428373668830300085650219459974701588901291,427660300107522994538791232761616142662131142234945666620460681757069587002421636449099874675218488912225359428713775902235016576565531397345002001166527254555699729200052739867740788272516457497859568251192144704431298212101856469342734690447583085607097591547685515622397916186942279884556709767139560196364|21550716916645018398165650019236850766796511258117069952017796540701386085912310717417651598467640925140901250417026118119274327376121328459299004640348530767025071918784935281870705231282717494840395458987826494640924389129904911635742804398745940919397702998940021391844339448198369222701583556010313045812,17308540888407999086403450710891722292596558140904996642436794702554735336548386086410226733754785281982433279805336861038046891710619959255360830608311138886000204010857210058502793117398659272632248311839231357476736302883731390652600445524351263663967663494261178750828036606884450644013387538641171794195,202180803355870010447215408817189049345827932931561109501494466474799106708426285256026437292412097802628616665602361337631758401467452446995726703770591794057694222974232570992815439680545736890553211079290478720762205284250715176457370298196341449115424087895906723941555883338741498383975320110297668277534
10019269520234431826137367355034420920528860342846780753959912064827599010243316724633755419135436935645907443407020572618899291215095816080730065338555965834485853320180090560809076866724238012634325051855947616588404872824038021038592555404461140712393653058441964129349148722979422040489509372096847725674,4522869991076735362499160116541059903683984737748984347542239263701333187108105456062644949444149453629982469461841568384073346981390834850295332934943879978241839313265925834724485912067878288054867100877621399054735204930899125650232136163964080568519169554901660276496750207252542508193487574803619459009,749663683253588383775532442379228650764046549728574777396900821733935114135159669567652069917832665405176945410288020981482404785970875873582684426212358839598234585501899432885966938532819200647768194074040482435441119436072379143147234400064595949108182133121869311200924895068707591158185629325001898213097|10019269520234431826137367355034420920528860342846780753959912064827599010243316724633755419135436935645907443407020572618899291215095816080730065338555965834485853320180090560809076866724238012634325051855947616588404872824038021038592555404461140712393653058441964129349148722979422040489509372096847725674,4522869991076735362499160116541059903683984737748984347542239263701333187108105456062644949444149453629982469461841568384073346981390834850295332934943879978241839313265925834724485912067878288054867100877621399054735204930899125650232136163964080568519169554901660276496750207252542508193487574803619459009,749663683253588383775532442379228650764046549728574777396900821733935114135159669567652069917832665405176945410288020981482404785970875873582684426212358839598234585501899432885966938532819200647768194074040482435441119436072379143147234400064595949108182133121869311200924895068707591158185629325001898213097|16642018863761441710765797012067927359722077189969631448415362616699814913503672898852374525215334055299068298216385689523710707393718883505223743676435071846547044089283998146628167129062401919282532587286538467437993909697773987546172287165832896898434018866746267084068433592983100742343012553891013967598,4279618085412193426188644638927864595084294097891450444438077735383453062127268915528450003127312343513730070105859170701493137563013978799842440344152818674511355384686181809257130294212609318791976849425989687196701708107582124757707100916931554678238461537620568164241235565012338998887375426548345583339,451300244762011954040540232948856842185637826616664360199909803894796107535366932948228367749161671550552967885565839529658452718412544695138612399812114901538129955756634712380719016039028157710981132001101643596366369267735875381875175432502771795477425963992931644164806539340880034536557519705047322385756
10019417926514296392019946929112818021632198703101505458649653394849455829204203329294836960034957633501294764450648155864378373289178486051989714219614702737597295310475376780688730971937576079121199314793519307265245938553456529418922522984552293638273911817508398110317305685502955048568809327523071451646,7901274255200127696618788587659559342110188499337362982289909048078505324309251529636836412429419509644512565320215289593933580545899621400755280134055539493035902983697255734323738954580031486643652880504218537900293807494750583881428021909372888539470375818772560108989429450107579283565673329101511361623,623699550931583586227312516211712634135558043787600676758608115259112248746313728815655527067581286781548781459656217474418345498402764321216306327583412055637930534007526887412883845579485648951016708462255973917762702757210736584322682381497339273737323760137458761222143566171226992185720766268284746949539|33994172292722720621983078916917152805135157553786453695681859425113486805780487896660717595372501233092400041645960826591356846046682770081212496668808601116475820169782887756136359474132767453083956483565660497074117273547864843066209384954581834231890370515327604527171929343867967182910635357940103381259,31993846672125961531384598386820046988679306439927918439126442104342750287165534338581303476671621941233213276321267207968356271919850887377330275696357098758109012385572207725576199219446164534402970313646005215676387512077572153065651471880735849343888575800500099273015977254516159942552263434250458169021,190897440537416564844354648094133803032782149306929915760090455032909782181885170078703110757010607891226613247221902350507051587112666985339761578838390574506735798985627221778883031220656445342689661417080864579978266745285225101384742969161503945655665695989381533846227380883303389726073267640913232240808|46223752318790909370837447383363380695209474743451082994109239582734730617406604327737568722130199854939421799114849872972877989567189718205858628003551407137904188277330292052370440786619825504842930785565096667031645779355485895793277208105594179243179236367866554346063343397949912203277267219196168228342,-11006265064354212636439188801633654461277681721343546696389358983928696946083632218719947786058303199938972841132237674419697191902116627029793522898887023505508883048022803011324802659223889838681052775013756116093960676539648227562055647315361638076266948642978861465645013053193461759019970585499519918551,135510058813836316466595636693848570774859961098724584660465530747418644245153590246150906297996570248784693174475582519076799984652691145697384165112598092893383581702308752699625740019767305915611482144859189733431647333812818245189583002227073705672065057825892795634209388635037930002295896526893410999911
10019602901864092738325953873535047812547299524695025320532290515768840900630595544396879008556083370139972255849271116199083634435552540915196064651229780380925328336224573551564497154428220750159228126503023660786371036661986963326869101885946108118123565859605937169197265825780593487194236118858010532600,385562394428775749047853575173957314087625602564743010180946094529317438985024787344743900106472493168796231871305499111699051361035813309229378162588371556942740300961721890004066420192802443990741112403096930009444198021764517249355582327168404565052575639878289683556483174213973783173191751884045426337,783418388779217407199495491198572563161785093246466615634830075323053502538909242522004194931674520522772536562755280126097220160459899598091584353065112800205031495803329979380114748688327366649214078234380064643848371559165846159884696566323937944146599304471519733682046929885711023157291005000370881207583|10019602901864092738325953873535047812547299524695025320532290515768840900630595544396879008556083370139972255849271116199083634435552540915196064651229780380925328336224573551564497154428220750159228126503023660786371036661986963326869101885946108118123565859605937169197265825780593487194236118858010532600,385562394428775749047853575173957314087625602564743010180946094529317438985024787344743900106472493168796231871305499111699051361035813309229378162588371556942740300961721890004066420192802443990741112403096930009444198021764517249355582327168404565052575639878289683556483174213973783173191751884045426337,783418388779217407199495491198572563161785093246466615634830075323053502538909242522004194931674520522772536562755280126097220160459899598091584353065112800205031495803329979380114748688327366649214078234380064643848371559165846159884696566323937944146599304471519733682046929885711023157291005000370881207583|19818230550133203045823734101898906263121512206428289485014719092970295967340599816897147977749512129070950063889339566610951920388554330328298156066258170373411927366975503222525343688945315211747565841144619516815319867733346621311891854079913905473945585105165350274151561111090081792706060108559348689465,3535705381589141871228391312322719660822687473426523492896512078425893509048104602680687792493669387659393458499063851065894084002514574997947346565631807028562721897282782831306960899838643543821499923380013426924166037069379808013932912663720597103553887305082262913905822119893857258661880909162082386383,396232614221934638032209379440961132627800399045535096109310461742382984824006540071415151913091585171033970335144034008200593280126662125846778006926029922409396791751216059456912978293211117174561768028351334637727875808828406496707486419218523437819900629926847694284488804630237181598046520852448325184912
10019618759445604574695938593576587154046024907827143734869384751181580594765954554297229655147503034078881467428687208204647162639839815171638500727552711523715462319701731893862102462479728615304020826611064530542284194703939928285119162487825469366941939907341692107287635698074740058272417655173119766470,-1495231899271916161022455577964100860902948284811380648472435397705462086200159484323324090415310461943736883556854457678257712744145878200402349694425772714427495950140611274533744925805188738644517051127445631541048041016411029423836592778690668280454275321001430386581000830461603779827661500573849313313,783469223238034771138196543049546952638608016561545783572815717469547125551690528706587314602219345674223915943792376346892343135362218779360461138111067908088830730205053230437782849794424701715846764766896886615248793041482000930114725702333293352788421520623938402925312326001614873502389289399996101695820|10019618759445604574695938593576587154046024907827143734869384751181580594765954554297229655147503034078881467428687208204647162639839815171638500727552711523715462319701731893862102462479728615304020826611064530542284194703939928285119162487825469366941939907341692107287635698074740058272417655173119766470,-1495231899271916161022455577964100860902948284811380648472435397705462086200159484323324090415310461943736883556854457678257712744145878200402349694425772714427495950140611274533744925805188738644517051127445631541048041016411029423836592778690668280454275321001430386581000830461603779827661500573849313313,783469223238034771138196543049546952638608016561545783572815717469547125551690528706587314602219345674223915943792376346892343135362218779360461138111067908088830730205053230437782849794424701715846764766896886615248793041482000930114725702333293352788421520623938402925312326001614873502389289399996101695820|42753617832955580018896456376048021312038672906196490293353833260191208069121641097415768067383199309083970209480148720670849061245193936234205337011636997701073642429299438906449136644520319530218401933372485811940869805081506160718825508067884253210821932270118450554609943933258707984251287707298966456434,17230882403850817862353558174953648187864024855604030801497255731670352761964080837026196910757872387822284474688098560486179344653906733048259368377140267627812727873134204479739477928295254560644024291521347574950750033700697110313592478883239065168888362080121017118321399563553912315660492325767550439625,185334720796235401233770375301583579692277465177160979515315309579304038663377302594175210667527463523713902806451243556694869849316694559583762178930255061453115298736511664428765337617081386042405590606496094216885684005811351670599975552269701611841562351169528636440894665534868320186990351387365005093446
10019692946699738437088786776088494849594837049086417807717694310404351446172508582779767667693745900344488207593378322991177040183985344860702086830308533532509706853397521152883298228273128452797173239342923997882671035778655648164732292144430552486960912845252279998708953177942214236682313539500552760871,2604527605619485478722364121534608303298155156200794123073555280322873845863667712157493176540131822726294136122515227024701303496679207443255980148330176850776277321446427192954383305967741429509598325549628410919591073607402118557146971439755257250099080900555940132394424289156437827280461319685081840835,500718425039020767061203454192505123268716467124573838196978962956303476515938135055207132642966201859533626566887497521633145487747565092871485790754737106452537951081291971352805654412531250563576927867442028177911508524615458471957056998884949042800057393476930961808638050281181278355398049850987480026266|10019692946699738437088786776088494849594837049086417807717694310404351446172508582779767667693745900344488207593378322991177040183985344860702086830308533532509706853397521152883298228273128452797173239342923997882671035778655648164732292144430552486960912845252279998708953177942214236682313539500552760871,2604527605619485478722364121534608303298155156200794123073555280322873845863667712157493176540131822726294136122515227024701303496679207443255980148330176850776277321446427192954383305967741429509598325549628410919591073607402118557146971439755257250099080900555940132394424289156437827280461319685081840835,500718425039020767061203454192505123268716467124573838196978962956303476515938135055207132642966201859533626566887497521633145487747565092871485790754737106452537951081291971352805654412531250563576927867442028177911508524615458471957056998884949042800057393476930961808638050281181278355398049850987480026266|15699856336284744968275216258343503146645953756650748657692246165468174044843605062520381697859516745152728271221936503804746010309726370554190521588468426695997279591480421106636754720909204606127286384900034321176510676319624471022876412905986167145718126102692531020933251202001854123564019876070185880355,-14062166839366990397106911248374270143217677864591057546982352524148999437729801685798965579843060529335708158623771293637111706433187114619631528674568287241750380206758693785598159577574034470606603276333153981703961125634290277406642003061722480822932526131741380714977106447263763374124622526844984498859,322600729981396869806359195462894217882445977495880795669692121484810837171658548584546952485525802042033579797467228310295552846960328437752401071423653349872764602844139832402563063433112043761099494603274082871711473366936549010464198833941650861319850342621348528624209403813616631484437129382551268946870
10019878828465334585310006306241539349820320632176313877609501227637096062920082798688866463474161563221707726590576927421178038553651876427988000587231398238649949818114022781306536860520405792494648694702226319794624629000713829609168795402418848754413215058377284034953425744232395623600320736707606263601,1457969396702138085449463993396644727452880810876852537963663018612951369129008613129868381569339225995112076334917995066335564006261425730889703965704362733694154907573251182502287488642500690958462811412545500622611307129116327910472660655763332350656262023349742750811995788737019311563028749123005882623,450291340913970001914821927902049497930656487941189505155449421740207064831253795807819514379798428822187833726946052293837627776646264129023306160855543475421211570474321370516290659041655321190880413623652464931091503946846331738732993987858421621514193715128900207229532916132573315382608752305324170212688|10019878828465334585310006306241539349820320632176313877609501227637096062920082798688866463474161563221707726590576927421178038553651876427988000587231398238649949818114022781306536860520405792494648694702226319794624629000713829609168795402418848754413215058377284034953425744232395623600320736707606263601,1457969396702138085449463993396644727452880810876852537963663018612951369129008613129868381569339225995112076334917995066335564006261425730889703965704362733694154907573251182502287488642500690958462811412545500622611307129116327910472660655763332350656262023349742750811995788737019311563028749123005882623,450291340913970001914821927902049497930656487941189505155449421740207064831253795807819514379798428822187833726946052293837627776646264129023306160855543475421211570474321370516290659041655321190880413623652464931091503946846331738732993987858421621514193715128900207229532916132573315382608752305324170212688|42833037907205783423276083695584027308854900022881436412191284154327219859963073830726581978719142468079055995456299937273491938799745755641832339881754413481117724798837471944396287268574687471412696368395253559323362777618554120629431245413190434891698142985970974309630607227057049486649455303551234276454,39533289765204979838239940217464189791925681811448897199438008522556423440885704979337332145873978223602711609006720684578384015360399795422483770905500296209984111909778890881255526888804755991926913525266473446809003766056812782710240729514579954010888129016691348159521572577875112811888010834450317724241,114445618247053384708154338158850812121782306445016732813783780022720172489813267526238634887903604880900808775058943405768328545540868455633901730958967680579278364092793074061036266572372464072327099841482886966487871555516444733955521438600902217517451457471166242011115873608622049499975622745683155293044
10020286611438471830628019358455663881253310586699113562825236385112929540691864656311239753327727457544039348532845219250052901384983806849838772233628634015372101882756673893804993295286755978494686187836862364142553996432815511321224683238615875757382081170105089085250727802357622063598298344850144933258,-3518711690583590719591097309663537838033234040270517781284035777894691716513958367977437977244707408588621580445912322309023058291956527967904833369032334021917801602130557563969030363343390282689269679494383594614447232630864097161162053988664606910387710340058810601198928739842230703566256279504206597349,624519074467883157241759882142650482668439956786299222741478860768930417779553600133573019763129305374619657419598952403430928431333332942138935285782814167747294995855160857963617057240775629113016734743963566849367848417555290458534979590030936513460373735155075741191499370817771701007396549636851814063246|8984140046463484249883815882793946664284637844291004682379330614023973939307670161213321888699915249072065095665013984357459013131040423611078930602512682262356539184355252741789076484547599307370908468303880417320438645852556648240043112769759543510509999231273948875843246292758661134579579434257790056943,1015829211229239775971450394627474475125445320143707214965330038892897841144751214160653701706601947354240523693277132829250608515076685164228306669891554248890083979225036216154539270241518786129131737028646904986272214000689553330402618431223976598945398343370629254397826639390022921851207744783430299181,696229436805911789845333715373446839368886781044433762113742356470360747294068486152977041956647781976745992022313448046591023280602965461797453603661925762491060402477228052040796508933029960965488494546655270327536485285614615574903948243360057525231142937895796209410153481097105649076038536726330776071856|54848884991217637960566999744777250759299676195564728508167267655054271555707478739692179275489551583228746099712696785024768087317010330909987410610335755940330039266190842809649304513680352828151859917245186776225281746820196246056188053726348717015680880973426980177317094806038726097322528009147634772745,-6297694570572926762876118238570574530971092334512760425031884066392157325338148271545111848669911902764684562706179269339278979620083804367858431071965438609706945865206821584390347519912299967269039438763099113180095159546022212222371772149775642184659607016581991317838734844206339663600961049231899483767,114217089877346912860627247021964232304547591103532855496244374445579581677534108677722729277710412822218846458954885849274521645333106817369257230151814552428619784818123898009869914417388072106361002314975966932911313776975771180600386738223895005689517440276702703392932181245821359844597699717902940161882
10020350829980446730171851653876883566847163081423697114380946239282341122006641305758856122547334357120649922140862854047676100901410759420113771337592330434048703781028710403003719890979006119445870636592350392949743016116360518402562929646175152381835283065319457849053035555929737557936105886116269575510,5109280702416633154295665717802160083976280911440360164357040723966034505263983198614731009455276771449649216657900445462253241694441028125347117381803166387820276260518904247537793302370100297043111469835733504997940289628818493126591029673530532890213508380205622484398576652164337711722991311438354895077,783009249844890893386725492620727464553802137797080547324163831661264002221403011235072342035014102836039015675936188668078646910670188403603171656900915122608838040537846311585633442130109085368959065613240580402159306705278726186443869273434480098383561830991110484097132938532579731404550435571781667457120|10020350829980446730171851653876883566847163081423697114380946239282341122006641305758856122547334357120649922140862854047676100901410759420113771337592330434048703781028710403003719890979006119445870636592350392949743016116360518402562929646175152381835283065319457849053035555929737557936105886116269575510,5109280702416633154295665717802160083976280911440360164357040723966034505263983198614731009455276771449649216657900445462253241694441028125347117381803166387820276260518904247537793302370100297043111469835733504997940289628818493126591029673530532890213508380205622484398576652164337711722991311438354895077,783009249844890893386725492620727464553802137797080547324163831661264002221403011235072342035014102836039015675936188668078646910670188403603171656900915122608838040537846311585633442130109085368959065613240580402159306705278726186443869273434480098383561830991110484097132938532579731404550435571781667457120|15925442580907323476159397125803944340654208405155024852617286343514956884706735535756801413937274485810029110697926230088903038708172843921662902925858010133310107241826173293821650453674715296467364194160263065021258375363251922427504055324499581378214158250201451314577475359578763255572268099357250433862,-7555018813268449946347299883155637510823174468910058845458344328340586029132905296413170968626375161086356436888766911933184468019856845539645923943455062521960029199818385839225962202237763532700191551972267033706448220551883282613693004882011515763441495954827960366711246754821589418038272565907011571371,493158713590448502858812148491777446425856175908645102112390069549258575786631074217529579034304661646702428496672314797453719364387931287920597953147023776521758543809562386644010437874871311725548645377471116791426470171042917330992088151061235643311858502168972419940204783448967903363982044887911681560644
10020520888850607221318889209733010855356370939979030352174416847268871176606842611908448929226351061331244222832181615393476121893202716429497688626737367070357875341852767661277331348237224754401428337725087948250057680576003972340744936007808116625981445480427395587481367415686693519322831225744083857506,-3510865184553106032575534381192821350315875177100225193260562098432442799313338094676188269972656054940854032321449718355451351690660219631429988981801589127116014570347706272895437608443770068021130141264825492984427313262655182236186480543751195475768423487011396127341338009641051881511727659162848161119,631736658355910953992723930048397079196586052511742763210137641692860240361410089621711682505909275894759266095700988382555714505394268624248297891868203056209475282038131157087467910727013960998888913755441699771876897234334835639550616100989309716008969633105517000398222168491114030388197708472040972683126|10020520888850607221318889209733010855356370939979030352174416847268871176606842611908448929226351061331244222832181615393476121893202716429497688626737367070357875341852767661277331348237224754401428337725087948250057680576003972340744936007808116625981445480427395587481367415686693519322831225744083857506,-3510865184553106032575534381192821350315875177100225193260562098432442799313338094676188269972656054940854032321449718355451351690660219631429988981801589127116014570347706272895437608443770068021130141264825492984427313262655182236186480543751195475768423487011396127341338009641051881511727659162848161119,631736658355910953992723930048397079196586052511742763210137641692860240361410089621711682505909275894759266095700988382555714505394268624248297891868203056209475282038131157087467910727013960998888913755441699771876897234334835639550616100989309716008969633105517000398222168491114030388197708472040972683126|7743624975856046040306859618381122855435839505066655963077953345318192394961725484815279361678840380508650449544352702656790861663924047145774380332205220566837995316217250717822771650639012193352578327705393209628172084550305955102732361657948117240351750958876943333563882332223706621973470079325216233558,-1302101084353535785220069078550654080595332453473298993211431176604229397211571627224468015823760998656644913758576425096529602829962318111227560243799515644278666734720045652589883053894188670485823003998604116205699634345292108055002592831517880997584910995083278522924829895139882422136963697022188627761,817146068444645002282702401442161961453363715531517354922416373299365609662611633811411725714915989553805697260975442785287852917015804775140015044436435034561860932937633743951090004573111260937285724402644730836466114286731010063169028245934842509507242843981736397798548000353928823827450308171577842094862
10020928293252284825691361744328291985679526412406671670547266480511907045983316758483586023724996977667177961315263269397743828323222195866600241379821175298238115703011379072606569390759148045042025527825985903353933863183965714600189445609817913064133950477152949408914363876047922634974111379776851043444,8142743010559227647391965354039043610167208616578224783916189122845589179285287981476385252457789283574398377141778580365522603626148442954692842646237080732477747098895946414915542936790529750280288364463486949414374698119959104763454330750738981793594749326992763123032351693132354526673391669903228534689,592964939014299189950759948556152413778070028508201513223477782517837089792535061751235218815245724595945353108562584681842937744985593454797280372456160144528618905336752579099036263281502692258180148097231362749391384857475259373320991218168838336648271137666762974150421876463236269917491554488254970217679|1349884692028663713443418855258970852876197688505766806916101525225125648882224033090914393786384981404185367136201476426040087000294669320520442557740324611111940178669433599306350594555401574017007121415045406126185440950248044705540071793090107212207268142684391021538262661004297297377597036659211434174,875208077680684118200876261868445011629698306468238985964846580756586701312125036248886125282325554453814339944800057599270619114144498434513170361313175501368378946075602194132049645256086611958223310749365652107262190169934699379958455541016773996539749758645125590779000274985163557422936755735709025447,4389763511378485954501282191747251660999265924712682485695638493214865378547677386856476228802410653501422368180730844272453992845175409659922990510986478738442978379229425566565975718386747664393902959866984083918397026705604419570614664652992630348606149487368881973666571039701786237266865588917768672714852|5132295574467316848841777686734617679960174295612803556136691640948831222631657128041983413228627956037030789543068853182770008751639881188344733284990628383483491534738190385257771536358960825091917844011611151709882253457446948086421180899165481250089224998180312937340245384853080966454437114981749282088,4739229759958591334649295599424854432655955954287517912213597569502250150023192426249576133181257597090869245470242256174272934097508617180274802785425851556700817333154643929185825330049486269453049410315760063060060300773867433992976428473895933388104059320286367359084036012644394853593574323294698599047,1155642354763640840161317866632512711606463189115904666846240158382151567767869875575965412366883980252176109447698054839109820546539837615968386168917753356894372414795267678454138557008897676758489406076799290056896394919016510966326013771652656266881913835619564662608220574395369543699406086980500479286021
1002117978472811787753331928095730917976095264113100009019616793747721435107135088389509812754479746771762680547024275550906766428627777497396364614972130274470274918515966945652987824482224985008334448385591915791378703701911471719689908547324909949135740705163689874051360252727792128439306172396510982072,-605384264858430906616142488992272359132356724983679496986875094989266808748892270936577381465129550495430948251840196888998891525556778784313001078991820767039598015715393254809115469379426480017252950332375890914475777381882010670869152139638115965300974540658001803028482400664131564914546111105190254697,5913050976191825085156815974405378266929897129377882420061135471366299940142986781640170880340909029950997987433372868814199338484242838439841578708925504283923079897355159590243914836924282498902916652661483948536914918309139164893684671128828548900808846820323860573206533041501286493089345814823705125482184|1002117978472811787753331928095730917976095264113100009019616793747721435107135088389509812754479746771762680547024275550906766428627777497396364614972130274470274918515966945652987824482224985008334448385591915791378703701911471719689908547324909949135740705163689874051360252727792128439306172396510982072,-605384264858430906616142488992272359132356724983679496986875094989266808748892270936577381465129550495430948251840196888998891525556778784313001078991820767039598015715393254809115469379426480017252950332375890914475777381882010670869152139638115965300974540658001803028482400664131564914546111105190254697,5913050976191825085156815974405378266929897129377882420061135471366299940142986781640170880340909029950997987433372868814199338484242838439841578708925504283923079897355159590243914836924282498902916652661483948536914918309139164893684671128828548900808846820323860573206533041501286493089345814823705125482184|40380288636863554747802272146363479186663329648459490067115808757434033306882038739884681373117979723495792330864501446629245889731229516933727403492773771957483850679041758865017396807842498482944854723605982182982516939476048881995525535805104281408686338183559590430185038164235953706463250800021094604474,-39534865948835591455192703514729394748021266253728249692602243000799548352268225360374954844443730084878434721021241498114475458481167089270721522242274850596448738616202710373135498775106936938952151771547223007405550740805387552512761050820125134092471485389585963771433812018574391368483598373549383847189,156418754990595886837540510636676538980249340054775526675231187766083040611703861850669234853631535367187296945071108522620946681763860321505477715553908841995650918300850635601347255855518666703848642329714582982193362014895765955759528160104377932684150225067984397783920984799879483126817672124425872829049
10021358599463053436428121851639014288861925656265693598359693460594603335959883569550641125363212428397536880700859686977743945025535807563785786052244914761332363029072620567677261483868230251440566526595521949067385197316983806258145013751454322468391099167319094251906044804264200412596430324237392628100,709083183297048652772820333122772466256400885278203522245823989743215866042577745109340161132152908476855845193022669210873284198994493560336775521366659865852432460708969754436068709338598181470025481044065851120985245468046464349075382208377683917405549429133970439515821299430661611942330536123845644949,516570730285299534762323653103362077033679349887441156383985263227144702832028548168588332437855509742797208817471793880841971810641558363411834198813856099949994799818753787070184420373328485385171466383296907894871575302325766835865200237080249407408770698788688709844525521993129914019403957225364497263784|10021358599463053436428121851639014288861925656265693598359693460594603335959883569550641125363212428397536880700859686977743945025535807563785786052244914761332363029072620567677261483868230251440566526595521949067385197316983806258145013751454322468391099167319094251906044804264200412596430324237392628100,709083183297048652772820333122772466256400885278203522245823989743215866042577745109340161132152908476855845193022669210873284198994493560336775521366659865852432460708969754436068709338598181470025481044065851120985245468046464349075382208377683917405549429133970439515821299430661611942330536123845644949,516570730285299534762323653103362077033679349887441156383985263227144702832028548168588332437855509742797208817471793880841971810641558363411834198813856099949994799818753787070184420373328485385171466383296907894871575302325766835865200237080249407408770698788688709844525521993129914019403957225364497263784|45614503146354773723748422556503247371485318543120586857419562717702458851951901017328552145694380945314803604713256441070275022414069445773768101699000362770774983002903055045789385932735047082208988353464300453066243128392263161058473354625441431303590972274514200470903553097396578608004283743393727480965,-18121746874119905746733087661833019801123133290011543785996868679743860577167772600952885673213204134707814090152450287251108460725457761668330446170883400606809709199165941064933022535458655256850936026007055165113021346772772048647561510274730081303287537167422875133875982474754404203878182518086566378039,115286014209231820841785285504789236723202458419099047051127275140595097884705397561562945865060894329450657461353202401141562369532605474636151114816630008035888537731586842019104642780200033707263419710825605300157241899226642312799356394901240315456385563221341513078098381767868711376025198760539717198382
10021467180917602737976485607440169246689782775819592060097133723376896163041617997117690261968456452635527584517534178504548298348503697184587408892932776130526709512085862666360259215825375712520283335147827351975626062358619071671249870717811464295853663335144999169566479738875598518880232950110692415860,5837741371138928752178739797917364838658798118140089345232324713852930065920933839519905580179654383108038638880741427980662680469791777270068068248248823295528533080598248956003543247574941878960563240116001302598572351690506654603050328390643642345907246472180377442808566360199364409627306574545050404961,447367712945794368035040617182455309390859836657260473211881159345841479208328013611245196832742331205848397804369783648021077720443154207595416670723327933025826385393654289188255079761853719682847837385185400997339750661153486494578411301935184740783631461198583032914565210707960404049019611688784713553950|10021467180917602737976485607440169246689782775819592060097133723376896163041617997117690261968456452635527584517534178504548298348503697184587408892932776130526709512085862666360259215825375712520283335147827351975626062358619071671249870717811464295853663335144999169566479738875598518880232950110692415860,5837741371138928752178739797917364838658798118140089345232324713852930065920933839519905580179654383108038638880741427980662680469791777270068068248248823295528533080598248956003543247574941878960563240116001302598572351690506654603050328390643642345907246472180377442808566360199364409627306574545050404961,447367712945794368035040617182455309390859836657260473211881159345841479208328013611245196832742331205848397804369783648021077720443154207595416670723327933025826385393654289188255079761853719682847837385185400997339750661153486494578411301935184740783631461198583032914565210707960404049019611688784713553950|37349917633767587717677900017226055640277491797128368066909216648299856708848885314856667952257677125356703617528489552040640666031343260644627231518748509259039268948250724796991429094425535890736981916444739110193691988414365116633947866879178749608358114634543684726462828729304210028284694641568628398966,28432301470760114127472799211494908630719349909135890789013779669649467182102043473145513283547284407986093529470668063517370252190889483927419539271833812410008532555047333957640590516339384293520187649830718680466604203963675273404448810489933228206090139475240540056839557201036234130668781355507913201183,125217411042216743409615853418748212447815557938720716586287232669270939052168073429461670911284540249994159813915524580152040717865022372477773851596046555005754956888615646701914356508633194785367798807957000924761874706728044310360895862676117058335122487191434401996751617050877596333038588838996255145412
10021498468260956088123000232540981309673362233093607160766199611849988598018670545801586655713528191099718167654049219862424879654097800612715754405882205966256512537388088543329708772570689386840584832681600027519346949153293344313097460804932850840053785736778266237521116511372386612740914586110495537184,3731424607272136278046418371062826309603938690430502989163037797814883875895107208656392082954628965555189423854897982564780098075475012739517997385664143357277834178448678167762594236943371764347482562787414335427396456552673654489280935057856453787409277651050808844230948476551514072021069206021678774679,804130312590685641878596579775606667166276173286759021130255643061750446804433775305738231667374247846782607238734204509216228540137516790899866440807044660490591982953819190288555363659024778526537985822773652575997791262130221988665167762257066646395773224522658242462757313827560884465576118125526400301268|34167053368438934062493883132954265990697806318308586148616977663701145830016368570117108522767165162437388551633476818714638781998737588453423052906955047313659481428825017492981415212399429876112133486106544289854247118707826610748061980313138870978861241099932331052851628733408772936072321439631381625681,-3231990625187035132148669134941674343311291560670575472626948487039873506375201953961203524971750773872175368844083313789606744945666601496978495543448223413432959722175027775640416642119534579082078058359377011061266769493053544073177090778768228650034186796092538667273516567672252447273843436045477135595,235833074847574898390813679013790646015645150909185733872405459206523708909325302363230937825102097363178252008781874033668789787718772243559737247157023625992313606650868510119173526138833975525463395139358451436580786324137262685697090102400693677208248369147898653293586089386800659102730021728025849255818|64608837982278224108987963939830921137767130655870201859314566649037112194604993755919994541029928783963356571015929786284493006279718103094473109088356869444636451105877134516067500703977445578997872357043341015093673550983708510265625469154579844276561631683451922580837098594165662625287526508058436293986,15854906341458894966500422391448052536768193946037447623218750633953720338742777805649471066920966160101792990529839212517155533383911249825767111242302747793376405376781322851763232537121183798411448041082168628199040455135693063512226758138709898399548068871039436946823094929235771529576088321067557016361,125647737690478667744295859750549841902875194170056775019306475803353424716724181236654109541003077830795994847519888612974479612555855274394676374638319448048091194349835875247946393849792063872096400150096455332718354245732182310596592154379165437563189009506346555534189191250868232374253149843604451203312
100215518435515616798081693150831119413586767021678884124518533924984792516593586077070489902053827517598088670562746849336597165534172718871853401767137095032008213339529086616777467841346280017019578258259797551450310087222690828893461467525694138266456717327225955476876417507053206969995585955166268406129,95057958551667401403353090513192344071592935246219146691681088413017107538601166978955721880254187942559271242509539286042857509266018196345088028113071042234423096387755035509877692642793106294014825987119124937967036662120185797721977723389759564327297787909379686186622926363357951464215904895677999421567,102919326722329333489116060760618421823222867295966177344707558731080005177983472593218329502964236109795974387237881276225611846575332218440299281932674994159773703889896299379022277106535867836949285795306043775879545666098740309487810106763993748938964994198360229518682147400433454886610366004026941047356|100215518435515616798081693150831119413586767021678884124518533924984792516593586077070489902053827517598088670562746849336597165534172718871853401767137095032008213339529086616777467841346280017019578258259797551450310087222690828893461467525694138266456717327225955476876417507053206969995585955166268406129,95057958551667401403353090513192344071592935246219146691681088413017107538601166978955721880254187942559271242509539286042857509266018196345088028113071042234423096387755035509877692642793106294014825987119124937967036662120185797721977723389759564327297787909379686186622926363357951464215904895677999421567,102919326722329333489116060760618421823222867295966177344707558731080005177983472593218329502964236109795974387237881276225611846575332218440299281932674994159773703889896299379022277106535867836949285795306043775879545666098740309487810106763993748938964994198360229518682147400433454886610366004026941047356|97265337163108204413956364816446311461172514617683583383746668715450840222180976393430496104553022674333721978573099848181220662887846947468935453182046364733749916475895309307017567642434296055225121834950440706059303257140878621147190170027097598386070490643511792242136161870345758898813890460055238965518,87547457109798873839305649757452333043926932497015596041815056726077989206997009131840148396020804211298638181409067017194388111483773222118240882283209994405160200490126585806391098433830826470475358556954973925001096433563812177048160467037091694157852152308504545492956027258260588167152638099756708452923,102515957029857878751803789736896993327202543313952394340885451428025600212535749454672085478483321275958139112689603772374702592116757008616636478536965453679964666255956305064090090239129654015924433954512354305722977754010864408774189090428174122344384620043576093595618564991259055360564491303523423085863
100215518435515616798081693150831119413586767021678884124518533924984792516593586077070489902053827517598088670562746849336597165534172718871853401767137095032008213339529086616777467841346280017019578258259797551450310087222690828893461467525694138266456717327225955476876417507053206969995585955166268406129,95057958551667401403353090513192344071592935246219146691681088413017107538601166978955721880254187942559271242509539286042857509266018196345088028113071042234423096387755035509877692642793106294014825987119124937967036662120185797721977723389759564327297787909379686186622926363357951464215904895677999421567,102919326722329333489116060760618421823222867295966177344707558731080005177983472593218329502964236109795974387237881276225611846575332218440299281932674994159773703889896299379022277106535867836949285795306043775879545666098740309487810106763993748938964994198360229518682147400433454886610366004026941047356|97265337163108204413956364816446311461172514617683583383746668715450840222180976393430496104553022674333721978573099848181220662887846947468935453182046364733749916475895309307017567642434296055225121834950440706059303257140878621147190170027097598386070490643511792242136161870345758898813890460055238965518,87547457109798873839305649757452333043926932497015596041815056726077989206997009131840148396020804211298638181409067017194388111483773222118240882283209994405160200490126585806391098433830826470475358556954973925001096433563812177048160467037091694157852152308504545492956027258260588167152638099756708452923,102515957029857878751803789736896993327202543313952394340885451428025600212535749454672085478483321275958139112689603772374702592116757008616636478536965453679964666255956305064090090239129654015924433954512354305722977754010864408774189090428174122344384620043576093595618564991259055360564491303523423085863|36966589133632021596451231446360613869218644305972974964188922476722370035917724082641341991636532809500406571267262673636673259154835535079572834230006192461227395506315158937114124659074990425552664025796331234355303904150803244972310400202941266552149385712614489884410598364289566113507512621328083820598,-21149549205459986335385704446469107610959268704221609170214996514478740430167085550085863459876947711137447213809502018277525104101042350103376631096271919925064995296178696672186362840988476041323653097243744018198278462448741240768165379772727430920245528842325914682295445854217287403981994755438946746143,220927487842748418739085114242513506611909793723984315299233121420377274197319470229298268289856409101985756388437199198962449705412131211265923072982106236351953282676471404053070507026981693842676184502073850443982862759823135849927410711140706664324113248738142786497634534093355523248932828221913746822818
1002171279912987474674729832690970557140429555644292059472271841324924331291685060249454596336585889404705002700240738701699260928512934819245660001207610075089195766056310376194900771895925996113770666776022108500330653518924376342638824072832759321658474598385675431858595122771183526939999696158578609708,826219028959713490046361889088584439498783654783530925153550597879152616132729000468702177706363955325292708928091882754198698376648310966516057873159349764829040425546512821864182430231493467696041840597321743210951783900165181749863389211006249005916285731575237461143803624956905795631847651371075603271,8037828098286918052259824988376802356784599160404526733485731117320394626772712632224126968007402853349764765913068975115077635719542022449549397610278043584259551667143554443745235133704301422592616247052815801996895563245349515275951060813799742580455732670079073038616591480535324416008144264918698168050014|1002171279912987474674729832690970557140429555644292059472271841324924331291685060249454596336585889404705002700240738701699260928512934819245660001207610075089195766056310376194900771895925996113770666776022108500330653518924376342638824072832759321658474598385675431858595122771183526939999696158578609708,826219028959713490046361889088584439498783654783530925153550597879152616132729000468702177706363955325292708928091882754198698376648310966516057873159349764829040425546512821864182430231493467696041840597321743210951783900165181749863389211006249005916285731575237461143803624956905795631847651371075603271,8037828098286918052259824988376802356784599160404526733485731117320394626772712632224126968007402853349764765913068975115077635719542022449549397610278043584259551667143554443745235133704301422592616247052815801996895563245349515275951060813799742580455732670079073038616591480535324416008144264918698168050014|56177784089692916832266345214421120674340798487038570515623153805048107174705903801913422904686022519185882309714950449353350144136176082122642988743155385846519789014579069658520240091050781441562176069717906258293112423657764692478227614483398005555460543943687308770699629754468588531994448652035243537193,-1367086938896255072793415069058299472671169571526909227192393757206171174220534221238412428332819898373711167739278653738196147736460040492805449727552702294473184951105379473908985544436596593693459127262500591594358945429165046595165680187593280155590732587752336804926254680443537232304173256876819864345,143394353759539327949427865403227850259090677769631111628953936665415814894670562885615312902238352976078395198035416430261300974094600135242231268642783230986499797624830094698405716034919055851528418996945744623233014619026973652777892429824489371625486460871462705495597542593148226840678864076948049036056
10022430537581100668502883292824778933607339338765926026805737984600928768394291101969168677779321137283218236917508266473465030665219284863536608447940487677072083129795072785840083494425556238492937940196822995238448372796541954279303435932510765640503040286741618037016213243353519162818665268721728774804,1745450390765598318476765814191109791291817192933930838487529317598912090407141417101048723630667618601898718290746648849351810269839537783425961583377520701947088669609241693035013571476458016904170389418378228794668337339954300480921565354479003099904568784841604791321827362751710640603340143528678878307,505461416773210200375665916297012066614237052797213136609066313311545733018491487357728242574093909073856795981653867763762281713211234379922321747443616377604676750509494828442443340820844933440417718090216464110039019539088373064239526712549777394214168807828906636896179669124200810156121848745927583143473|10022430537581100668502883292824778933607339338765926026805737984600928768394291101969168677779321137283218236917508266473465030665219284863536608447940487677072083129795072785840083494425556238492937940196822995238448372796541954279303435932510765640503040286741618037016213243353519162818665268721728774804,1745450390765598318476765814191109791291817192933930838487529317598912090407141417101048723630667618601898718290746648849351810269839537783425961583377520701947088669609241693035013571476458016904170389418378228794668337339954300480921565354479003099904568784841604791321827362751710640603340143528678878307,505461416773210200375665916297012066614237052797213136609066313311545733018491487357728242574093909073856795981653867763762281713211234379922321747443616377604676750509494828442443340820844933440417718090216464110039019539088373064239526712549777394214168807828906636896179669124200810156121848745927583143473|62092481921639574438226283198332200678734028657724766941730022043809545444204108322446905830622252301375431538847493859046365695561521947886739278282380330944740137778796806258440017010320211759144908638103476555150573303911926239710190937911611647166321874200336757808613044926465128049757211183544247137033,-45250053315775064910191280612561362661486537888549446589078696876018947013616669550765115160411532144837380748629686624052593601626644191366587957076497250945144687082001936959339633808733565487985938465191480629685961056777143827741613522372695750936020580143021192692134512265227690413020620317312128938767,89818959533274049458857462069020739338602011671046728330943513188118466840658369260446327848180189713317967953477747595755322234416809755612045527023070344299134617743385420998285144607795275808302453674682604268889767229654448620219461284821255145925444306004911131336470833940664306256327917520781637949994
10022447467429108159774355787589122715485396978224199367300758397771363796346073591552810427326339622121413685155961164725589610901918895551781900417862806225664599680621980718988526130452221161919053852672286805155084312599146807342205269705230729665300558186233143844168304167857171548003707472393702474384,1188885044590400163258159304120537014931301063692806659646722818307638465604090862597898645794165661603569562151904733849823451481071963642820939826997500655539582070601901658042242359967350311563512079177663668335375683704849269904109356286951724174166294895547399547486092075854607019467491563004574181747,451886511793730238078310968270671960837012936994555807769579552350299617939295621484477388940254813126337697555682035175155312684470552706006082326229489214590934446980684912399661406451818153885180492656373585024394872163807899894979861799817481760468528780471201306793514412189815424515752868704991093442748|10022447467429108159774355787589122715485396978224199367300758397771363796346073591552810427326339622121413685155961164725589610901918895551781900417862806225664599680621980718988526130452221161919053852672286805155084312599146807342205269705230729665300558186233143844168304167857171548003707472393702474384,1188885044590400163258159304120537014931301063692806659646722818307638465604090862597898645794165661603569562151904733849823451481071963642820939826997500655539582070601901658042242359967350311563512079177663668335375683704849269904109356286951724174166294895547399547486092075854607019467491563004574181747,451886511793730238078310968270671960837012936994555807769579552350299617939295621484477388940254813126337697555682035175155312684470552706006082326229489214590934446980684912399661406451818153885180492656373585024394872163807899894979861799817481760468528780471201306793514412189815424515752868704991093442748|40311793122681847438147936825674014314470693373123318161207015676732082581716792137317735331938108693356512243120485847992937858572985495883514340613966135614307974866016309204238807033530669264492564117724246353883749827195305324197399377631361609176376894124562777952015115546002574992839306368859847102214,-33025539083635098527284543501358773726385310602673068647569756256609245347645406103541323476799319282115094670558563042038040727572072629107289743928712116480609261863925810781181839890265471330792670893248452312920468922228853995606392415425665874155050360471274554137526685669823510791388257867791420447345,119104774305358145853754696022566395542085319811674406549968528384273306539129655277119394569116384064134522924495522726505126314830673393570305912602792523829301472113875383292982915986048501532006750975293601050038174705411480721485112499986909208662941192321772927410908019836648310546774872889908741289549
10022730206246523605885847628248331589129959745152946800589982371582759735440896033124734292653525513269378463322751069994968860121969888496580966465696069881018097413525001416210515174455496944629883370533539582159385347137053307519490537337422600372155743988569466107652391801498216166822344049274248006914,729727310531644666459577636524370584122920562232400100508958613100574209791027073647329563436154072167135037277674792721862334569450792556614550488339055151138688316081220432057278684502305768700617734898572463248131416139418546546921772768563777642345566507958981323489827996692750181630164696164350792239,743420530670049129014551314283001582671251574132606225656558769248051872668919945335156046109684599461479010072698042194265131432439432111708952985059170648240550914992169145894926437588173425753889988734024781047390921725232442091277340971091116650569099484901188657501225210251920789312381353410873675482898|10022730206246523605885847628248331589129959745152946800589982371582759735440896033124734292653525513269378463322751069994968860121969888496580966465696069881018097413525001416210515174455496944629883370533539582159385347137053307519490537337422600372155743988569466107652391801498216166822344049274248006914,729727310531644666459577636524370584122920562232400100508958613100574209791027073647329563436154072167135037277674792721862334569450792556614550488339055151138688316081220432057278684502305768700617734898572463248131416139418546546921772768563777642345566507958981323489827996692750181630164696164350792239,743420530670049129014551314283001582671251574132606225656558769248051872668919945335156046109684599461479010072698042194265131432439432111708952985059170648240550914992169145894926437588173425753889988734024781047390921725232442091277340971091116650569099484901188657501225210251920789312381353410873675482898|72678153493282504157416115644391264652311137140691071678059939078869970502440343742868078709786102781757123551689967637475890683084227768997487411568948523707471659432320585674519265605598599734502760770267332905322559905487379207111063130039684891358469047921852095373415568614214678421199229135813148340086,-33947255666808860516772098102208086001134373039996489095024233296987004975315716216270171442041054094605710390151835995913332617034994068103936254773578912095997116516855870766220741602335129322709546766837859664219492792132163257557798382623121354098297535938342782377977312458602436715508338777893530715947,106484190269718620144286637065233814518223762302071472353291401620347574484719889974719727699170546479802692571973907348709106400438154108695479596777257546039047068390011589281587022778512291574952016353907379824791098458869045617748541670371657706126860369909581308416699070396340994092087729258233572584479
10022801037884735919398225401015346770690037220981230548926941756106963920408338416095733094536206053772963879852109190901255264805008288279841331919785607478274212775267264447609163695284184368267756738466008982331882800742073245734831347575593957813641726104668466028052775256385701674654962758632735214325,-1581758127940839328365881014818315360646059541554455415456767586268677829342640676667660057584626141079060910685268398574862315277919005616512245424342499450499940252940175197812452339693288044870174334000429767858420712066019926176503980859313840839446940401868444636117019979796283038985302067912785275287,496761537019467923365643288264945659788228256979170730808696057920098575449994591930452099194380843846370073248896650848520976197841222484748214967557803091427696552713317560221122191533744679546984546053333189737767090004462878944114371161170193473185997313558677097782867340116873490763865370370260817678938|10022801037884735919398225401015346770690037220981230548926941756106963920408338416095733094536206053772963879852109190901255264805008288279841331919785607478274212775267264447609163695284184368267756738466008982331882800742073245734831347575593957813641726104668466028052775256385701674654962758632735214325,-1581758127940839328365881014818315360646059541554455415456767586268677829342640676667660057584626141079060910685268398574862315277919005616512245424342499450499940252940175197812452339693288044870174334000429767858420712066019926176503980859313840839446940401868444636117019979796283038985302067912785275287,496761537019467923365643288264945659788228256979170730808696057920098575449994591930452099194380843846370073248896650848520976197841222484748214967557803091427696552713317560221122191533744679546984546053333189737767090004462878944114371161170193473185997313558677097782867340116873490763865370370260817678938|11794018787280482940784484560654447929703367834543013693618622456325444683498014462584498990809979794991029406828035162064888206099231897450516338131683344468341641773247077777974904033180523619849644665052604243871182886239709602918372696154159689574416694382901020412810986466933364313296340223658056711860,1521303582082972784094072429213245037004474422912041747980341661334088522130166480999863587718878595218681652383126000473728595142115360315778132844751721718890137106680913339185860894697918722593994440198312742439897553470706013918108591714015302153342792691194124679477731145179750991721088470556891980683,422154249545788907790313192562529747503206514258177376656051975747255059759645179919603489351691318624495599133821906453410850735326793444201922900151270842818708202863054380424556183873836633029531584190623724167592312286966999660766414372084390763660497972689763908414494950088490657933080790950343854684683
100229993686309443431652234853242745584964039848901396902154758000675611952948762456754223980100376888310959032918053199573371179952836402943594446966248713771392255748269391671122973567354604611827710836480143363448852247469233467634585666281897503837387248046923275198978369387627574778973203963568459570613,99141614774063628352404317381455383177814780210220526925227232275804977777537108958838490639289349073928621828114260050626184229387757267144939794360548040966543453766396248232212371430223357646841577045712198699745634479223254936354615654319866477688010773948549511551046967361375809493630740150224195152939,104882524400956127942658813062851389442407913609672222789148495255743494809906874598039501219688723468166574648371069153919928988258063568059818823680918241728433303999086584504182405446032391227196284068159574388579981415818096136448105143139694516800086480906674126689437313489030594417564677758780953521314|100229993686309443431652234853242745584964039848901396902154758000675611952948762456754223980100376888310959032918053199573371179952836402943594446966248713771392255748269391671122973567354604611827710836480143363448852247469233467634585666281897503837387248046923275198978369387627574778973203963568459570613,99141614774063628352404317381455383177814780210220526925227232275804977777537108958838490639289349073928621828114260050626184229387757267144939794360548040966543453766396248232212371430223357646841577045712198699745634479223254936354615654319866477688010773948549511551046967361375809493630740150224195152939,104882524400956127942658813062851389442407913609672222789148495255743494809906874598039501219688723468166574648371069153919928988258063568059818823680918241728433303999086584504182405446032391227196284068159574388579981415818096136448105143139694516800086480906674126689437313489030594417564677758780953521314|74350434749389969050012184990337127551177662105941520713519479144559556197790064845857130327167806787623076521428876751871163669518580183330141936425233250661556229643890019866856080560251792692090494599862764037832371889499003253542457382200017573287275373464647146587627430764219256453016377003846953421792,63957711791573361964387609614017192151897432836032720396105880275969302058600840013396804158201720534370023895822842857827830012733763196699928990175961939998886321856401382898475734879783268690655497427397663979021512999064707392335539401656442120559970485354029428771216688798043679886727502284879667604695,122094202522303244187343830185980046602374556531568820744954812272038371153739943186637285289631950376927966459293327247925407412742819149064968500238603572438294529950547276948751033111097715894035925769404645235126181286620345914299937264438033627270225587240098530161700877220337370607067995020225846162049
100236185197041329075554833621063049933091933804804579181020863476728313391686305869039610612323226747485959655907451027539483829746780221656275287251359920572256326848112354466643258852396004468792417619989592999892771161118188446161121453052287245392349650298061886772129843629230859327769032485896380376,-23246228755139486121091450291914215536752934295258164744923084651696211557139982911633633936256958755233390860799953871691506689375274550434281909010783595844874773750530708001462730196953616598369162178869242223651107363158755851755977149870788847101056032248840046983417481075963548958473469668684959891,56573523673680298471644280373809509686143659597565817726545502453421314503494549466829923326874504507298291631695935926527600390521472116074127195438583945763976558015737054829572336871056542824657451863625497940311479875421301704568832621760721804490304525701867696665290350769186367013604263730372702025776917|100236185197041329075554833621063049933091933804804579181020863476728313391686305869039610612323226747485959655907451027539483829746780221656275287251359920572256326848112354466643258852396004468792417619989592999892771161118188446161121453052287245392349650298061886772129843629230859327769032485896380376,-23246228755139486121091450291914215536752934295258164744923084651696211557139982911633633936256958755233390860799953871691506689375274550434281909010783595844874773750530708001462730196953616598369162178869242223651107363158755851755977149870788847101056032248840046983417481075963548958473469668684959891,56573523673680298471644280373809509686143659597565817726545502453421314503494549466829923326874504507298291631695935926527600390521472116074127195438583945763976558015737054829572336871056542824657451863625497940311479875421301704568832621760721804490304525701867696665290350769186367013604263730372702025776917|15573203821391096660668742152065727671791482748659900060639926963022005424305428598384096201045285103243110012385503647750757013115954608677386233978142224494513680866630913236076316930192686744226921983870965664346251492074685634583531334565997695428546882772894918870424603926033309071559111059501203642333,6451721584690521069581901111974092204654122587875579916279551744658661205413364185368986076832511568929170794843492990781144450828332965740817648161987976580582338126230945095334678085775013660661642032765404588316501300352495628863315640949745573214882043885532409624351786399389352651138436910377540588715,364800994330757396882653090957020494991186585063682233319677342832051344502776958834410035811370111943816463424448302716551318762170472662165419035921367121365358358160571142517808605560056227966869017916492144933000445349984077920674346135535102210585266868874844995392794923436866721883251932973852604825116
10023667082494025533694458923906062911614808800770741660171152481026059347510371753561616097379084784341713671154750835715019868680624888814365226032644794597463378220681171484265152741451558871527205613714299617780955377578029153710181790009777505367079339560569389236075705577562497976407198835496123421815,8237178824212969139758302266371465433903111044341794615829413365403141507594223080352356455683475273814082845524013102162873125179530876016035628585832833134556337909718743386830931466874558092486241907311137385119488677802975754525714977343935483066353264879509528297193753064624793968877384112576484389591,423224971588853021692214116546653537988666116441804013450094782696541031203993989512468938158606185066216192664407632356213925851579704646681338385590758369803509256824915492724160624602987883926813515751341908451718832678074898298694978135986894313441355375932022035725661361883088309484290780962315557040384|10023667082494025533694458923906062911614808800770741660171152481026059347510371753561616097379084784341713671154750835715019868680624888814365226032644794597463378220681171484265152741451558871527205613714299617780955377578029153710181790009777505367079339560569389236075705577562497976407198835496123421815,8237178824212969139758302266371465433903111044341794615829413365403141507594223080352356455683475273814082845524013102162873125179530876016035628585832833134556337909718743386830931466874558092486241907311137385119488677802975754525714977343935483066353264879509528297193753064624793968877384112576484389591,423224971588853021692214116546653537988666116441804013450094782696541031203993989512468938158606185066216192664407632356213925851579704646681338385590758369803509256824915492724160624602987883926813515751341908451718832678074898298694978135986894313441355375932022035725661361883088309484290780962315557040384|26149581659024134542252839056088737943459101230098434304929833472689045273647101980834416767117184344850968739815058973073425320764635194473778310753733774870500611744687135320440722493629102059325894273417025541554717397282491317870553755571826770905575804901409545560793682652830798005534542887045797606186,-1697969983698485305905454448895722929114256960413081228420951351866600414430800217182268923658152076765210118720420817273440690524435493363475828642615467592516719174944772197605654745416391960101282581330420264887754748587983051609045080004443224578293135292425351561632174977350140009380537152490928076887,161609629862554141142708472275797044218689904367615056614920333643328937851927686237891781051003871507296405842898237370248243352582987628460341700892139196626441792037632328670727659225186548971653052724874684965299456515833967561157293186033533538079205556741150926459475886439855496878616457828726831550112
10023862893594232582190646068648463209940952006884955056666263414474264317722655546318247009455771884983355234222787422801894657323776793269825967901010897328305149754199815134059038386803327107954623997783328925014573712361190412041544730846393144970158584993932522919092961533807689663994273510181230611975,-2760322820547873699921094239708262618123220686640344280427532457964735913231839541155448488755106353058077772483391926518490758309421884945189004380274532339303673658136307214150768559915038249044318636340829040623019533080008795877188365713108541851533478868182315253939354465782006188226272150540248455533,539774532098344028178575637715654362402942864818067869426574212334581836029933543954242820122684669884416483020859433711413498388105161261765872011520166122694643001745601237406507189268543940858796801993814111596277340371144355358041455940732653675597524992815557778776692308187755956982584432604519599405036|10023862893594232582190646068648463209940952006884955056666263414474264317722655546318247009455771884983355234222787422801894657323776793269825967901010897328305149754199815134059038386803327107954623997783328925014573712361190412041544730846393144970158584993932522919092961533807689663994273510181230611975,-2760322820547873699921094239708262618123220686640344280427532457964735913231839541155448488755106353058077772483391926518490758309421884945189004380274532339303673658136307214150768559915038249044318636340829040623019533080008795877188365713108541851533478868182315253939354465782006188226272150540248455533,539774532098344028178575637715654362402942864818067869426574212334581836029933543954242820122684669884416483020859433711413498388105161261765872011520166122694643001745601237406507189268543940858796801993814111596277340371144355358041455940732653675597524992815557778776692308187755956982584432604519599405036|48715243603698629821940426961114291788526831094737919680655564244368028434506892148169445801801507062147482077938401141271200004998443292904217897448972538551776558146708202066192286102689914350481841990540885514221263570815029978710961611989482704700171591369852446182654047272669614885074291437285365544460,15461979039278362276597154663342472093520340953601325231902305531667625678747495978358134272949704300055117324152966543774546452680787464009096008897144630532639259858616922948118805845884304673520502690819270668894425836172912196918903901652212033563796089034742441883378992888990103186375633458530164516317,112254170401540486949707124025758283679636240637378289192656933481574624585762302045534446659987957789349537165930984237831795400327841686426067814232036082567083362372524941094990583657803451112651533845361102072607539347050570081691100018981326399925221570110823787216043908322347678600920061436414622205345
10024289314253109068181408824584907548682813194738591861732979563130066037537322274697443177137048505246344585833979570630525401656305713560413859208020518275537432959569499157916033857588787751319126726484190263493857704290501320067515311770609186057345956871152108834406551727855172143151298819670712846606,250504711193651543885319560950205973661493792695329060474635142907355144915197487552594082031949875905008463463563678142215091936373578313885813322111597330162926418717728507984924427400756505737871837782137693463723537653383553918621336520844369928180694979696895523967764933497235970432812594037072497051,715621301200572432492975207084152505969843326949635795107806123209445143151718517449817068713936125495042559248838811939558778417894618132276860461288711015473626724568542195567695133648202437411311798035098899324593482673311597084169133485553033610858821471717692594066324611630669968328053616507731719142856|10024289314253109068181408824584907548682813194738591861732979563130066037537322274697443177137048505246344585833979570630525401656305713560413859208020518275537432959569499157916033857588787751319126726484190263493857704290501320067515311770609186057345956871152108834406551727855172143151298819670712846606,250504711193651543885319560950205973661493792695329060474635142907355144915197487552594082031949875905008463463563678142215091936373578313885813322111597330162926418717728507984924427400756505737871837782137693463723537653383553918621336520844369928180694979696895523967764933497235970432812594037072497051,715621301200572432492975207084152505969843326949635795107806123209445143151718517449817068713936125495042559248838811939558778417894618132276860461288711015473626724568542195567695133648202437411311798035098899324593482673311597084169133485553033610858821471717692594066324611630669968328053616507731719142856|69691918841176288984823797473901681196094628879675315489755259444998436434953893357490252440851727841764856894926617359858762775119043951866997363697297297444653923770370354552225052699848341814307273549886449783549055935119439453155817735871573060612568620074695549908654214345458834165261842993120064731877,29396998803244259208706324369693841135210373137766178345587378836957006029896347992580130862460199303906902776177861781944189386331882004200746161097147483839158568813322086972498062377955537624817737605600339132204987534032119897113967273038860438816060235575010015500174845850861550917579850703027368690837,106032740697299793989572674990101926746114173477172287236417937947154096127701068054351010022541808717403069236123423199088480578855329299917113038220143550055260783011691574203288951873393089140671443554631887510834797278656898859315134431047639142121497581377857339388563046962362704012299890107532747273864
10025428900225290685290151690469854982214932916715816521705584076773008242243937008766386881454192668460673460928145859037221457715710934570710912601758825277917537132977601878466722300639421318388444709119075347515835153260761313907776418189378977092187686581753209864749194659254262457796167519362282389944,8035407417908027120985682166291560102987169154314800046344974577695327891178900017914738842677039490694291401465931876496716613929624358740551659992744919248664062419629947961043318471204322567520912143542047278378993142962380418872588429956261466474640589358106914252999077869082097127384356318300378316515,526506212965607285294504652802203087863317784238837123201810456971631654056439372780456787465506517550858742170829690899565417756124817089047569475165769047941621936008499130409010932902058625548248971355379292220521819976269615165269965092960486278068237861168382524126578791019346639264332649030378056985183|10025428900225290685290151690469854982214932916715816521705584076773008242243937008766386881454192668460673460928145859037221457715710934570710912601758825277917537132977601878466722300639421318388444709119075347515835153260761313907776418189378977092187686581753209864749194659254262457796167519362282389944,8035407417908027120985682166291560102987169154314800046344974577695327891178900017914738842677039490694291401465931876496716613929624358740551659992744919248664062419629947961043318471204322567520912143542047278378993142962380418872588429956261466474640589358106914252999077869082097127384356318300378316515,526506212965607285294504652802203087863317784238837123201810456971631654056439372780456787465506517550858742170829690899565417756124817089047569475165769047941621936008499130409010932902058625548248971355379292220521819976269615165269965092960486278068237861168382524126578791019346639264332649030378056985183|22138319840700167895312881508181272807615611642960031764554010440709354488166777949391350577243475719290294812551529754345491786841502661934416467056115565617682227037416000132315258676326832664293472268496755124942179527934459542753167413348749025306046598965185451619481594689484505194124705909904529437016,-11131863740438194145696527360624732907005872365618169777307266620259512556501908857842536958655885195096195748687569086057992329814846073549253878495916056982261048696264863065937434987201822416655310303356962123778695372607503843603636308900759414300401601767853289915741229529512784406304245742359645877437,239100722014735247362237833086276623512072741916888955896402203382427372194255695065669877432592987292352301916479402236621014870053157629159394772682571609781590319296070407875820019520943129073048256367075297134176669670916790346961022995994025660850270895833918044332478002360056773821184240475743476227793
10025696373056081323076067608649787757301021243808185859274808349280293058956119916709251366791092102112010300737183625444037192198725817688527600134257833611989912831501342672141015848343142445555687647450237725473967806277927764282835935236016323094913726640542283793306041765928288192544236949963888652742,-7551573577419239436071851881922105087510160439185121186338107875456959549550841973546977393389532111591614312842887678906809652876632858754122403767673808362967953534249136664179536748454994677273595591516700421480181975305574013927943181245218443636797391029556909610245497977668952560989113626530355626403,488551202347944315504020596344859283372184958565644254623325222360870646703286196267475027122265755221917465236349901297478448862017138325309245093096937651510172757567584161967211867376922683411877153052678659984267061266457787269417246896692832538104568250487618601354692837088103049130077128213591142309282|10025696373056081323076067608649787757301021243808185859274808349280293058956119916709251366791092102112010300737183625444037192198725817688527600134257833611989912831501342672141015848343142445555687647450237725473967806277927764282835935236016323094913726640542283793306041765928288192544236949963888652742,-7551573577419239436071851881922105087510160439185121186338107875456959549550841973546977393389532111591614312842887678906809652876632858754122403767673808362967953534249136664179536748454994677273595591516700421480181975305574013927943181245218443636797391029556909610245497977668952560989113626530355626403,488551202347944315504020596344859283372184958565644254623325222360870646703286196267475027122265755221917465236349901297478448862017138325309245093096937651510172757567584161967211867376922683411877153052678659984267061266457787269417246896692832538104568250487618601354692837088103049130077128213591142309282|60393031392510595353689024388979736338459176869905458858711562614756995826747740419365757994707737913997543366818386810567166008495382740947599739430340534765458717365457600414802742877973222192406990314478073640352910084093417199594859293029865969059185936671473103965892459853411850141569702842003428649274,38329753573953857590669151489102652306888210200689056278625104334993443543324622863340848043537460677248162565965074671978338401303611611484783137870568580776992301362308417714890643838644524909137849140837295996399799637901901974938629017550061052634048860038885099946489697555545683915123490961748882032563,86948805727102164020528697795654924433436758890959241635759391106001442581272485956111792521204085749386969011988358799013634480122996757146530322550896381169828204152724081141046858586814946327125019525970600049950459272456428386457599502469581747116784271717706447744628609754739530433937342398267975398266
10025795277027889904587708106143218928217212795791943900096455901045016119560329143219194735847213817310006544292588010221295347093799623990992065640705758739633420740707391553060038825197435786302291280814741597987499076013530747593280825513696921556065232738339683658383829389180388637941998690144811369597,5684979695119467447669475199616030835217750876317308626399899267476547529035287916782085067945907170746605510283861183133612038067129245932165458949837306805149633974813244043762392619755476811530088171886491397765159164208502011381649757076514242464099478526057069033992519207091422655970324739132300656901,562007444349085595243678168150362315344210015071199683818344834829191775432825810670825147187078104135705553739701002486305372357596398874560795249464367016590567012959728033251032467564115881230202627660086530992291649152268041406000599974523312325932278194132351429623587227242904398909856612628818780435778|10025795277027889904587708106143218928217212795791943900096455901045016119560329143219194735847213817310006544292588010221295347093799623990992065640705758739633420740707391553060038825197435786302291280814741597987499076013530747593280825513696921556065232738339683658383829389180388637941998690144811369597,5684979695119467447669475199616030835217750876317308626399899267476547529035287916782085067945907170746605510283861183133612038067129245932165458949837306805149633974813244043762392619755476811530088171886491397765159164208502011381649757076514242464099478526057069033992519207091422655970324739132300656901,562007444349085595243678168150362315344210015071199683818344834829191775432825810670825147187078104135705553739701002486305372357596398874560795249464367016590567012959728033251032467564115881230202627660086530992291649152268041406000599974523312325932278194132351429623587227242904398909856612628818780435778|21268893649707309919570226960346372728495718162766890279898665692070832053021527941744710318344298178920800948932846738089018664772788493927580517099544523821251022066659574678369202749060209753445042621950578890219002532761197990179516522502045501310564866950615799259252489912339574839719060814022687315833,-16974163508967143175633640446755920949410222455507178592573412674696095005693865169009177473634493301741992193686041205183814819978515841920175784743689108590732720018205453159865088935842801461210617037675036778351747079803439546961298001090840400908639940207556458714733757110771041917290102952953525885901,267927541659497862467954399158595317217757334505550228883969422271210761133505257969057962914766286654857630940214532971487737583736851759345565614399969808206018020458924660929875641469250964043761370010683938550578868703713683401770700995854517531350144574746588257756156838858326386968013405064043171677102
10027231464587935675639730747678568553908782143975994882531107664457436183429164280181747996889942331170488347016005448660418260392761004178712470722876674735769717730721096608074660784751458654872470573207263246635112395824536847938300087322544843942058256547417838850894365569811278659238183569174057618461,-4440267082761131414853294025879558077404333378765096794740543986499915534978609296838455472705453725784503668845242671918380807204902116758601260037461056825902249629220350908043324356588944839161111532952326818438147003761862650635018374512533491039199092599100710336766544058009407418500582600655649176731,648644865497954786776779349508457974872894617589720812073415733603605246322174185807123848556285887617844905639166726609275182111944451202589938026255239735903760010573449137429043799240258539000988138770732321918291392488327546867698375214486961050410251228096630089455328472100573545758827677160537099320072|10027231464587935675639730747678568553908782143975994882531107664457436183429164280181747996889942331170488347016005448660418260392761004178712470722876674735769717730721096608074660784751458654872470573207263246635112395824536847938300087322544843942058256547417838850894365569811278659238183569174057618461,-4440267082761131414853294025879558077404333378765096794740543986499915534978609296838455472705453725784503668845242671918380807204902116758601260037461056825902249629220350908043324356588944839161111532952326818438147003761862650635018374512533491039199092599100710336766544058009407418500582600655649176731,648644865497954786776779349508457974872894617589720812073415733603605246322174185807123848556285887617844905639166726609275182111944451202589938026255239735903760010573449137429043799240258539000988138770732321918291392488327546867698375214486961050410251228096630089455328472100573545758827677160537099320072|46009921711915221172675762660378602913284935911769009327398886576025556944392570855250807675821524214292205195685897041743100957229886916848065466280285331142834500895832407569582736664860239313946858454701727263963934792933919730548918244937925570913918752904708052633399310307728141781833372082621654521012,23113475896105025107394605331889841460333790037514477610982037645403180016015663190091781841332002225731097821541822074963875072814544317858697958764287783670995655541483455486482934375887626558700537105583870368524253911345190227270218382103667348149461739557925536602713765457923023851021682724701425292285,144158936962616263074854848511540730235089365933518189341717329619972562457005307870230026030935456404849352326770086269924745439466300887545713518178631945541398236558781981355199214433550895067837895099984050382102279411033270720567051341019780619857285120976043103941344405749600962507460384488305160927409
10028350739307738239553437040783010537831658077620987335136512740169676263676747904072610524038617826531776850363823183733316438383606013506243196250082245650509414494066287488240898643357609392647649696817421880362011995934355791054933802156008906495889209763185641418699747996844644309107005112769042124318,-8707724909729199988066303291337645249173793540898282778024990496827621579508639942367666079187451324678862416133361451354021503910330702173658524643590899178624105480074443491370735876152164927759833250717689047284841393067105491783984924710355073809596596309834373465404107419929383484013294580151001556205,709758849546988349416271112886481225556022674837057904210411294800853958134290458192748393663317224087035819308413648727887254453418237510262143014913358121419251454923066768843049946946235581252429358021933518874438830803109875124372809973223871915099838973789742920465584130081571378073407884375094121268086|75318449301263415467735932548665333631833209464496019863964846786179367552717568503501179580307848690931127517090493242442668414948431300766436151276701082711193885234526326365772794857402011587084042826807831628195071551088506032974178171732912459672450935320336391563419572190330442739927553072512433668492,-37666884930926310053453757600840503983118095033807980727340808659295811653448510252245931091899049389573453471548035871058367468721695376360491358764096189091201995027259909431928638716214539254513869701208949761595174662474754859884399931318260163661631099379190898913272807941135716989109599181870658955411,98959195118263740892956000993748226884659367220332828268929254332674345256309662055166848715197441404549693155497652798902798133883715701424760429622411156195661335500009744018343869593442437677434882815576040667549098187431048868332096738149061496080175268157896224795266747997461998351291015430290846127991|78879828918733154172761232408717349879484411577276118445906917725867063887736403698268620449039366903222875325557071665537210036919488537356651491469585633888702020869953229589162929365722510146484615161939420331780149558523973332122378453822513488024388432239153051455307708434618917487055946350509115159954,76022832032228931560745697540761625684085285731069434889900171934534714627230254695020398894919788417337545845925550378316932977023401785630385785258013781974664129868656557307645950862628223235191878262315897562597443878541677560567949780990105397727409041603839660905756066382442879369790583798789010488305,108311876812780092185464248430819211209817518273155531596997245418001592611818208219323720419932959536655772814492616252593108875759365327114882816039706034356112007450695439375062874008822159624139628714241658551452565287963490475631456873365249553095821106476912177956653681222238113836907581862856535718737
10028851844651833483859929571953137249991455639548429827963027247884276614126582614765754168788406967864569784762670102265610798647378386836840906226432130520069813697908016956233348000504802826879321612396642793367212498698674853695626535119160503473498038239103440516242421347929877540717111105756485685416,2125595786027029524418010744012416366895751257304333344547068089057782417304598028459234751630103098379533864111162338454453990302791615035666668646880454521909199231924063610130346480860493194786475025500179927152042631414216166076205706865335089506746163544867373884186074330874303125032398057106297186863,800913161978634698742609378449357774955505407483415355913501780948951093468088505693408572348493350961801168010893237963412292289122055848739177106855852125098292236006510856110523212361731635197072591774393685461794786770421350652687522647241859653967881884006552182286419954577117744245767788677817306762852|50429916262905224121199165505326103712322633321578675412441680250060233972857110270845245669993781820897616267433177701631160063889458653764653687193369398981186203131244488744056545097485284912257268749768458331368107477031080466529105477483573960360042156349879055924595032652993263006931935621163071940669,-27065457947223595691396496360583757525811978893552969421355220262690251856919447274985744020030753772138102799000695707517100290349316439468276434701083568894717249805760937039437729313480400330251378090593495078991541936054800615447964857892934462412215184000258243195317080477356913381022045983896051265339,162884360410278142867611075754290453359699000687335791914852080089316910769333692647979960993562595617317591055325367385753910502341805589561432506963888415490402296553372275035046411345233183682360113909981999769321373626395576042577426393704313732652524189312065702142816306042456646293512481995292218184630|53997723292458827021420578276444072896002053124414909531202213558828743141566632795132611868503445251027453958158504792518315802051451653007369750551307662332396699632827748059470875485288011830316694909885816703989889585271656952405885761371722676008299809654786389827849524552375005490619782071967768476620,-3921961296864439599504210025762424797468664702267290731411285739993844771294339132594454147684650522033462891630908841344585194018116919380259122700777039543903609394837238783496880317096351827072103366260798880944073390853134441762823497871536553346031444078137460262118850735234076150428857645894786599751,148801743068668131617014767083337764289837422117725728166091414005082627848729316116752646484455568027336119364510594603975358934000097718262611755893849397982664596027513725455266261222215386005085253076887565120162601272630243587251846986242350641739720550891898677287459766121608903079025422071040317411427
10029389724354647916501896404393742667486460299990236556418317010668116357688170330436730152626311842309710400719826928488284825527027730454134618086311842571929328216480439284941404499751921093227604323134474990591797348436817566328316099817073417778247297081309102907064789976846493401165211794614652077581,-5748548483444797737722189452249937786310843486604864328602367281135708748614533947090219774019556230317272055169227525539578087511031078860820692360107715435130140444616499305586047090927584090418666083007681585523416727535418733837425822999564006750813702161869964846496575730545650729911357481033875975819,719895727819428792994563756994341424767785889195228293344753744212732679301708252203825226413012156273021174986595157595824763180256881701588113889797640827369987995936500880423386237711358833858185065722206691788564039408747808726964665919487597212670306097386648373066512338291830265434985728533154609458396|10029389724354647916501896404393742667486460299990236556418317010668116357688170330436730152626311842309710400719826928488284825527027730454134618086311842571929328216480439284941404499751921093227604323134474990591797348436817566328316099817073417778247297081309102907064789976846493401165211794614652077581,-5748548483444797737722189452249937786310843486604864328602367281135708748614533947090219774019556230317272055169227525539578087511031078860820692360107715435130140444616499305586047090927584090418666083007681585523416727535418733837425822999564006750813702161869964846496575730545650729911357481033875975819,719895727819428792994563756994341424767785889195228293344753744212732679301708252203825226413012156273021174986595157595824763180256881701588113889797640827369987995936500880423386237711358833858185065722206691788564039408747808726964665919487597212670306097386648373066512338291830265434985728533154609458396|8560998041202342563145796199673331908087223591151890019844277290088279806853407215903188817680041281745686724901293662893322531582604865370359246593736212994518909947445852055733198112706083016676348016714291995623917124402224705247934604030962953619706293397331305385867121828720733169551586472433525366937,-537975643989974344334263003423538768209474800355518283566587248897859525466409192148505701554962331296631250873445941844817525452815362174465113061273994639614043454341045805645253425898526417994404807933232055819444976823823121190979410608683098711316112363065614462414343124780847750195760827288806749811,842416466225224033183393216850362224780744722633748075411867357471068659147784175969996596348967969848559647034288532517371764252498077837862667546193299637156461175039504339023851201930547252305821527420041035325847162633397442876512610187216200063222815713605031344575281997919080197584636819283493689893368
10029462828108406279939177067115161395010840703955688660855251935920272008672857135011101256731718086932191566776707625465927083826902687987460773347952918706606341231446896979494902183159052228641287627294356517943283997224691515527031637969828335115038316970291491432668820800917926368076854280638205187309,-6629646230072911423556297764360629625589965368903862583111147478898388162363395818084398589541887766856708633717083099875720612184669212924373539095145308857941719336023981955297255371765324592355503775749174475673743444341624220885937903545914339945102711106579165895756968511409705213351719512183267438507,782742743661597372172423816386424221021017552503284524697466177183281891845425353410464186233869636520966594583971179297268228166989165546064661406781232750204176842910595282543729669785450570724055031796400642778914378223882150571438409693254554219540729724954243581265311980228274664427499269984624348473720|10029462828108406279939177067115161395010840703955688660855251935920272008672857135011101256731718086932191566776707625465927083826902687987460773347952918706606341231446896979494902183159052228641287627294356517943283997224691515527031637969828335115038316970291491432668820800917926368076854280638205187309,-6629646230072911423556297764360629625589965368903862583111147478898388162363395818084398589541887766856708633717083099875720612184669212924373539095145308857941719336023981955297255371765324592355503775749174475673743444341624220885937903545914339945102711106579165895756968511409705213351719512183267438507,782742743661597372172423816386424221021017552503284524697466177183281891845425353410464186233869636520966594583971179297268228166989165546064661406781232750204176842910595282543729669785450570724055031796400642778914378223882150571438409693254554219540729724954243581265311980228274664427499269984624348473720|78667156036256111077611624900655903416490936286908879028793529978954307476546731244382117972535629204391216663640753691624585098486838208251820032478479477157140644001833697695041181016581251701307504852404041540782811897181398727717806959310986773271700555774873273014053192416692372242335858566589217791557,-11681938670990905592355073596188490162953864508666802257304897456361955348551384361326321552281799532866414312577544184561189074950098884814900830627703536569755802878449922371901033061871486784064588452214883192668082672979794267084922475962025561930112420060063420934779749780994794637529679089941387143427,100087743332058471063169855843669770171915090829420561680411008586982501053400685795132793033729482971332564612241450018617179058547543051543609602249472699027915450803902552375241387388609502154707845080333148480015751381946173697011349301767118798190494650916047348538729674905622316757245591467381527471900

38
crates/vdf/Cargo.toml Normal file
View File

@ -0,0 +1,38 @@
# Copyright 2018 POA Networks Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# and limitations under the License.
[package]
name = "vdf"
version = "0.1.0"
authors = ["Demi M. Obenour <demiobenour@gmail.com>"]
readme = "README.md"
keywords = ["vdf", "classgroup", "crypto", "cryptography"]
repository = "https://github.com/poanetwork/vdf"
license = "Apache-2.0"
edition = "2018"
description = "An implementation of Verifiable Delay Functions (VDFs) in Rust"
[dependencies]
classgroup = { path = "../classgroup", version = "^0.1.0" }
num-traits = "0.2"
sha2 = "0.8"
bit-vec = "0.5"
[dev-dependencies]
criterion = ">=0.2"
hex = "0.3"
[[bench]]
name = "classgroup-bench"
harness = false
path = "bench/bench.rs"

223
crates/vdf/README.md Normal file
View File

@ -0,0 +1,223 @@
# Verifiable Delay Function (VDF) Implementation in Rust
## What is a VDF?
A Verifiable Delay Function (VDF) is a function that requires substantial time
to evaluate (even with a polynomial number of parallel processors) but can be
very quickly verified as correct. VDFs can be used to construct randomness
beacons with multiple applications in a distributed network environment. By
introducing a time delay during evaluation, VDFs prevent malicious actors from
influencing output. The output cannot be differentiated from a random number
until the final result is computed. See <https://eprint.iacr.org/2018/712.pdf>
for more details.
## Description
This VDF implementation is written in Rust. The GMP library is used for
arithmetic and greatest common divisor (GCD) calculations. We use class groups
to implement the approaches described in the following papers:
1. [Simple Verifiable Delay Functions](https://eprint.iacr.org/2018/627.pdf). Pietrzak, 2018
2. [Efficient Verifiable Delay Functions](https://eprint.iacr.org/2018/623.pdf). Wesolowski, 2018
The chosen generator is (2, 1, c), where c is calculated from the provided
discriminant. A form is represented internally (a, b, c), with the
discriminant not being used in most omputations. This implementation performs
reduction is performed after every multiplication and squaring, as not doing so
did not give any gains in our benchmarks.
This repo includes three crates:
* `classgroup`: a class group implementation, as well as a trait for class
groups.
* `vdf`: a Verifyable Delay Function (VDF) trait, as well as an
implementation of that trait.
* `vdf-cli`: a command-line interface to the vdf crate. It also includes
additional commands, which are deprecated and will be replaced by a CLI to
the classgroup crate.
## Usage
- Install [Rust]. We (POA Networks) have tested the code with the latest
stable, beta, and nightly versions of Rust. It may work with older
versions, but this is not guaranteed.
- Install the [GNU Multiple Precision Library](https://gmplib.org/)
* On Debian and derivatives (including Ubuntu):
```sh
$ sudo apt-get install -y libgmp-dev
```
* On Red Hat and derivatives (Fedora, CentOS)
```sh
$ sudo dnf -y install gmp-devel
```
- Download and prepare the repository
```sh
$ git clone https://github.com/poanetwork/vdf.git
$ cargo install --path=vdf-cli
$ # or for the competition binary
$ cargo install --path=vdf-competition
```
### Command Line Interface
To initiate, use the `vdf-cli` command followed by 2 arguments:
- _challenge_: byte string of arbitrary length
- _difficulty_: number of iterations, each iteration requires more time to evaluate
This generates the Weslowski proof of time. To generate the Pietrzak proof of
time, pass `-tpietrzak`. For detailed usage information, run `vdf-cli --help`.
Once complete you will see the output, returned as a `Vec<u8>`. The CLI tool
hex-encodes its output.
**Example**
```sh
$ vdf-cli aa 100
005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
```
To verify, use the `vdi-cli` command with the same arguments and include the
output.
**Example**
```sh
$ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
Proof is valid
```
### VDF Library
<!--
Keep as is, and possibly include argument explanations as well (for byte_length for example). May not be needed though is CLI is main user interaction tool.
-->
```rust
extern crate vdf;
use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
/// The correct solution.
const CORRECT_SOLUTION: &[u8] =
b"\x00\x52\x71\xe8\xf9\xab\x2e\xb8\xa2\x90\x6e\x85\x1d\xfc\xb5\x54\x2e\x41\x73\xf0\x16\
\xb8\x5e\x29\xd4\x81\xa1\x08\xdc\x82\xed\x3b\x3f\x97\x93\x7b\x7a\xa8\x24\x80\x11\x38\
\xd1\x77\x1d\xea\x8d\xae\x2f\x63\x97\xe7\x6a\x80\x61\x3a\xfd\xa3\x0f\x2c\x30\xa3\x4b\
\x04\x0b\xaa\xaf\xe7\x6d\x57\x07\xd6\x86\x89\x19\x3e\x5d\x21\x18\x33\xb3\x72\xa6\xa4\
\x59\x1a\xbb\x88\xe2\xe7\xf2\xf5\xa5\xec\x81\x8b\x57\x07\xb8\x6b\x8b\x2c\x49\x5c\xa1\
\x58\x1c\x17\x91\x68\x50\x9e\x35\x93\xf9\xa1\x68\x79\x62\x0a\x4d\xc4\xe9\x07\xdf\x45\
\x2e\x8d\xd0\xff\xc4\xf1\x99\x82\x5f\x54\xec\x70\x47\x2c\xc0\x61\xf2\x2e\xb5\x4c\x48\
\xd6\xaa\x5a\xf3\xea\x37\x5a\x39\x2a\xc7\x72\x94\xe2\xd9\x55\xdd\xe1\xd1\x02\xae\x2a\
\xce\x49\x42\x93\x49\x2d\x31\xcf\xf2\x19\x44\xa8\xbc\xb4\x60\x89\x93\x06\x5c\x9a\x00\
\x29\x2e\x8d\x3f\x46\x04\xe7\x46\x5b\x4e\xee\xfb\x49\x4f\x5b\xea\x10\x2d\xb3\x43\xbb\
\x61\xc5\xa1\x5c\x7b\xdf\x28\x82\x06\x88\x5c\x13\x0f\xa1\xf2\xd8\x6b\xf5\xe4\x63\x4f\
\xdc\x42\x16\xbc\x16\xef\x7d\xac\x97\x0b\x0e\xe4\x6d\x69\x41\x6f\x9a\x9a\xce\xe6\x51\
\xd1\x58\xac\x64\x91\x5b";
fn main() {
// The length of the prime numbers generated, in bits.
let num_bits: u16 = 2048;
// An instance of the VDF. Instances can be used arbitrarily many times.
let pietrzak_vdf = PietrzakVDFParams(num_bits).new();
// Solve for the correct answer. This will take a minute or two.
assert_eq!(
&pietrzak_vdf.solve(b"\xaa", 10000).unwrap()[..],
CORRECT_SOLUTION
);
// Verify the answer. This should be far faster (less than a second).
assert!(pietrzak_vdf.verify(b"\xaa", 10000, CORRECT_SOLUTION).is_ok());
}
```
## Benchmarks
Benchmarks are provided for the classgroup operations. To run benchmarks:
```sh
$ ./bench.sh <your challenge here>
```
Additional benchmarks are under development.
### Current Benchmarks
These were generated by `./bench.sh aadf`. Outliers could be due to preemption
by the OS and/or hypervisor. Changes are relative to the previous test run
done on the same machine. Since the previous run was done with different
settings and/or code than reported here, these changes are not meaningful.
```text
Benchmarking square with seed aadf: 512: Collecting 100 samples in estimated 5.0439 s (374k iteratio square with seed aadf: 512
time: [13.301 us 13.333 us 13.372 us]
change: [-22.286% -21.745% -21.225%] (p = 0.00 < 0.05)
Performance has improved.
Found 22 outliers among 100 measurements (22.00%)
5 (5.00%) high mild
17 (17.00%) high severe
Benchmarking multiply with seed aadf: 512: Collecting 100 samples in estimated 5.0452 s (293k iterat multiply with seed aadf: 512
time: [17.219 us 17.251 us 17.287 us]
change: [-24.323% -23.739% -23.149%] (p = 0.00 < 0.05)
Performance has improved.
Found 10 outliers among 100 measurements (10.00%)
4 (4.00%) high mild
6 (6.00%) high severe
Benchmarking square with seed aadf: 1024: Collecting 100 samples in estimated 5.0822 s (177k iterati square with seed aadf: 1024
time: [28.672 us 28.716 us 28.767 us]
change: [-29.947% -29.339% -28.708%] (p = 0.00 < 0.05)
Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
1 (1.00%) low mild
1 (1.00%) high mild
6 (6.00%) high severe
Benchmarking multiply with seed aadf: 1024: Collecting 100 samples in estimated 5.0886 s (136k itera multiply with seed aadf: 1024
time: [37.163 us 37.207 us 37.254 us]
change: [-21.403% -20.750% -20.170%] (p = 0.00 < 0.05)
Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
1 (1.00%) low mild
1 (1.00%) high mild
6 (6.00%) high severe
Benchmarking square with seed aadf: 2048: Collecting 100 samples in estimated 5.2519 s (76k iteratio square with seed aadf: 2048
time: [69.115 us 69.254 us 69.430 us]
change: [-28.091% -27.738% -27.341%] (p = 0.00 < 0.05)
Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
1 (1.00%) low mild
1 (1.00%) high mild
6 (6.00%) high severe
Benchmarking multiply with seed aadf: 2048: Collecting 100 samples in estimated 5.0554 s (56k iterat multiply with seed aadf: 2048
time: [90.922 us 91.057 us 91.201 us]
change: [-25.236% -24.794% -24.336%] (p = 0.00 < 0.05)
Performance has improved.
Found 13 outliers among 100 measurements (13.00%)
2 (2.00%) low mild
5 (5.00%) high mild
6 (6.00%) high severe
```
[Rust]: <https://doc.rust-lang.org/cargo/getting-started/installation.html>
## License
Copyright 2018 Chia Network Inc and POA Networks Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
<http://www.apache.org/licenses/LICENSE-2.0>
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

54
crates/vdf/bench/bench.rs Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2018 POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_use]
extern crate criterion;
use hex;
use classgroup::{gmp_classgroup::GmpClassGroup, ClassGroup};
use criterion::Criterion;
use std::{cell::RefCell, env, rc::Rc};
use vdf::create_discriminant;
fn bench_square(c: &mut Criterion) {
let bench_params = |c: &mut Criterion, len: u16, seed: &[u8]| {
let i = Rc::new(RefCell::new(GmpClassGroup::generator_for_discriminant(
create_discriminant(seed, len),
)));
{
let i = i.clone();
c.bench_function(
&format!("square with seed {}: {}", hex::encode(seed), len),
move |b| b.iter(|| i.borrow_mut().square()),
);
}
{
let multiplier = i.borrow().clone();
c.bench_function(
&format!("multiply with seed {}: {}", hex::encode(seed), len),
move |b| b.iter(|| *i.borrow_mut() *= &multiplier),
);
}
};
let seed = env::var("VDF_BENCHMARK_SEED")
.ok()
.and_then(|x| hex::decode(x).ok())
.expect("bug in calling script");
for &i in &[512, 1024, 2048] {
bench_params(c, i, &seed)
}
}
criterion_group!(benches, bench_square);
criterion_main!(benches);

112
crates/vdf/build.rs Normal file
View File

@ -0,0 +1,112 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{env, fs::File, io::Write, path::PathBuf, u16};
/// The number of odd primes less than 65536.
const PRIMES_LEN: usize = 6541;
/// The number of integers that are:
///
/// * equal to 7 mod 8
/// * not divisible by any prime number less than or equal to 13.
/// * less than 8 * 3 * 5 * 7 * 11 * 13
const RESIDUES_LEN: usize = 5760;
/// The number of odd prime numbers between 13 and 65536 exclusive.
const SIEVE_INFO_LEN: usize = PRIMES_LEN - 5;
fn odd_primes_below_65536() -> Vec<usize> {
const N: usize = 1 << 16;
let mut sieve = vec![true; N >> 1];
let mut q = (N as f64).powf(0.5) as usize;
assert!(q * q <= N);
q += 1;
assert!(q * q > N);
for i in (3..q).step_by(2) {
if sieve[i >> 1] {
for i in ((i * i >> 1)..sieve.len()).step_by(i) {
sieve[i] = false;
}
}
}
// mega cheat ― we know the exact size of this vector
let res: Vec<_> = (1..N / 2)
.filter(|&i| sieve[i])
.map(|i| 2 * i + 1)
.collect();
assert_eq!(res.len(), PRIMES_LEN);
res
}
fn mod_exponentiation(base: usize, exponent: usize, modulus: usize) -> usize {
assert!(base < u16::MAX.into());
assert!(exponent < u16::MAX.into());
assert!(modulus < u16::MAX.into());
let (mut base, mut exponent, modulus) = (base as u32, exponent as u32, modulus as u32);
let mut state = 1;
loop {
if exponent & 1 != 0 {
state *= base;
state %= modulus;
}
exponent >>= 1;
if exponent == 0 {
return state as _;
}
base *= base;
base %= modulus;
}
}
macro_rules! const_fmt {
() => {
"#[allow(warnings)]\nconst {}: [{}; {}] = {:#?};\n\n";
};
}
/// A product of many small prime numbers. We precompute the numbers between
/// `1` and `M` that are coprime to `M`. Any number whose residue modulo `M` is
/// one of these is not divisible by any of the prime factors of `M`. This
/// speeds up the generation of random prime numbers.
const M: usize = 8 * 3 * 5 * 7 * 11 * 13;
fn emit<T: std::fmt::Debug>(f: &mut dyn Write, name: &str, t: &str, obj: &[T]) {
write!(f, const_fmt!(), name, t, obj.len(), obj).expect("i/o error in build script");
}
/// Write the generated code to `f`.
fn generate(f: &mut dyn Write) {
write!(f, "const M: u32 = 8 * 3 * 5 * 7 * 11 * 13;\n\n").expect("i/o error");
let residues: Vec<usize> = {
let primes = [3, 5, 7, 11, 13];
let not_divisible = |&x: &usize| primes.iter().all(|p| x % p != 0);
(7..M).step_by(8).filter(not_divisible).collect()
};
assert_eq!(residues.len(), RESIDUES_LEN);
emit(f, "RESIDUES", "u32", &residues[..]);
let sieve_info: Vec<(usize, usize)> = odd_primes_below_65536()[5..]
.iter()
.map(|&i| (i, mod_exponentiation(M % i, i - 2, i)))
.collect();
assert_eq!(sieve_info.len(), SIEVE_INFO_LEN);
emit(f, "SIEVE_INFO", "(u16, u16)", &sieve_info[..]);
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let manifest_path = env::var("OUT_DIR").expect("cargo should have set this");
let mut path = PathBuf::from(&manifest_path);
path.push("constants.rs");
let mut f = File::create(path).expect("cannot create constants.rs");
generate(&mut f);
}

View File

@ -0,0 +1,199 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Creation of discriminants.
//!
//! The [`pot`] tool does not accept a discriminant as a command-line argument.
//! Instead, we generate the discriminant from a (much smaller) seed.
//!
//! For performance, we follow the Chia network's [`inkfish`] implementation
//! of ["Close to Uniform Prime Number Generation With Fewer Random Bits"][1]
//! by Pierre-Alain Fouque and Mehdi Tibouchi.
//! We employ a table of precomputed constants generated by `build.rs`.
//!
//! [1]: https://eprint.iacr.org/2011/481.pdf
//! [`inkfish`]: <https://github.com/Chia-Network/vdf-competition/blob/003b0d202d3b27058159f7a3f6a838e312e7d79e/inkfish/create_discriminant.py>
//! [`pot`]: <https://github.com/Chia-Network/vdf-competition/blob/003b0d202d3b27058159f7a3f6a838e312e7d79e/inkfish/cmds.py>
include!(concat!(env!("OUT_DIR"), "/constants.rs"));
use classgroup::BigNumExt;
use num_traits::Zero;
use sha2::{digest::FixedOutput, Digest, Sha256};
use std::u16;
fn random_bytes_from_seed(seed: &[u8], byte_count: usize) -> Vec<u8> {
assert!(byte_count <= 32 * ((1 << 16) - 1));
let mut blob = Vec::with_capacity(byte_count);
let mut extra: u16 = 0;
while blob.len() < byte_count {
let mut hasher = Sha256::new();
hasher.input(seed);
let extra_bits: [u8; 2] = [((extra & 0xFF00) >> 8) as _, (extra & 0xFF) as _];
hasher.input(&extra_bits);
blob.extend_from_slice(&hasher.fixed_result()[..]);
extra += 1;
}
blob.resize(byte_count, 0);
blob
}
/// Create a discriminant from a seed (a byte string) and a bit length (a
/// `u16`). The discriminant is guaranteed to be a negative prime number that
/// fits in `length` bits, except with negligible probability (less than
/// 2^(-100)). It is also guaranteed to equal 7 modulo 8.
///
/// This function uses sha256 to expand the seed. Therefore, different seeds
/// will result in completely different discriminants with overwhelming
/// probability, unless `length` is very small. However, this function is
/// deterministic: if it is called twice with identical seeds and lengths, it
/// will always return the same discriminant.
///
/// This function is guaranteed not to panic for any inputs whatsoever, unless
/// memory allocation fails and the allocator in use panics in that case.
pub fn create_discriminant<T: BigNumExt>(seed: &[u8], length: u16) -> T {
let (mut n, residue) = {
// The number of “extra” bits (that dont evenly fit in a byte)
let extra: u8 = (length as u8) & 7;
// The number of random bytes needed (the number of bytes that hold `length`
// bits, plus 2).
let random_bytes_len = ((usize::from(length) + 7) >> 3) + 2;
let random_bytes = random_bytes_from_seed(seed, random_bytes_len);
let (n, last_2) = random_bytes.split_at(random_bytes_len - 2);
let numerator = (usize::from(last_2[0]) << 8) + usize::from(last_2[1]);
// If there are any extra bits, right shift `n` so that it fits
// in `length` bits, discarding the least significant bits.
let n = T::from(n) >> usize::from((8 - extra) & 7);
(n, RESIDUES[numerator % RESIDUES.len()])
};
n.setbit(usize::from(length - 1));
debug_assert!(n >= Zero::zero());
let rem = n.frem_u32(M);
// HACK HACK `rust-gmp` doesnt expose += and -= with i32 or i64
if residue > rem {
n = n + u64::from(residue - rem);
} else {
n = n - u64::from(rem - residue);
}
debug_assert!(n >= Zero::zero());
// This generates the smallest prime ≥ n that is of the form n + m*x.
loop {
// Speed up prime-finding by quickly ruling out numbers
// that are known to be composite.
let mut sieve = ::bit_vec::BitVec::from_elem(1 << 16, false);
for &(p, q) in SIEVE_INFO.iter() {
// The reference implementation changes the sign of `n` before taking its
// remainder. Instead, we leave `n` as positive, but use ceiling
// division instead of floor division. This is mathematically
// equivalent and potentially faster.
let mut i: usize = (n.crem_u16(p) as usize * q as usize) % p as usize;
while i < sieve.len() {
sieve.set(i, true);
i += p as usize;
}
}
for (i, x) in sieve.iter().enumerate() {
if !x {
let q = u64::from(M) * u64::from(i as u32);
n = n + q;
if n.probab_prime(2) {
return -n;
}
n = n - q;
}
}
// M is set to a number with many prime factors so the results are
// more uniform https://eprint.iacr.org/2011/481.pdf
// TODO: Explain previous reference to https://eprint.iacr.org/2011/401.pdf
n = n + (u64::from(M) * (1 << 16)) as u64
}
}
#[cfg(test)]
mod test {
use super::*;
use classgroup::{gmp_classgroup::GmpClassGroup, ClassGroup};
type Mpz = <GmpClassGroup as ClassGroup>::BigNum;
use std::str::FromStr;
#[test]
fn check_discriminant_1() {
assert_eq!(
create_discriminant::<Mpz>(b"\xaa", 40),
(-685_537_176_559i64).into()
);
}
#[test]
fn check_discriminant_3() {
assert_eq!(
create_discriminant::<Mpz>(b"\xaa", 1024),
Mpz::from_str(
"-112084717443890964296630631725167420667316836131914185144761\
7438378168250988242739496385274308134767869324152361453294226\
8295868231081182819214054220080323345750407342623884342617809\
8794592117225058677336074005099949757067786815439982423354682\
0386024058617141397148586038290164093146862666602485017735298\
03183"
)
.unwrap()
)
}
#[test]
fn check_discriminant_2() {
assert_eq!(
create_discriminant::<Mpz>(b"\xaa", 2048),
-Mpz::from_str(
"201493927071865251625903550712920535753645598483515670853547009\
878440933309489362800393797428711071833308081461824159206915864\
150805748296170245037221957772328044276705571745811271212292422\
075849739248257870371300001313586036515879618764093772248760562\
386804073478433157526816295216137723803793411828867470089409596\
238958950007370719325959579892866588928887249912429688364409867\
895510817680171869190054122881274299350947669820596157115994418\
034091728887584373727555384075665624624856766441009974642693066\
751400054217209981490667208950669417773785631693879782993019167\
69407006303085854796535778826115224633447713584423"
)
.unwrap()
);
}
#[test]
fn check_random_bytes() {
assert_eq!(
&random_bytes_from_seed(b"\xaa", 7),
b"\x9f\x9d*\xe5\xe7<\xcb"
);
assert_eq!(
&random_bytes_from_seed(b"\xaa", 258)[..],
&b"\x9f\x9d*\xe5\xe7<\xcbq\xa4q\x8e\
\xbc\xf0\xe3:\xa2\x98\xf8\xbd\xdc\xaa\xcbi\xcb\x10\xff\x0e\xafv\xdb\xec!\xc4K\
\xc6Jf\xf3\xa5\xda.7\xb7\xef\x87I\x85\xb8YX\xfc\xf2\x03\xa1\x8f4\xaf`\xab\xae]n\
\xcc,g1\x12EI\xc7\xd5\xe2\xfc\x8b\x9a\xde\xd5\xf3\x8f'\xcd\x08\x0fU\xc7\xee\xa85\
[>\x87]\x07\x82\x00\x13\xce\xf7\xc3/@\xef\x08v\x8f\x85\x87dm(1\x8b\xd9w\xffA]xzY\
\xa0,\xebz\xff\x03$`\x91\xb66\x88-_\xa9\xf1\xc5\x8e,\x15\xae\x8f\x04\rvhnU3f\x84\
[{$\xa6l\x95w\xa9\x1f\xba\xa8)\x05\xe6\x8f\x167o\x11/X\x9cl\xab\x9c\xcb}\xec\x88\
\xf8\xa5\xabXpY\xb0\x88\xed@r\x05\xba\\\x03\xf6\x91\xf8\x03\xca\x18\x1c\xcdH\x1c\
\x91\xe1V\xed;\x94oJ\xa8 \xa4\x97\xb7K\xce\xc4e\xea\xa2\xbf\x8b\x1f\x90\x87\xc8\
\x15\xee\x0e\x0fPC:\xb5\xe1g\x97\xea/_\x86c\xaf\x12Wp\xfd\x11\xdb\x17\xe6\x9f\
\xa5\x8a"[..]
);
}
}

245
crates/vdf/src/lib.rs Normal file
View File

@ -0,0 +1,245 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![deny(warnings)]
//! # Rust implementations of class groups and verifyable delay functions
//!
//! This repo includes three crates
//!
//! * `classgroup`, which includes a class group implementation, as well as a
//! trait for class groups.
//! * `vdf`, which includes a Verifyable Delay Function (VDF) trait, as well as
//! an implementation of that trait.
//! * `vdf-cli`, which includes a command-line interface to the `vdf` crate. It
//! also includes additional commands, which are deprecated and will later be
//! replaced by a CLI to the `classgroup` crate.
//!
//! ## Usage
//!
//! First, install Rust, Cargo, and the GNU Multiprecision Library (GMP). Then,
//! follow one of the below steps.
//!
//! ### To use the command line interface
//!
//! ```sh
//! $ git clone https://github.com/poanetwork/vdf
//! $ cd vdf
//! $ cargo install
//! $ vdf-cli aa 100
//! 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! $ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! Proof is valid
//! ```
//!
//! ### To use the VDF library
//!
//! ```rust
//! extern crate vdf;
//! use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
//! const CORRECT_SOLUTION: &[u8] =
//! b"\x00\x52\x71\xe8\xf9\xab\x2e\xb8\xa2\x90\x6e\x85\x1d\xfc\xb5\x54\x2e\x41\x73\xf0\x16\
//! \xb8\x5e\x29\xd4\x81\xa1\x08\xdc\x82\xed\x3b\x3f\x97\x93\x7b\x7a\xa8\x24\x80\x11\x38\
//! \xd1\x77\x1d\xea\x8d\xae\x2f\x63\x97\xe7\x6a\x80\x61\x3a\xfd\xa3\x0f\x2c\x30\xa3\x4b\
//! \x04\x0b\xaa\xaf\xe7\x6d\x57\x07\xd6\x86\x89\x19\x3e\x5d\x21\x18\x33\xb3\x72\xa6\xa4\
//! \x59\x1a\xbb\x88\xe2\xe7\xf2\xf5\xa5\xec\x81\x8b\x57\x07\xb8\x6b\x8b\x2c\x49\x5c\xa1\
//! \x58\x1c\x17\x91\x68\x50\x9e\x35\x93\xf9\xa1\x68\x79\x62\x0a\x4d\xc4\xe9\x07\xdf\x45\
//! \x2e\x8d\xd0\xff\xc4\xf1\x99\x82\x5f\x54\xec\x70\x47\x2c\xc0\x61\xf2\x2e\xb5\x4c\x48\
//! \xd6\xaa\x5a\xf3\xea\x37\x5a\x39\x2a\xc7\x72\x94\xe2\xd9\x55\xdd\xe1\xd1\x02\xae\x2a\
//! \xce\x49\x42\x93\x49\x2d\x31\xcf\xf2\x19\x44\xa8\xbc\xb4\x60\x89\x93\x06\x5c\x9a\x00\
//! \x29\x2e\x8d\x3f\x46\x04\xe7\x46\x5b\x4e\xee\xfb\x49\x4f\x5b\xea\x10\x2d\xb3\x43\xbb\
//! \x61\xc5\xa1\x5c\x7b\xdf\x28\x82\x06\x88\x5c\x13\x0f\xa1\xf2\xd8\x6b\xf5\xe4\x63\x4f\
//! \xdc\x42\x16\xbc\x16\xef\x7d\xac\x97\x0b\x0e\xe4\x6d\x69\x41\x6f\x9a\x9a\xce\xe6\x51\
//! \xd1\x58\xac\x64\x91\x5b";
//!
//! fn main() {
//! let pietrzak_vdf = PietrzakVDFParams(2048).new();
//! assert_eq!(
//! &pietrzak_vdf.solve(b"\xaa", 100).unwrap()[..],
//! CORRECT_SOLUTION
//! );
//! assert!(pietrzak_vdf.verify(b"\xaa", 100, CORRECT_SOLUTION).is_ok());
//! }
//! ```
//!
//! ### To run the benchmarks
//!
//! Benchmarks are provided for the classgroup operations. Run `cargo bench`
//! to run them. Additional benchmarks are under development.
use classgroup;
mod create_discriminant;
use std::fmt::Debug;
pub use self::{
create_discriminant::create_discriminant,
proof_pietrzak::{PietrzakVDF, PietrzakVDFParams},
proof_wesolowski::{WesolowskiVDF, WesolowskiVDFParams},
};
/// Message used to report an internal miscalculation of serialization buffer
/// sizes.
const INCORRECT_BUFFER_SIZE: &str =
"internal error: incorrect buffer size calculation (this is a bug)";
mod proof_of_time;
mod proof_pietrzak;
mod proof_wesolowski;
/// An empty struct indicating verification failure.
///
/// For security reasons, the functions that perform verification *do not*
/// return any information on failure. Use `VDF::validate_params` to check if
/// the parameters are correct.
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
pub struct InvalidProof;
/// An error return indicating an invalid number of iterations. The string is a
/// human-readable message describing the valid iterations. It should not be
/// interpreted by programs.
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
pub struct InvalidIterations(String);
/// The type of VDF parameters.
///
/// Parameters represent public information that can be shared by all users
/// of the protocol. As such, they must implement `Clone`, so that they can
/// be duplicated. They also must implement `Send`, so that a parallel
/// application can send them safely across threads.
///
/// The parameters *do not* include the difficulty level (usually an
/// iteration count), since that can be separate for each invocation.
///
/// This must implement `Clone` and `Eq`.
pub trait VDFParams: Clone + Eq {
type VDF: VDF + Sized;
/// Creates an instance of this VDF from the given parameters.
///
/// # Performance
///
/// This method is expected to be fairly cheap. For example, it is okay if
/// it allocates memory, but it should not perform expensive computations or
/// I/O.
///
/// # Panics
///
/// This method **MUST NOT** fail due to invalid values for `params`. Such
/// errors should be checked by the factory functions for `Self::Params`.
///
/// This function **MAY** panic for other reasons. For example, it is
/// allowed to panic if an allocation fails, or if a needed external library
/// could not be dynamically loaded.
fn new(self) -> Self::VDF;
}
/// A Verifiable Delay Function (VDF).
///
/// VDFs are problems that require a certain amount of time to solve, even on a
/// parallel machine, but can be validated much more easily.
///
/// While VDFs are considered to be cryptographic primitives, they generally do
/// *not* operate on highly sensitive data. As such, implementers of this trait
/// **do not** guarantee that they will be immune to side-channel attacks, and
/// consumers of this trait **MUST NOT** expect this.
///
/// Instances of this trait are *not* expected to be `Sync`. This allows them
/// to reuse allocations (such as scratch memory) accross invocations without
/// the need for locking. However, they **MUST** be `Send` and `Clone`, so that
/// consumers can duplicate them and send them across threads.
pub trait VDF: Send + Debug {
/// Solve an instance of this VDF, with challenge `challenge` and difficulty
/// `difficulty`.
///
/// The output is to be returned in a `Vec<u8>`, so it can be stored to disk
/// or sent over the network.
///
/// # Challenge format
///
/// The challenge is an opaque byte string of arbitrary length.
/// Implementors **MUST NOT** make any assumptions about its contents,
/// and **MUST** produce distinct outputs for distinct challenges
/// (except with negiligible probability).
///
/// This can be most easily implemented by using the challenge as part of
/// the input of a cryptographic hash function. The VDFs provided in this
/// crate use this strategy.
///
/// The difficulty must be checked before performing any expensive
/// computations.
///
/// Most applications will generate the challenge using a
/// cryptographically-secure pseudorandom number generator, but implementors
/// **MUST NOT** rely on this. In particular, this function must be secure
/// even if `challenge` is chosen by an adversary. Excessive values for
/// `difficulty` may cause excessive resource consumption, but must not
/// create any other vulnerabilities.
///
/// # Complexity
///
/// The VDFs in this crate consume memory that does not depend on
/// `difficulty`, and time linearly proportional to `difficulty`.
/// Implementors of this trait should document the resource use.
///
/// # Purity
///
/// This method must have no side effects. In particular, it must be
/// **deterministic**: it must always return the same output for the same
/// inputs, except with negligible probability. Furthermore, while it may
/// change `self` via interior mutability, such changes must not affect
/// future calls to this method, `Self::check_difficulty`, or
/// `Self::verify`. They *may* affect the `Debug` output.
fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, InvalidIterations>;
/// Check that the difficulty is valid.
///
/// This must return `Ok` if and only if `difficulty` is valid. Otherwise,
/// it must return `Err`.
///
/// # Rationale
///
/// It would be more ideomatic Rust to use the type system to enforce that a
/// difficulty has been validated before use. However, I (Demi) have not
/// yet figured out an object-safe way to do so.
fn check_difficulty(&self, difficulty: u64) -> Result<(), InvalidIterations>;
/// Verifies an alleged solution of this VDF, with challenge `challenge` and
/// difficulty `difficulty`. Return `Ok(())` on success, or
/// `Err(InvalidProof)` on failure.
///
/// This function *does not* return any extended error information for
/// security reasons. To check that the difficulty is correct, call
/// `Self::check_difficulty`.
///
/// # Uniqueness of valid solutions
///
/// For any `(challenge, difficulty)` tuple, there must be at most one
/// `alleged_solution` (as measured by `Eq`) that causes this function to
/// return `Ok(())`. If the difficulty is valid (as determined by
/// `check_difficulty`), there must be exactly one such solution; otherwise,
/// there must be none.
///
/// # Purity
///
/// This method must have no side effects. In particular, it must be
/// **deterministic**: it must always return the same output for the same
/// inputs. Furthermore, while it may change `self` via interior
/// mutability, such changes must not affect future calls to this method,
/// `Self::prove`, or `Self::check_difficulty`. Such changes **MAY** affect
/// debugging output.
fn verify(
&self,
challenge: &[u8],
difficulty: u64,
alleged_solution: &[u8],
) -> Result<(), InvalidProof>;
}

View File

@ -0,0 +1,88 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::classgroup::ClassGroup;
use std::{collections::HashMap, usize};
pub fn serialize<V: ClassGroup>(proof: &[V], y: &V, int_size_bits: usize) -> Vec<u8> {
let proof_len = proof.len();
let element_length = 2 * ((int_size_bits + 16) >> 4);
let proof_len_in_bytes = (proof_len + 1) * element_length;
let mut v = vec![0; proof_len_in_bytes];
y.serialize(&mut v[0..element_length])
.expect(super::INCORRECT_BUFFER_SIZE);
for (index, group) in proof.iter().enumerate() {
let offset = (index + 1) * element_length;
group
.serialize(&mut v[offset..offset + element_length])
.expect(super::INCORRECT_BUFFER_SIZE)
}
v
}
pub fn deserialize_proof<T>(
proof_blob: &[u8],
discriminant: &T::BigNum,
orig_length: usize,
) -> Result<Vec<T>, ()>
where
T: ClassGroup,
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
{
let length = T::size_in_bits(discriminant);
if length > usize::MAX - 16 {
return Err(());
}
let length = (length + 16) >> 4;
if length == 0 {
return Err(());
}
if orig_length != length {
return Err(());
}
let length = length * 2;
let proof_blob_length = proof_blob.len();
let rem = proof_blob_length % length;
if rem != 0 {
return Err(());
}
let proof_len = proof_blob_length / length;
let mut v = Vec::with_capacity(proof_len);
for i in 0..proof_len {
let offset = i * length;
v.push(T::from_bytes(
&proof_blob[offset..offset + length],
discriminant.clone(),
))
}
Ok(v)
}
pub fn iterate_squarings<V, U>(mut x: V, powers_to_calculate: U) -> HashMap<u64, V>
where
V: ClassGroup,
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
U: Iterator<Item = u64>,
{
let mut powers_calculated = HashMap::new();
let mut powers_to_calculate: Vec<u64> = powers_to_calculate.collect();
powers_to_calculate.sort_unstable();
let mut previous_power: u64 = 0;
for &current_power in &powers_to_calculate {
x.repeated_square(current_power - previous_power);
powers_calculated.insert(current_power, x.clone());
previous_power = current_power
}
powers_calculated
}

View File

@ -0,0 +1,466 @@
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::proof_of_time::{deserialize_proof, iterate_squarings, serialize};
use classgroup::{gmp_classgroup::GmpClassGroup, BigNumExt, ClassGroup};
use num_traits::{One, Zero};
use std::{fmt, num::ParseIntError, ops::Index, str::FromStr, u64, usize};
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone, Debug)]
pub struct Iterations(u64);
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Copy, Clone, Debug)]
pub enum InvalidIterations {
OddNumber(u64),
LessThan66(u64),
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ParseIterationsError {
kind: Result<InvalidIterations, ParseIntError>,
}
impl From<InvalidIterations> for ParseIterationsError {
fn from(t: InvalidIterations) -> Self {
Self { kind: Ok(t) }
}
}
impl From<ParseIntError> for ParseIterationsError {
fn from(t: ParseIntError) -> Self {
Self { kind: Err(t) }
}
}
impl fmt::Display for InvalidIterations {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
InvalidIterations::OddNumber(s) => {
write!(f, "Pietrzak iterations must be an even number, not {}", s)
}
InvalidIterations::LessThan66(s) => write!(
f,
"Pietrzak proof-of-time must run for at least 66 iterations, not {}",
s
),
}
}
}
impl From<Iterations> for u64 {
fn from(t: Iterations) -> u64 {
t.0
}
}
impl fmt::Display for ParseIterationsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
Ok(ref q) => <InvalidIterations as fmt::Display>::fmt(q, f),
Err(ref q) => <ParseIntError as fmt::Display>::fmt(q, f),
}
}
}
impl FromStr for Iterations {
type Err = ParseIterationsError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::new(s.parse::<u64>().map_err(ParseIterationsError::from)?)
.map_err(ParseIterationsError::from)
}
}
impl Iterations {
pub fn new<T: Into<u64>>(iterations: T) -> Result<Iterations, InvalidIterations> {
let iterations = iterations.into();
if iterations & 1 != 0 {
Err(InvalidIterations::OddNumber(iterations))
} else if iterations < 66 {
Err(InvalidIterations::LessThan66(iterations))
} else {
Ok(Iterations(iterations))
}
}
}
/// Selects a reasonable choice of cache size.
fn approximate_i(t: Iterations) -> u64 {
let x: f64 = (((t.0 >> 1) as f64) / 8.) * 2.0f64.ln();
let w = x.ln() - x.ln().ln() + 0.25;
(w / (2. * 2.0f64.ln())).round() as _
}
fn sum_combinations<'a, T: IntoIterator<Item = &'a u64>>(numbers: T) -> Vec<u64> {
let mut combinations = vec![0];
for i in numbers {
let mut new_combinations = combinations.clone();
for j in combinations {
new_combinations.push(i + j)
}
combinations = new_combinations
}
combinations.remove(0);
combinations
}
fn cache_indices_for_count(t: Iterations) -> Vec<u64> {
let i: u64 = approximate_i(t);
let mut curr_t = t.0;
let mut intermediate_ts = vec![];
for _ in 0..i {
curr_t >>= 1;
intermediate_ts.push(curr_t);
if curr_t & 1 != 0 {
curr_t += 1
}
}
let mut cache_indices = sum_combinations(&intermediate_ts);
cache_indices.sort();
cache_indices.push(t.0);
cache_indices
}
fn generate_r_value<T>(x: &T, y: &T, sqrt_mu: &T, int_size_bits: usize) -> T::BigNum
where
T: ClassGroup,
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
{
use sha2::{digest::FixedOutput, Digest, Sha256};
let size = (int_size_bits + 16) >> 4;
let mut v = Vec::with_capacity(size * 2);
for _ in 0..size * 2 {
v.push(0)
}
let mut hasher = Sha256::new();
for i in &[&x, &y, &sqrt_mu] {
i.serialize(&mut v).expect(super::INCORRECT_BUFFER_SIZE);
hasher.input(&v);
}
let res = hasher.fixed_result();
T::unsigned_deserialize_bignum(&res[..16])
}
fn create_proof_of_time_pietrzak<T>(
challenge: &[u8],
iterations: Iterations,
int_size_bits: u16,
) -> Vec<u8>
where
T: ClassGroup,
<T as ClassGroup>::BigNum: BigNumExt,
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
{
let discriminant = super::create_discriminant::create_discriminant(&challenge, int_size_bits);
let x = T::from_ab_discriminant(2.into(), 1.into(), discriminant);
let delta = 8;
let powers_to_calculate = cache_indices_for_count(iterations);
let powers = iterate_squarings(x.clone(), powers_to_calculate.iter().cloned());
let proof: Vec<T> = generate_proof(
x,
iterations,
delta,
&powers,
&generate_r_value,
usize::from(int_size_bits),
);
serialize(
&proof,
&powers[&iterations.into()],
usize::from(int_size_bits),
)
}
pub fn check_proof_of_time_pietrzak<T>(
challenge: &[u8],
proof_blob: &[u8],
iterations: u64,
length_in_bits: u16,
) -> Result<(), super::InvalidProof>
where
T: ClassGroup,
T::BigNum: BigNumExt,
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
{
let discriminant = super::create_discriminant::create_discriminant(&challenge, length_in_bits);
let x = T::from_ab_discriminant(2.into(), 1.into(), discriminant);
let iterations = Iterations::new(iterations).map_err(|_| super::InvalidProof)?;
if usize::MAX - 16 < length_in_bits.into() {
// Proof way too long.
return Err(super::InvalidProof);
}
let length: usize = (usize::from(length_in_bits) + 16usize) >> 4;
if proof_blob.len() < 2 * length {
// Invalid length of proof
return Err(super::InvalidProof);
}
let result_bytes = &proof_blob[..length * 2];
let proof_bytes = &proof_blob[length * 2..];
let discriminant = x.discriminant().clone();
let proof =
deserialize_proof(proof_bytes, &discriminant, length).map_err(|()| super::InvalidProof)?;
let y = T::from_bytes(result_bytes, discriminant);
verify_proof(
&x,
&y,
proof,
iterations,
8,
&generate_r_value,
length_in_bits.into(),
)
.map_err(|()| super::InvalidProof)
}
fn calculate_final_t(t: Iterations, delta: usize) -> u64 {
let mut curr_t = t.0;
let mut ts = vec![];
while curr_t != 2 {
ts.push(curr_t);
curr_t >>= 1;
if curr_t & 1 == 1 {
curr_t += 1
}
}
ts.push(2);
ts.push(1);
assert!(ts.len() >= delta);
ts[ts.len() - delta]
}
pub fn generate_proof<T, U, V>(
x: V,
iterations: Iterations,
delta: usize,
powers: &T,
generate_r_value: &U,
int_size_bits: usize,
) -> Vec<V>
where
T: for<'a> Index<&'a u64, Output = V>,
U: Fn(&V, &V, &V, usize) -> V::BigNum,
V: ClassGroup,
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
{
let identity = x.identity();
let i = approximate_i(iterations);
let mut mus = vec![];
let mut rs: Vec<V::BigNum> = vec![];
let mut x_p = vec![x];
let mut curr_t = iterations.0;
let mut y_p = vec![powers[&curr_t].clone()];
let mut ts = vec![];
let final_t = calculate_final_t(iterations, delta);
let mut round_index = 0;
while curr_t != final_t {
assert_eq!(curr_t & 1, 0);
let half_t = curr_t >> 1;
ts.push(half_t);
assert!(round_index < 63);
let denominator: u64 = 1 << (round_index + 1);
mus.push(if round_index < i {
let mut mu = identity.clone();
for numerator in (1..denominator).step_by(2) {
let num_bits = 62 - denominator.leading_zeros() as usize;
let mut r_prod: V::BigNum = One::one();
for b in (0..num_bits).rev() {
if 0 == (numerator & (1 << (b + 1))) {
r_prod *= &rs[num_bits - b - 1]
}
}
let mut t_sum = half_t;
for b in 0..num_bits {
if 0 != (numerator & (1 << (b + 1))) {
t_sum += ts[num_bits - b - 1]
}
}
let mut power = powers[&t_sum].clone();
power.pow(r_prod);
mu *= &power;
}
mu
} else {
let mut mu = x_p.last().unwrap().clone();
for _ in 0..half_t {
mu *= &mu.clone()
}
mu
});
let mut mu: V = mus.last().unwrap().clone();
let last_r: V::BigNum = generate_r_value(&x_p[0], &y_p[0], &mu, int_size_bits);
assert!(last_r >= Zero::zero());
rs.push(last_r.clone());
{
let mut last_x: V = x_p.last().unwrap().clone();
last_x.pow(last_r.clone());
last_x *= &mu;
x_p.push(last_x);
}
mu.pow(last_r);
mu *= y_p.last().unwrap();
y_p.push(mu);
curr_t >>= 1;
if curr_t & 1 != 0 {
curr_t += 1;
y_p.last_mut().unwrap().square();
}
round_index += 1
}
if cfg!(debug_assertions) {
let mut last_y = y_p.last().unwrap().clone();
let mut last_x = x_p.last().unwrap().clone();
let one: V::BigNum = 1u64.into();
last_y.pow(one.clone());
assert_eq!(last_y, y_p.last().unwrap().clone());
last_x.pow(one << final_t as usize);
}
mus
}
pub fn verify_proof<T, U, V>(
x_initial: &V,
y_initial: &V,
proof: T,
t: Iterations,
delta: usize,
generate_r_value: &U,
int_size_bits: usize,
) -> Result<(), ()>
where
T: IntoIterator<Item = V>,
U: Fn(&V, &V, &V, usize) -> V::BigNum,
V: ClassGroup,
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
{
let mut one: V::BigNum = One::one();
let (mut x, mut y): (V, V) = (x_initial.clone(), y_initial.clone());
let final_t = calculate_final_t(t, delta);
let mut curr_t = t.0;
for mut mu in proof {
assert!(
curr_t & 1 == 0,
"Cannot have an odd number of iterations remaining"
);
let r = generate_r_value(x_initial, y_initial, &mu, int_size_bits);
x.pow(r.clone());
x *= &mu;
mu.pow(r);
y *= &mu;
curr_t >>= 1;
if curr_t & 1 != 0 {
curr_t += 1;
y.square();
}
}
one <<= final_t as _;
x.pow(one);
if x == y {
Ok(())
} else {
Err(())
}
}
#[derive(Debug, Clone)]
pub struct PietrzakVDF {
int_size_bits: u16,
}
use super::InvalidIterations as Bad;
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
pub struct PietrzakVDFParams(pub u16);
impl super::VDFParams for PietrzakVDFParams {
type VDF = PietrzakVDF;
fn new(self) -> Self::VDF {
PietrzakVDF {
int_size_bits: self.0,
}
}
}
impl super::VDF for PietrzakVDF {
fn check_difficulty(&self, difficulty: u64) -> Result<(), Bad> {
Iterations::new(difficulty)
.map_err(|x| Bad(format!("{}", x)))
.map(drop)
}
fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, Bad> {
Ok(create_proof_of_time_pietrzak::<GmpClassGroup>(
challenge,
Iterations::new(difficulty).map_err(|x| Bad(format!("{}", x)))?,
self.int_size_bits,
))
}
fn verify(
&self,
challenge: &[u8],
difficulty: u64,
alleged_solution: &[u8],
) -> Result<(), super::InvalidProof> {
check_proof_of_time_pietrzak::<GmpClassGroup>(
challenge,
alleged_solution,
difficulty,
self.int_size_bits,
)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn check_approximate_i() {
assert_eq!(approximate_i(Iterations(534)), 2);
assert_eq!(approximate_i(Iterations(134)), 1);
assert_eq!(approximate_i(Iterations(1024)), 2);
}
#[test]
fn check_cache_indices() {
assert_eq!(cache_indices_for_count(Iterations(66))[..], [33, 66]);
assert_eq!(
cache_indices_for_count(Iterations(534))[..],
[134, 267, 401, 534]
);
}
#[test]
fn check_calculate_final_t() {
assert_eq!(calculate_final_t(Iterations(1024), 8), 128);
assert_eq!(calculate_final_t(Iterations(1000), 8), 126);
assert_eq!(calculate_final_t(Iterations(100), 8), 100);
}
#[test]
fn check_assuptions_about_stdlib() {
assert_eq!(62 - u64::leading_zeros(1024u64), 9);
let mut q: Vec<_> = (1..4).step_by(2).collect();
assert_eq!(q[..], [1, 3]);
q = (1..3).step_by(2).collect();
assert_eq!(q[..], [1]);
q = (1..2).step_by(2).collect();
assert_eq!(q[..], [1]);
}
}

View File

@ -0,0 +1,308 @@
// Copyright 2018 POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::proof_of_time::{iterate_squarings, serialize};
use classgroup::{gmp_classgroup::GmpClassGroup, BigNum, BigNumExt, ClassGroup};
use sha2::{digest::FixedOutput, Digest, Sha256};
use std::{cmp::Eq, collections::HashMap, hash::Hash, mem, u64, usize};
#[derive(Debug, Clone)]
pub struct WesolowskiVDF {
int_size_bits: u16,
}
use super::InvalidIterations as Bad;
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
pub struct WesolowskiVDFParams(pub u16);
impl super::VDFParams for WesolowskiVDFParams {
type VDF = WesolowskiVDF;
fn new(self) -> Self::VDF {
WesolowskiVDF {
int_size_bits: self.0,
}
}
}
impl super::VDF for WesolowskiVDF {
fn check_difficulty(&self, _difficulty: u64) -> Result<(), Bad> {
Ok(())
}
fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, Bad> {
if difficulty > usize::MAX as u64 {
Err(Bad("Cannot have more that usize::MAX iterations".to_owned()))
} else {
Ok(create_proof_of_time_wesolowski::<
<GmpClassGroup as ClassGroup>::BigNum,
GmpClassGroup,
>(
challenge, difficulty as usize, self.int_size_bits
))
}
}
fn verify(
&self,
challenge: &[u8],
difficulty: u64,
alleged_solution: &[u8],
) -> Result<(), super::InvalidProof> {
check_proof_of_time_wesolowski::<<GmpClassGroup as ClassGroup>::BigNum, GmpClassGroup>(
challenge,
alleged_solution,
difficulty,
self.int_size_bits,
)
.map_err(|()| super::InvalidProof)
}
}
/// To quote the original Python code:
///
/// > Create `L` and `k` parameters from papers, based on how many iterations
/// > need to be performed, and how much memory should be used.
pub fn approximate_parameters(t: f64) -> (usize, u8, u64) {
let log_memory = (10_000_000.0f64).log2();
let log_t = (t as f64).log2();
let l = if log_t - log_memory > 0. {
2.0f64.powf(log_memory - 20.).ceil()
} else {
1.
};
let intermediate = t * (2.0f64).ln() / (2.0 * l);
let k = (intermediate.ln() - intermediate.ln().ln() + 0.25)
.round()
.max(1.);
let w = (t / (t / k + l * (2.0f64).powf(k + 1.0)) - 2.0).floor();
(l as _, k as _, w as _)
}
fn u64_to_bytes(q: u64) -> [u8; 8] {
if false {
// This use of `std::mem::transumte` is correct, but still not justified.
unsafe { std::mem::transmute(q.to_be()) }
} else {
[
(q >> 56) as u8,
(q >> 48) as u8,
(q >> 40) as u8,
(q >> 32) as u8,
(q >> 24) as u8,
(q >> 16) as u8,
(q >> 8) as u8,
q as u8,
]
}
}
/// Quote:
///
/// > Creates a random prime based on input s.
fn hash_prime<T: BigNum>(seed: &[&[u8]]) -> T {
let mut j = 0u64;
loop {
let mut hasher = Sha256::new();
hasher.input(b"prime");
hasher.input(u64_to_bytes(j));
for i in seed {
hasher.input(i);
}
let n = T::from(&hasher.fixed_result()[..16]);
if n.probab_prime(2) {
break n;
}
j += 1;
}
}
/// Quote:
///
/// > Get“s the ith block of `2^T // B`, such that `sum(get_block(i) * 2^(k*i))
/// > = t^T // B`
fn get_block<T: BigNumExt>(i: u64, k: u8, t: u64, b: &T) -> T {
let mut res = T::from(0);
let two = T::from(2);
res.mod_powm(&two, &T::from(t - u64::from(k) * (i + 1)), b);
res *= &((two >> 1) << (k as usize));
res / b
}
fn eval_optimized<T, U: BigNumExt, L: ClassGroup<BigNum = U> + Eq + Hash>(
h: &L,
b: &U,
t: usize,
k: u8,
l: usize,
powers: &T,
) -> L
where
T: for<'a> std::ops::Index<&'a u64, Output = L>,
{
assert!(k > 0, "k cannot be zero");
assert!(l > 0, "l cannot be zero");
let kl = (k as usize)
.checked_mul(l)
.expect("computing k*l overflowed a u64");
assert!(kl <= u64::MAX as _);
assert!((kl as u64) < (1u64 << 53), "k*l overflowed an f64");
assert!((t as u64) < (1u64 << 53), "t overflows an f64");
assert!(
k < (mem::size_of::<usize>() << 3) as u8,
"k must be less than the number of bits in a usize"
);
let k1 = k >> 1;
let k0 = k - k1;
let mut x = h.identity();
let identity = h.identity();
let k_exp = 1usize << k;
let k0_exp = 1usize << k0;
let k1_exp = 1usize << k1;
for j in (0..l).rev() {
x.pow(U::from(k_exp as u64));
let mut ys: HashMap<U, L> = HashMap::new();
for b in 0..1usize << k {
ys.entry(U::from(b as u64))
.or_insert_with(|| identity.clone());
}
let end_of_loop = ((t as f64) / kl as f64).ceil() as usize;
assert!(end_of_loop == 0 || (end_of_loop as u64 - 1).checked_mul(l as u64).is_some());
for i in 0..end_of_loop {
if t < k as usize * (i * l + j + 1) {
continue;
}
let b = get_block((i as u64) * (l as u64), k, t as _, b);
*ys.get_mut(&b).unwrap() *= &powers[&((i * kl) as _)];
}
for b1 in 0..k1_exp {
let mut z = identity.clone();
for b0 in 0..k0_exp {
z *= &ys[&U::from((b1 * k0_exp + b0) as u64)]
}
z.pow(U::from((b1 as u64) * (k0_exp as u64)));
x *= &z;
}
for b0 in 0..k0_exp {
let mut z = identity.clone();
for b1 in 0..k1_exp {
z *= &ys[&U::from((b1 * k0_exp + b0) as u64)];
}
z.pow(U::from(b0 as u64));
x *= &z;
}
}
x
}
pub fn generate_proof<U, T: BigNumExt, V: ClassGroup<BigNum = T> + Eq + Hash>(
x: &V,
iterations: u64,
k: u8,
l: usize,
powers: &U,
int_size_bits: usize,
) -> V
where
U: for<'a> std::ops::Index<&'a u64, Output = V>,
{
let element_len = 2 * ((int_size_bits + 16) >> 4);
let mut x_buf = vec![0; element_len];
x.serialize(&mut x_buf[..])
.expect(super::INCORRECT_BUFFER_SIZE);
let mut y_buf = vec![0; element_len];
powers[&iterations]
.serialize(&mut y_buf[..])
.expect(super::INCORRECT_BUFFER_SIZE);
let b = hash_prime(&[&x_buf[..], &y_buf[..]]);
eval_optimized(&x, &b, iterations as _, k, l, powers)
}
/// Verify a proof, according to the Wesolowski paper.
pub fn verify_proof<T: BigNum, V: ClassGroup<BigNum = T>>(
mut x: V,
y: &V,
mut proof: V,
t: u64,
int_size_bits: usize,
) -> Result<(), ()> {
let element_len = 2 * ((int_size_bits + 16) >> 4);
let mut x_buf = vec![0; element_len];
x.serialize(&mut x_buf[..])
.expect(super::INCORRECT_BUFFER_SIZE);
let mut y_buf = vec![0; element_len];
y.serialize(&mut y_buf[..])
.expect(super::INCORRECT_BUFFER_SIZE);
let b = hash_prime(&[&x_buf[..], &y_buf[..]]);
let mut r = T::from(0);
r.mod_powm(&T::from(2u64), &T::from(t), &b);
proof.pow(b);
x.pow(r);
proof *= &x;
if &proof == y {
Ok(())
} else {
Err(())
}
}
pub fn create_proof_of_time_wesolowski<T: BigNumExt, V: ClassGroup<BigNum = T> + Eq + Hash>(
challenge: &[u8],
iterations: usize,
int_size_bits: u16,
) -> Vec<u8>
where
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
{
let discriminant = super::create_discriminant::create_discriminant(&challenge, int_size_bits);
let x = V::from_ab_discriminant(2.into(), 1.into(), discriminant);
assert!((iterations as u128) < (1u128 << 53));
let (l, k, _) = approximate_parameters(iterations as f64);
let q = l.checked_mul(k as _).expect("bug");
let powers = iterate_squarings(
x.clone(),
(0..=iterations / q + 1)
.map(|i| i * q)
.chain(Some(iterations))
.map(|x| x as _),
);
let proof = generate_proof(&x, iterations as _, k, l, &powers, int_size_bits.into());
serialize(&[proof], &powers[&(iterations as _)], int_size_bits.into())
}
pub fn check_proof_of_time_wesolowski<T: BigNum, V: ClassGroup<BigNum = T>>(
challenge: &[u8],
proof_blob: &[u8],
iterations: u64,
int_size_bits: u16,
) -> Result<(), ()>
where
T: BigNumExt,
{
let discriminant: T = super::create_discriminant::create_discriminant(challenge, int_size_bits);
let x = V::from_ab_discriminant(2.into(), 1.into(), discriminant.clone());
if (usize::MAX - 16) < int_size_bits.into() {
return Err(());
}
let int_size = (usize::from(int_size_bits) + 16) >> 4;
if int_size * 4 != proof_blob.len() {
return Err(());
}
let (result_bytes, proof_bytes) = proof_blob.split_at(2 * int_size);
let proof = ClassGroup::from_bytes(proof_bytes, discriminant.clone());
let y = ClassGroup::from_bytes(result_bytes, discriminant);
verify_proof(x, &y, proof, iterations, int_size_bits.into())
}