what did i do?
This commit is contained in:
commit
9448b6f84b
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
580
Cargo.lock
generated
Normal file
580
Cargo.lock
generated
Normal file
@ -0,0 +1,580 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
|
||||
dependencies = [
|
||||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"atty",
|
||||
"bit-set",
|
||||
"diff",
|
||||
"ena",
|
||||
"itertools",
|
||||
"lalrpop-util",
|
||||
"petgraph",
|
||||
"pico-args",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"string_cache",
|
||||
"term",
|
||||
"tiny-keccak",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.138"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "modinverse"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f62f577f148cc1a9466e7065a22e59466a7d537cceba5e77e57181d0f706633"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468"
|
||||
|
||||
[[package]]
|
||||
name = "polynomial"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"modinverse",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "small-simple-snark"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"modinverse",
|
||||
"polynomial",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
|
||||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "small-simple-snark"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
author = "nganhkhoa"
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
lalrpop-util = { version = "0.19.8", features = ["lexer"] }
|
||||
modinverse = "0.1.1"
|
||||
polynomial = { path="polynomial-rs" }
|
||||
regex = "1.7.0"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.19.8"
|
5
build.rs
Normal file
5
build.rs
Normal file
@ -0,0 +1,5 @@
|
||||
extern crate lalrpop;
|
||||
|
||||
fn main() {
|
||||
lalrpop::process_root().unwrap();
|
||||
}
|
7
examples/a.bsnark
Normal file
7
examples/a.bsnark
Normal file
@ -0,0 +1,7 @@
|
||||
a, b, c
|
||||
|
||||
|
||||
d = a * a
|
||||
e = b * b
|
||||
f = c * c
|
||||
f = d + e
|
15
polynomial-rs/.github/dependabot.yml
vendored
Normal file
15
polynomial-rs/.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "cargo" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
118
polynomial-rs/.github/workflows/rust-ci.yml
vendored
Normal file
118
polynomial-rs/.github/workflows/rust-ci.yml
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
name: Rust CI
|
||||
|
||||
on: push
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
rustfmt_check:
|
||||
name: Rustfmt Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
components: rustfmt
|
||||
override: true
|
||||
- name: rustfmt-check
|
||||
run: cargo fmt --all --check
|
||||
|
||||
clippy_check:
|
||||
name: Clippy Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check workflow permissions
|
||||
id: check_permissions
|
||||
uses: scherermichael-oss/action-has-permission@1.0.6
|
||||
with:
|
||||
required-permission: write
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run clippy action to produce annotations
|
||||
uses: actions-rs/clippy-check@v1
|
||||
if: ${{ steps.check_permissions.outputs.has-permission }}
|
||||
with:
|
||||
# GitHub displays the clippy job and its results as separate entries
|
||||
name: Clippy (stable) Results
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features --all-targets -- -D warnings
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
components: clippy
|
||||
override: true
|
||||
- name: Run clippy manually without annotations
|
||||
if: ${{ !steps.check_permissions.outputs.has-permission }}
|
||||
run: cargo clippy --all-features --all-targets -- -D warnings
|
||||
|
||||
security_audit:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/audit-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- 1.56.1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: cargo test
|
||||
run: cargo test --workspace --all-targets --all-features
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- 1.56.1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: cargo build
|
||||
run: cargo build --workspace --all-targets --all-features
|
||||
|
||||
coverage:
|
||||
name: Code coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
override: true
|
||||
components: llvm-tools-preview
|
||||
- name: Install cargo-llvm-cov
|
||||
uses: taiki-e/install-action@cargo-llvm-cov
|
||||
- name: Generate code coverage
|
||||
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: lcov.info
|
||||
fail_ci_if_error: true
|
||||
|
2
polynomial-rs/.gitignore
vendored
Normal file
2
polynomial-rs/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Cargo.lock
|
26
polynomial-rs/Cargo.toml
Normal file
26
polynomial-rs/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "polynomial"
|
||||
version = "0.2.5"
|
||||
edition = "2021"
|
||||
rust-version = "1.56.1"
|
||||
authors = ["gifnksm <makoto.nksm+github@gmail.com>"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/gifnksm/polynomial-rs"
|
||||
description = "A library for manipulating polynomials"
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "passively-maintained" }
|
||||
|
||||
[dependencies]
|
||||
num-traits = "0.2"
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
modinverse = "0.1.1"
|
||||
|
||||
[features]
|
||||
serde = ["dep:serde"]
|
||||
|
||||
[package.metadata.release]
|
||||
pre-release-replacements = [
|
||||
{ file = "README.md", search = "polynomial = \"[0-9\\.]+\"", replace = "{{crate_name}} = \"{{version}}\"" }
|
||||
]
|
22
polynomial-rs/LICENSE
Normal file
22
polynomial-rs/LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 NAKASHIMA, Makoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
30
polynomial-rs/README.md
Normal file
30
polynomial-rs/README.md
Normal file
@ -0,0 +1,30 @@
|
||||
# polynomial-rs
|
||||
|
||||
[![maintenance status: passively-maintained](https://img.shields.io/badge/maintenance-passively--maintained-yellowgreen.svg)](https://doc.rust-lang.org/cargo/reference/manifest.html#the-badges-section)
|
||||
[![license](https://img.shields.io/crates/l/polynomial.svg)](LICENSE)
|
||||
[![crates.io](https://img.shields.io/crates/v/polynomial.svg)](https://crates.io/crates/polynomial)
|
||||
[![docs.rs](https://img.shields.io/docsrs/polynomial/latest)](https://docs.rs/polynomial/latest/)
|
||||
[![rust 1.56.1+ badge](https://img.shields.io/badge/rust-1.56.1+-93450a.svg)](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field)
|
||||
[![Rust CI](https://github.com/gifnksm/polynomial-rs/actions/workflows/rust-ci.yml/badge.svg)](https://github.com/gifnksm/polynomial-rs/actions/workflows/rust-ci.yml)
|
||||
[![codecov](https://codecov.io/gh/gifnksm/polynomial-rs/branch/master/graph/badge.svg?token=0RxeiNjQNM)](https://codecov.io/gh/gifnksm/polynomial-rs)
|
||||
|
||||
A library for manipulating polynomials.
|
||||
|
||||
[Documentation](https://docs.rs/polynomial/latest/polynomial/)
|
||||
|
||||
## How to use?
|
||||
|
||||
Add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
polynomial = "0.2.5"
|
||||
```
|
||||
|
||||
## Minimum supported Rust version (MSRV)
|
||||
|
||||
The minimum supported Rust version is **Rust 1.56.1**.
|
||||
At least the last 3 versions of stable Rust are supported at any given time.
|
||||
|
||||
While a crate is pre-release status (0.x.x) it may have its MSRV bumped in a patch release.
|
||||
Once a crate has reached 1.x, any MSRV bump will be accompanied with a new minor version.
|
616
polynomial-rs/src/lib.rs
Normal file
616
polynomial-rs/src/lib.rs
Normal file
@ -0,0 +1,616 @@
|
||||
//! A library for manipulating polynomials.
|
||||
|
||||
#![warn(bad_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(trivial_casts)]
|
||||
#![warn(trivial_numeric_casts)]
|
||||
#![warn(unused)]
|
||||
#![warn(unused_extern_crates)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![warn(unused_qualifications)]
|
||||
#![warn(unused_results)]
|
||||
|
||||
use num_traits::{FromPrimitive, One, Zero};
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub, Rem};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
/// A polynomial.
|
||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Polynomial<T> {
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Zero> Polynomial<T> {
|
||||
/// Creates a new `Polynomial` from a `Vec` of coefficients.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use polynomial::Polynomial;
|
||||
/// let poly = Polynomial::new(vec![1, 2, 3]);
|
||||
/// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn new(mut data: Vec<T>) -> Self {
|
||||
while let Some(true) = data.last().map(|x| x.is_zero()) {
|
||||
let _ = data.pop();
|
||||
}
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Polynomial<T>
|
||||
where
|
||||
T: One
|
||||
+ Zero
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Neg<Output = T>
|
||||
+ Div<Output = T>
|
||||
+ Mul<Output = T>
|
||||
+ Sub<Output = T>
|
||||
+ Rem<Output = T>
|
||||
+ Ord
|
||||
+ fmt::Display,
|
||||
{
|
||||
fn egcd(a: T, b: T) -> (T, T, T) {
|
||||
if a == T::zero() {
|
||||
(b, T::zero(), T::one())
|
||||
}
|
||||
else {
|
||||
let (g, x, y) = Self::egcd(b % a, a);
|
||||
(g, y - (b / a) * x, x)
|
||||
}
|
||||
}
|
||||
|
||||
fn modinverse(a: T, m: T) -> Option<T> {
|
||||
let (g, x, _) = Self::egcd(a, m);
|
||||
if g != T::one() {
|
||||
None
|
||||
}
|
||||
else {
|
||||
Some((x % m + m) % m)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the [Lagrange polynomial] that fits a number of points.
|
||||
///
|
||||
/// [Lagrange polynomial]: https://en.wikipedia.org/wiki/Lagrange_polynomial
|
||||
///
|
||||
/// Returns `None` if any two x-coordinates are the same.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use polynomial::Polynomial;
|
||||
/// let poly = Polynomial::lagrange(&[1, 2, 3], &[10, 40, 90]).unwrap();
|
||||
/// println!("{}", poly.pretty("x"));
|
||||
/// assert_eq!("10*x^2", poly.pretty("x"));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn lagrange(xs: &[T], ys: &[T], field: Option<&T>) -> Option<Self> {
|
||||
let mut res = Polynomial::new(vec![Zero::zero()]);
|
||||
for ((i, x), y) in (0..).zip(xs.iter()).zip(ys.iter()) {
|
||||
let mut p: Polynomial<T> = Polynomial::new(vec![T::one()]);
|
||||
let mut denom = T::one();
|
||||
let mut negative = false;
|
||||
for (j, x2) in (0..).zip(xs.iter()) {
|
||||
if i != j {
|
||||
p = p * &Polynomial::new(vec![-x2.clone(), T::one()]);
|
||||
let diff = if x < x2 {
|
||||
x2.clone() - x.clone()
|
||||
} else {
|
||||
x.clone() - x2.clone()
|
||||
};
|
||||
if diff.is_zero() {
|
||||
return None;
|
||||
}
|
||||
|
||||
negative = !(negative ^ (x < x2));
|
||||
denom = denom * diff;
|
||||
}
|
||||
}
|
||||
let scalar = match field {
|
||||
Some(f) => {
|
||||
let denom_inv = Self::modinverse(denom, f.clone()).unwrap();
|
||||
if negative {
|
||||
- y.clone() * denom_inv
|
||||
} else {
|
||||
y.clone() * denom_inv
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if negative {
|
||||
- y.clone() / denom
|
||||
} else {
|
||||
y.clone() / denom
|
||||
}
|
||||
}
|
||||
};
|
||||
println!("{}/{} = {}", y.to_string(), denom.to_string(), scalar);
|
||||
res = res + p * &Polynomial::<T>::new(vec![scalar]);
|
||||
}
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Polynomial<T>
|
||||
where
|
||||
T: One
|
||||
+ Zero
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Neg<Output = T>
|
||||
+ Div<Output = T>
|
||||
+ Mul<Output = T>
|
||||
+ Sub<Output = T>
|
||||
+ Rem<Output = T>
|
||||
+ Ord
|
||||
+ FromPrimitive
|
||||
+ fmt::Display,
|
||||
{
|
||||
/// [Chebyshev approximation] fits a function to a polynomial over a range of values.
|
||||
///
|
||||
/// [Chebyshev approximation]: https://en.wikipedia.org/wiki/Approximation_theory#Chebyshev_approximation
|
||||
///
|
||||
/// This attempts to minimize the maximum error.
|
||||
///
|
||||
/// Retrurns `None` if `n < 1` or `xmin >= xmax`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use polynomial::Polynomial;
|
||||
/// use std::f64::consts::PI;
|
||||
/// let p = Polynomial::chebyshev(&f64::sin, 7, -PI/4., PI/4.).unwrap();
|
||||
/// assert!((p.eval(0.) - (0.0_f64).sin()).abs() < 0.0001);
|
||||
/// assert!((p.eval(0.1) - (0.1_f64).sin()).abs() < 0.0001);
|
||||
/// assert!((p.eval(-0.1) - (-0.1_f64).sin()).abs() < 0.0001);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn chebyshev<F: Fn(T) -> T>(f: &F, n: usize, xmin: f64, xmax: f64) -> Option<Self> {
|
||||
if n < 1 || xmin >= xmax {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut xs = Vec::new();
|
||||
for i in 0..n {
|
||||
use std::f64::consts::PI;
|
||||
let x = T::from_f64(
|
||||
(xmax + xmin) * 0.5
|
||||
+ (xmin - xmax) * 0.5 * ((2 * i + 1) as f64 * PI / (2 * n) as f64).cos(),
|
||||
)
|
||||
.unwrap();
|
||||
xs.push(x);
|
||||
}
|
||||
|
||||
let ys: Vec<T> = xs.iter().map(|x| f(x.clone())).collect();
|
||||
Polynomial::lagrange(&xs[0..], &ys[0..], None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + Mul<Output = T> + Clone> Polynomial<T> {
|
||||
/// Evaluates the polynomial at a point.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use polynomial::Polynomial;
|
||||
/// let poly = Polynomial::new(vec![1, 2, 3]);
|
||||
/// assert_eq!(1, poly.eval(0));
|
||||
/// assert_eq!(6, poly.eval(1));
|
||||
/// assert_eq!(17, poly.eval(2));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn eval(&self, x: T) -> T {
|
||||
let mut result: T = Zero::zero();
|
||||
for n in self.data.iter().rev() {
|
||||
result = n.clone() + result * x.clone();
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Polynomial<T> {
|
||||
/// Gets the slice of internal data.
|
||||
#[inline]
|
||||
pub fn data(&self) -> &[T] {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Polynomial<T>
|
||||
where
|
||||
T: Zero + One + Eq + Neg<Output = T> + Ord + fmt::Display + Clone,
|
||||
{
|
||||
/// Pretty prints the polynomial.
|
||||
pub fn pretty(&self, x: &str) -> String {
|
||||
if self.is_zero() {
|
||||
return "0".to_string();
|
||||
}
|
||||
|
||||
let one = One::one();
|
||||
let mut s = Vec::new();
|
||||
for (i, n) in self.data.iter().enumerate() {
|
||||
// output n*x^i / -n*x^i
|
||||
if n.is_zero() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let term = if i.is_zero() {
|
||||
n.to_string()
|
||||
} else if i == 1 {
|
||||
if (*n) == one {
|
||||
x.to_string()
|
||||
} else if (*n) == -one.clone() {
|
||||
format!("-{}", x)
|
||||
} else {
|
||||
format!("{}*{}", n, x)
|
||||
}
|
||||
} else if (*n) == one {
|
||||
format!("{}^{}", x, i)
|
||||
} else if (*n) == -one.clone() {
|
||||
format!("-{}^{}", x, i)
|
||||
} else {
|
||||
format!("{}*{}^{}", n, x, i)
|
||||
};
|
||||
|
||||
if !s.is_empty() && (*n) > Zero::zero() {
|
||||
s.push("+".to_string());
|
||||
}
|
||||
s.push(term);
|
||||
}
|
||||
|
||||
s.concat()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Neg for Polynomial<T>
|
||||
where
|
||||
T: Neg + Zero + Clone,
|
||||
<T as Neg>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<T as Neg>::Output>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Polynomial<<T as Neg>::Output> {
|
||||
-&self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Neg for &'a Polynomial<T>
|
||||
where
|
||||
T: Neg + Zero + Clone,
|
||||
<T as Neg>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<T as Neg>::Output>;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Polynomial<<T as Neg>::Output> {
|
||||
Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! forward_val_val_binop {
|
||||
(impl $imp:ident, $method:ident) => {
|
||||
impl<Lhs, Rhs> $imp<Polynomial<Rhs>> for Polynomial<Lhs>
|
||||
where
|
||||
Lhs: Zero + $imp<Rhs> + Clone,
|
||||
Rhs: Zero + Clone,
|
||||
<Lhs as $imp<Rhs>>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;
|
||||
|
||||
#[inline]
|
||||
fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
|
||||
(&self).$method(&other)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! forward_ref_val_binop {
|
||||
(impl $imp:ident, $method:ident) => {
|
||||
impl<'a, Lhs, Rhs> $imp<Polynomial<Rhs>> for &'a Polynomial<Lhs>
|
||||
where
|
||||
Lhs: Zero + $imp<Rhs> + Clone,
|
||||
Rhs: Zero + Clone,
|
||||
<Lhs as $imp<Rhs>>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;
|
||||
|
||||
#[inline]
|
||||
fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
|
||||
self.$method(&other)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! forward_val_ref_binop {
|
||||
(impl $imp:ident, $method:ident) => {
|
||||
impl<'a, Lhs, Rhs> $imp<&'a Polynomial<Rhs>> for Polynomial<Lhs>
|
||||
where
|
||||
Lhs: Zero + $imp<Rhs> + Clone,
|
||||
Rhs: Zero + Clone,
|
||||
<Lhs as $imp<Rhs>>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;
|
||||
|
||||
#[inline]
|
||||
fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
|
||||
(&self).$method(other)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! forward_all_binop {
|
||||
(impl $imp:ident, $method:ident) => {
|
||||
forward_val_val_binop!(impl $imp, $method);
|
||||
forward_ref_val_binop!(impl $imp, $method);
|
||||
forward_val_ref_binop!(impl $imp, $method);
|
||||
};
|
||||
}
|
||||
|
||||
forward_all_binop!(impl Add, add);
|
||||
|
||||
impl<'a, 'b, Lhs, Rhs> Add<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
|
||||
where
|
||||
Lhs: Zero + Add<Rhs> + Clone,
|
||||
Rhs: Zero + Clone,
|
||||
<Lhs as Add<Rhs>>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<Lhs as Add<Rhs>>::Output>;
|
||||
|
||||
fn add(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Add<Rhs>>::Output> {
|
||||
let max_len = cmp::max(self.data.len(), other.data.len());
|
||||
let min_len = cmp::min(self.data.len(), other.data.len());
|
||||
|
||||
let mut sum = Vec::with_capacity(max_len);
|
||||
for i in 0..min_len {
|
||||
sum.push(self.data[i].clone() + other.data[i].clone());
|
||||
}
|
||||
|
||||
if self.data.len() <= other.data.len() {
|
||||
for i in min_len..max_len {
|
||||
sum.push(num_traits::zero::<Lhs>() + other.data[i].clone());
|
||||
}
|
||||
} else {
|
||||
for i in min_len..max_len {
|
||||
sum.push(self.data[i].clone() + num_traits::zero::<Rhs>());
|
||||
}
|
||||
}
|
||||
|
||||
Polynomial::new(sum)
|
||||
}
|
||||
}
|
||||
|
||||
forward_all_binop!(impl Sub, sub);
|
||||
|
||||
impl<'a, 'b, Lhs, Rhs> Sub<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
|
||||
where
|
||||
Lhs: Zero + Sub<Rhs> + Clone,
|
||||
Rhs: Zero + Clone,
|
||||
<Lhs as Sub<Rhs>>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<Lhs as Sub<Rhs>>::Output>;
|
||||
|
||||
fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Sub<Rhs>>::Output> {
|
||||
let min_len = cmp::min(self.data.len(), other.data.len());
|
||||
let max_len = cmp::max(self.data.len(), other.data.len());
|
||||
|
||||
let mut sub = Vec::with_capacity(max_len);
|
||||
for i in 0..min_len {
|
||||
sub.push(self.data[i].clone() - other.data[i].clone());
|
||||
}
|
||||
if self.data.len() <= other.data.len() {
|
||||
for i in min_len..max_len {
|
||||
sub.push(num_traits::zero::<Lhs>() - other.data[i].clone())
|
||||
}
|
||||
} else {
|
||||
for i in min_len..max_len {
|
||||
sub.push(self.data[i].clone() - num_traits::zero::<Rhs>())
|
||||
}
|
||||
}
|
||||
Polynomial::new(sub)
|
||||
}
|
||||
}
|
||||
|
||||
forward_all_binop!(impl Mul, mul);
|
||||
|
||||
impl<'a, 'b, Lhs, Rhs> Mul<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
|
||||
where
|
||||
Lhs: Zero + Mul<Rhs> + Clone,
|
||||
Rhs: Zero + Clone,
|
||||
<Lhs as Mul<Rhs>>::Output: Zero,
|
||||
{
|
||||
type Output = Polynomial<<Lhs as Mul<Rhs>>::Output>;
|
||||
|
||||
fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Mul<Rhs>>::Output> {
|
||||
if self.is_zero() || other.is_zero() {
|
||||
return Polynomial::new(vec![]);
|
||||
}
|
||||
|
||||
let slen = self.data.len();
|
||||
let olen = other.data.len();
|
||||
let prod = (0..slen + olen - 1)
|
||||
.map(|i| {
|
||||
let mut p = num_traits::zero::<<Lhs as Mul<Rhs>>::Output>();
|
||||
let kstart = cmp::max(olen, i + 1) - olen;
|
||||
let kend = cmp::min(slen, i + 1);
|
||||
for k in kstart..kend {
|
||||
p = p + self.data[k].clone() * other.data[i - k].clone();
|
||||
}
|
||||
p
|
||||
})
|
||||
.collect();
|
||||
Polynomial::new(prod)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + Clone> Zero for Polynomial<T> {
|
||||
#[inline]
|
||||
fn zero() -> Self {
|
||||
Self { data: vec![] }
|
||||
}
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + One + Clone> One for Polynomial<T> {
|
||||
#[inline]
|
||||
fn one() -> Self {
|
||||
Self {
|
||||
data: vec![One::one()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Polynomial;
|
||||
|
||||
#[test]
|
||||
fn new() {
|
||||
fn check(dst: Vec<i32>, src: Vec<i32>) {
|
||||
assert_eq!(dst, Polynomial::new(src).data);
|
||||
}
|
||||
check(vec![1, 2, 3], vec![1, 2, 3]);
|
||||
check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
|
||||
check(vec![], vec![0, 0, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neg_add_sub() {
|
||||
fn check(a: &[i32], b: &[i32], c: &[i32]) {
|
||||
fn check_eq(a: &Polynomial<i32>, b: &Polynomial<i32>) {
|
||||
assert_eq!(*a, *b);
|
||||
assert_eq!(-a, -b);
|
||||
}
|
||||
fn check_add(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
|
||||
check_eq(sum, &(a + b));
|
||||
check_eq(sum, &(b + a));
|
||||
}
|
||||
fn check_sub(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
|
||||
check_eq(a, &(sum - b));
|
||||
check_eq(b, &(sum - a));
|
||||
}
|
||||
|
||||
let a = &Polynomial::new(a.to_vec());
|
||||
let b = &Polynomial::new(b.to_vec());
|
||||
let c = &Polynomial::new(c.to_vec());
|
||||
check_add(c, a, b);
|
||||
check_add(&(-c), &(-a), &(-b));
|
||||
check_sub(c, a, b);
|
||||
check_sub(&(-c), &(-a), &(-b));
|
||||
}
|
||||
check(&[], &[], &[]);
|
||||
check(&[], &[1], &[1]);
|
||||
check(&[1], &[1], &[2]);
|
||||
check(&[1, 0, 1], &[1], &[2, 0, 1]);
|
||||
check(&[1, 0, -1], &[-1, 0, 1], &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mul() {
|
||||
fn check(a: &[i32], b: &[i32], c: &[i32]) {
|
||||
let a = Polynomial::new(a.to_vec());
|
||||
let b = Polynomial::new(b.to_vec());
|
||||
let c = Polynomial::new(c.to_vec());
|
||||
assert_eq!(c, &a * &b);
|
||||
assert_eq!(c, &b * &a);
|
||||
}
|
||||
check(&[], &[], &[]);
|
||||
check(&[0, 0], &[], &[]);
|
||||
check(&[0, 0], &[1], &[]);
|
||||
check(&[1, 0], &[1], &[1]);
|
||||
check(&[1, 0, 1], &[1], &[1, 0, 1]);
|
||||
check(&[1, 1], &[1, 1], &[1, 2, 1]);
|
||||
check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
|
||||
check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval() {
|
||||
fn check<F: Fn(i32) -> i32>(pol: &[i32], f: F) {
|
||||
for n in -10..10 {
|
||||
assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
|
||||
}
|
||||
}
|
||||
check(&[], |_x| 0);
|
||||
check(&[1], |_x| 1);
|
||||
check(&[1, 1], |x| x + 1);
|
||||
check(&[0, 1], |x| x);
|
||||
check(&[10, -10, 10], |x| 10 * x * x - 10 * x + 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pretty() {
|
||||
fn check(slice: &[i32], s: &str) {
|
||||
assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
|
||||
}
|
||||
check(&[0], "0");
|
||||
check(&[1], "1");
|
||||
check(&[1, 1], "1+x");
|
||||
check(&[1, 1, 1], "1+x+x^2");
|
||||
check(&[2, 2, 2], "2+2*x+2*x^2");
|
||||
check(&[0, 0, 0, 1], "x^3");
|
||||
check(&[0, 0, 0, -1], "-x^3");
|
||||
check(&[-1, 0, 0, -1], "-1-x^3");
|
||||
check(&[-1, 1, 0, -1], "-1+x-x^3");
|
||||
check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lagrange() {
|
||||
// Evaluate the lagrange polynomial at the x coordinates.
|
||||
// The error should be close to zero.
|
||||
fn check(xs: &[f64], ys: &[f64]) {
|
||||
let p = Polynomial::lagrange(xs, ys).unwrap();
|
||||
for (x, y) in xs.iter().zip(ys) {
|
||||
assert!((p.eval(*x) - y).abs() < 1e-9);
|
||||
}
|
||||
}
|
||||
|
||||
// Squares
|
||||
check(&[1., 2., 3.], &[10., 40., 90.]);
|
||||
// Cubes
|
||||
check(&[-1., 0., 1., 2.], &[-1000., 0., 1000., 8000.]);
|
||||
// Non linear x.
|
||||
check(&[1., 9., 10., 11.], &[1., 2., 3., 4.]);
|
||||
// Test double x failure case.
|
||||
assert_eq!(
|
||||
Polynomial::lagrange(&[1., 9., 9., 11.], &[1., 2., 3., 4.]),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chebyshev() {
|
||||
// Construct a Chebyshev approximation for a function
|
||||
// and evaulate it at 100 points.
|
||||
fn check<F: Fn(f64) -> f64>(f: &F, n: usize, xmin: f64, xmax: f64) {
|
||||
let p = Polynomial::chebyshev(f, n, xmin, xmax).unwrap();
|
||||
for i in 0..=100 {
|
||||
let x = xmin + (i as f64) * ((xmax - xmin) / 100.0);
|
||||
let diff = (f(x) - p.eval(x)).abs();
|
||||
assert!(diff < 0.0001);
|
||||
}
|
||||
}
|
||||
|
||||
// Approximate some common functions.
|
||||
use std::f64::consts::PI;
|
||||
check(&f64::sin, 7, -PI / 2., PI / 2.);
|
||||
check(&f64::cos, 7, 0., PI / 4.);
|
||||
|
||||
// Test n >= 1 condition
|
||||
assert!(Polynomial::chebyshev(&f64::exp, 0, 0., 1.) == None);
|
||||
|
||||
// Test xmax > xmin condition
|
||||
assert!(Polynomial::chebyshev(&f64::ln, 1, 1., 0.) == None);
|
||||
}
|
||||
}
|
41
src/ast.rs
Normal file
41
src/ast.rs
Normal file
@ -0,0 +1,41 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Constraints<'input> {
|
||||
pub iden: Operand<'input>,
|
||||
pub expr: Expr<'input>,
|
||||
}
|
||||
|
||||
impl<'input> Constraints<'input> {
|
||||
pub fn new(iden: Operand<'input>, expr: Expr<'input>) -> Self {
|
||||
Self {
|
||||
iden, expr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Expr<'input> {
|
||||
pub left: Operand<'input>,
|
||||
pub right: Operand<'input>,
|
||||
pub op: Opcode,
|
||||
}
|
||||
|
||||
impl<'input> Expr<'input> {
|
||||
pub fn new(left: Operand<'input>, op: Opcode, right: Operand<'input>) -> Self {
|
||||
Self {
|
||||
left, right, op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Operand<'input> {
|
||||
Identifier(&'input str),
|
||||
Num(&'input str),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Opcode {
|
||||
Add,
|
||||
Mul,
|
||||
}
|
37
src/bsnark.lalrpop
Normal file
37
src/bsnark.lalrpop
Normal file
@ -0,0 +1,37 @@
|
||||
use crate::ast::{Expr, Constraints, Opcode, Operand};
|
||||
|
||||
grammar;
|
||||
|
||||
pub Declaration: Vec<Operand<'input>> = {
|
||||
<s:(Iden ",")*> <i:Iden> => {
|
||||
let mut s: Vec<Operand<'input>> = s.into_iter().map(|x| x.0).collect();
|
||||
s.push(i);
|
||||
s
|
||||
},
|
||||
};
|
||||
|
||||
pub Constraints: Box<Constraints<'input>> = {
|
||||
<i:Iden> "=" <e:Expr> => Box::new(Constraints::new(i, e))
|
||||
};
|
||||
|
||||
pub Expr: Expr<'input> = {
|
||||
Operand ExprOp Operand => Expr::new(<>),
|
||||
};
|
||||
|
||||
Operand: Operand<'input> = {
|
||||
Iden,
|
||||
Num,
|
||||
};
|
||||
|
||||
Iden: Operand<'input> = {
|
||||
r"[a-zA-Z][0-9a-zA-Z]*" => Operand::Identifier(<>),
|
||||
};
|
||||
|
||||
Num: Operand<'input> = {
|
||||
r"[0-9]+" => Operand::Num(<>),
|
||||
};
|
||||
|
||||
ExprOp: Opcode = {
|
||||
"+" => Opcode::Add,
|
||||
"*" => Opcode::Mul,
|
||||
};
|
165
src/field.rs
Normal file
165
src/field.rs
Normal file
@ -0,0 +1,165 @@
|
||||
use std::fmt;
|
||||
|
||||
use modinverse::modinverse;
|
||||
|
||||
pub struct G1 {
|
||||
p: u64,
|
||||
x: u64,
|
||||
y: u64,
|
||||
}
|
||||
|
||||
impl fmt::Display for G1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "({}, {}) in F_{}", self.x, self.y, self.p)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for G1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "({}, {}) in F_{}", self.x, self.y, self.p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl G1 {
|
||||
pub fn new(p: u64, x: u64, y: u64) -> Self {
|
||||
G1 {
|
||||
p, x, y
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(self: &mut Self, other: &G1) {
|
||||
let yp = &self.y;
|
||||
let yq = &other.y;
|
||||
let xp = &self.x;
|
||||
let xq = &other.x;
|
||||
|
||||
if *xq == 0 && *yq == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if *xp == 0 && *yp == 0 {
|
||||
self.x = *xq;
|
||||
self.y = *yq;
|
||||
return;
|
||||
}
|
||||
|
||||
if yp == yq && xp == xq {
|
||||
self.double();
|
||||
return;
|
||||
}
|
||||
|
||||
let p = &self.p;
|
||||
|
||||
let xq_xp = xq + (p - xp);
|
||||
let yq_yp = yq + (p - yp);
|
||||
|
||||
if xq_xp == *p {
|
||||
self.x = 0;
|
||||
self.y = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
let xq_xp_inv = modinverse(xq_xp as i64, *p as i64).unwrap();
|
||||
let lambda = (yq_yp * xq_xp_inv as u64) % p;
|
||||
|
||||
let xr = (lambda * lambda + (p - xp) + (p - xq)) % p;
|
||||
let yr = (lambda * (xp + (p - xr)) + (p - yp)) % p;
|
||||
|
||||
self.x = xr;
|
||||
self.y = yr;
|
||||
}
|
||||
|
||||
pub fn double(self: &mut Self) {
|
||||
let x = &self.x;
|
||||
let y = &self.y;
|
||||
let p = &self.p;
|
||||
|
||||
let y2_inv = modinverse((2 * y) as i64, *p as i64).unwrap();
|
||||
|
||||
let m = (3 * x * x * y2_inv as u64) % p;
|
||||
let m2 = (m * m) % p;
|
||||
let x_new = (m2 + (p - ((2 * x) % p))) % p;
|
||||
let y_new = (m * (3 * x + (p - m2)) + (p - y)) % p;
|
||||
|
||||
self.x = x_new;
|
||||
self.y = y_new;
|
||||
}
|
||||
|
||||
pub fn mul(self: &mut Self, times: u64) {
|
||||
let mut g = self.clone();
|
||||
let mut count = times;
|
||||
let mut res = G1::new(self.p, 0, 0);
|
||||
while count != 0 {
|
||||
if count & 1 == 1 {
|
||||
res.add(&g);
|
||||
}
|
||||
g.double();
|
||||
count = count >> 1;
|
||||
}
|
||||
self.x = res.x;
|
||||
self.y = res.y;
|
||||
println!("{}", self);
|
||||
}
|
||||
|
||||
pub fn inv(self: Self) -> Self {
|
||||
Self {
|
||||
p: self.p,
|
||||
x: self.x,
|
||||
y: self.p - self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone(self: &Self) -> Self {
|
||||
Self {
|
||||
p: self.p,
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double() {
|
||||
let mut g1 = G1::new(101, 1, 2);
|
||||
println!("g1 = {}", g1);
|
||||
g1.double();
|
||||
println!("2g1 = {}", g1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_0add() {
|
||||
let g1 = G1::new(101, 1, 2);
|
||||
let mut inf = G1::new(101, 0, 0);
|
||||
inf.add(&g1);
|
||||
println!("O+g1 = {}", inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add0() {
|
||||
let mut g1 = G1::new(101, 1, 2);
|
||||
let inf = G1::new(101, 0, 0);
|
||||
g1.add(&inf);
|
||||
println!("g1+O = {}", g1);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_mul() {
|
||||
let mut g1 = G1::new(101, 1, 2);
|
||||
println!("g1 = {}", g1);
|
||||
|
||||
let x = 121;
|
||||
g1.mul(x);
|
||||
println!("{}g1 = {}g1 = {}", x, x % 17, g1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
let mut g1 = G1::new(101, 1, 2);
|
||||
println!("g1 = {}", g1);
|
||||
g1.mul(7);
|
||||
println!("7g1 = {}", g1);
|
||||
}
|
||||
|
226
src/main.rs
Normal file
226
src/main.rs
Normal file
@ -0,0 +1,226 @@
|
||||
#[macro_use]
|
||||
extern crate lalrpop_util;
|
||||
|
||||
lalrpop_mod!(pub bsnark);
|
||||
pub mod ast;
|
||||
pub mod field;
|
||||
|
||||
use ast::{Operand, Constraints};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::vec::Vec;
|
||||
use std::{env, fs};
|
||||
use std::error::Error;
|
||||
|
||||
use polynomial::Polynomial;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Context<'a> {
|
||||
content: &'a str,
|
||||
inputs: Vec<Operand<'a>>,
|
||||
outputs: Vec<Operand<'a>>,
|
||||
publics: Vec<Operand<'a>>,
|
||||
constraints: Vec<Constraints<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
fn new(content: &'a str, inputs: Vec<Operand<'a>>, outputs: Vec<Operand<'a>>, publics: Vec<Operand<'a>>) -> Self {
|
||||
Self {
|
||||
content,
|
||||
inputs,
|
||||
outputs,
|
||||
publics,
|
||||
constraints: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_constraint(&mut self, constraint: Constraints<'a>) {
|
||||
self.constraints.push(constraint);
|
||||
}
|
||||
|
||||
fn make_trace(&mut self, input_values: Vec<u64>) {
|
||||
// building gates
|
||||
let mut q_left: Vec<i64> = Vec::new();
|
||||
let mut q_right: Vec<i64> = Vec::new();
|
||||
let mut q_output: Vec<i64> = Vec::new();
|
||||
let mut q_mul: Vec<i64> = Vec::new();
|
||||
let mut q_const: Vec<i64> = Vec::new();
|
||||
let mut a_values: Vec<i64> = Vec::new();
|
||||
let mut b_values: Vec<i64> = Vec::new();
|
||||
let mut c_values: Vec<i64> = Vec::new();
|
||||
|
||||
let mut values_map: HashMap<String, u64> = HashMap::new();
|
||||
for (i, input) in self.inputs.iter().enumerate() {
|
||||
match input {
|
||||
Operand::Identifier(id) => {
|
||||
values_map.insert(id.to_string(), input_values[i]);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
println!("{:?}", values_map);
|
||||
|
||||
// let mut execution_trace = ExecutionTrace::new(inputs, input_values);
|
||||
let polynomials = self.constraints
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(idx, Constraints { expr, iden })| {
|
||||
let left_value = match &expr.left {
|
||||
Operand::Identifier(id) => {
|
||||
values_map[&id.to_string()]
|
||||
},
|
||||
Operand::Num(n) => {
|
||||
n.parse::<u64>().unwrap()
|
||||
}
|
||||
};
|
||||
let right_value = match &expr.right {
|
||||
Operand::Identifier(id) => {
|
||||
values_map[&id.to_string()]
|
||||
},
|
||||
Operand::Num(n) => {
|
||||
n.parse::<u64>().unwrap()
|
||||
}
|
||||
};
|
||||
let assigned_var = match iden {
|
||||
Operand::Identifier(id) => id.to_string(),
|
||||
_ => "".into(),
|
||||
};
|
||||
|
||||
let eval_value = match &expr.op {
|
||||
ast::Opcode::Mul => {
|
||||
q_mul.push(1);
|
||||
q_left.push(0);
|
||||
q_right.push(0);
|
||||
q_output.push(-1);
|
||||
q_const.push(0);
|
||||
|
||||
left_value * right_value
|
||||
},
|
||||
ast::Opcode::Add => {
|
||||
q_mul.push(0);
|
||||
q_left.push(1);
|
||||
q_right.push(1);
|
||||
q_output.push(-1);
|
||||
q_const.push(0);
|
||||
left_value + right_value
|
||||
},
|
||||
};
|
||||
|
||||
a_values.push(left_value as i64);
|
||||
b_values.push(right_value as i64);
|
||||
c_values.push(eval_value as i64);
|
||||
|
||||
match values_map.get(&assigned_var) {
|
||||
Some(value) => {
|
||||
assert!(*value == eval_value,
|
||||
"constraint {}: expecting {} equals {}\n{:?} = {:?}",
|
||||
idx, value, left_value * right_value,
|
||||
iden, expr,);
|
||||
},
|
||||
None => {
|
||||
values_map.insert(assigned_var, eval_value);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
println!("values {:?}", values_map);
|
||||
|
||||
println!("q_mul {:?}", q_mul);
|
||||
println!("q_left {:?}", q_left);
|
||||
println!("q_right {:?}", q_right);
|
||||
println!("q_output {:?}", q_output);
|
||||
println!("q_const {:?}", q_const);
|
||||
println!("a_values {:?}", a_values);
|
||||
println!("b_values {:?}", b_values);
|
||||
println!("c_values {:?}", c_values);
|
||||
|
||||
let nroot = vec![1, 4, 16, 13];
|
||||
let field = 17;
|
||||
let a_poly = Polynomial::lagrange(&nroot, &a_values, Some(&field)).unwrap();
|
||||
println!("{}", a_poly.pretty("x"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>>{
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let content = fs::read_to_string(&args[1]).unwrap();
|
||||
|
||||
let mut lines = content.split("\n");
|
||||
|
||||
// first 3 lines declares the inputs/outputs/publics
|
||||
let inputs = lines.next().ok_or("1st line must provide a list of inputs")?;
|
||||
let outputs = lines.next().ok_or("2nd line must provide a list of outputs")?;
|
||||
let publics = lines.next().ok_or("3rd line must provide a list of publics")?;
|
||||
|
||||
let inputs = if inputs.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
bsnark::DeclarationParser::new().parse(inputs).unwrap()
|
||||
};
|
||||
|
||||
let outputs = if outputs.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
bsnark::DeclarationParser::new().parse(outputs).unwrap()
|
||||
};
|
||||
|
||||
let publics = if publics.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
bsnark::DeclarationParser::new().parse(publics).unwrap()
|
||||
};
|
||||
|
||||
let mut context = Context::new(&content, inputs, outputs, publics);
|
||||
|
||||
lines
|
||||
.fold(&mut context, |ctx, line| {
|
||||
if line.is_empty() {
|
||||
return ctx;
|
||||
}
|
||||
let constraint = bsnark::ConstraintsParser::new().parse(line).unwrap();
|
||||
println!("{:?}", constraint);
|
||||
ctx.add_constraint(*constraint);
|
||||
ctx
|
||||
});
|
||||
|
||||
println!("{:?}", context);
|
||||
|
||||
|
||||
// setup
|
||||
//
|
||||
// curve y^2 = x^3 + 3 (mod 101)
|
||||
// G1 (1, 2)
|
||||
// G2 (36, 31u) (complex number, u^2 = -2)
|
||||
// toxic waste s = 2 (randomly generated)
|
||||
//
|
||||
// SRS = [G1, sG1, s^2 G1, s^3 G1, ...., s^(n+2) G1, G2, sG2]
|
||||
// where n is the number of gates
|
||||
//
|
||||
// gates: QL a + QR b + QO c + QM a * b + QC = 0
|
||||
// therefore, we have n = 4 (QLeft, QRight, QOutput, QMultiply) (QConstant is not counted)
|
||||
|
||||
let s = 2u64;
|
||||
let mut srs: Vec<field::G1> = Vec::new();
|
||||
for i in 0..=6 {
|
||||
let mut g1 = field::G1::new(101, 1, 2);
|
||||
g1.mul(s.pow(i));
|
||||
srs.push(g1)
|
||||
}
|
||||
|
||||
println!("{:?}", srs);
|
||||
|
||||
context.make_trace(vec![3, 4, 5]);
|
||||
|
||||
let a = vec![14, 6, 3, 3, 4, 7];
|
||||
let a = a.iter().enumerate().fold(field::G1::new(101, 0, 0), |acc, (i, coeff)| {
|
||||
let mut point = srs[i].clone();
|
||||
point.mul(*coeff);
|
||||
point.add(&acc);
|
||||
point
|
||||
});
|
||||
println!("[a(s)]_1 = {}", a);
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user