diff --git a/Cargo.lock b/Cargo.lock index e5b3d4f..d753b97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,27 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + [[package]] name = "arrayref" version = "0.3.6" @@ -20,6 +41,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitvec" version = "1.0.0" @@ -43,24 +70,132 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "bumpalo" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" + +[[package]] +name = "bytemuck" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +dependencies = [ + "cc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation", + "foreign-types", + "libc", +] + +[[package]] +name = "core-text" +version = "19.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +dependencies = [ + "core-foundation", + "core-graphics", + "foreign-types", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-channel" version = "0.5.4" @@ -106,12 +241,125 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deflate" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "derive_builder" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" +dependencies = [ + "darling", + "derive_builder_core", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[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 = "dwrote" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +dependencies = [ + "lazy_static", + "libc", + "winapi", + "wio", +] + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "expat-sys" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" +dependencies = [ + "cmake", + "pkg-config", +] + [[package]] name = "ff" version = "0.12.0" @@ -128,6 +376,81 @@ name = "fibonacci" version = "0.1.0" dependencies = [ "halo2_proofs", + "plotters", + "tabbycat", +] + +[[package]] +name = "float-ord" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "font-kit" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28" +dependencies = [ + "bitflags", + "byteorder", + "core-foundation", + "core-graphics", + "core-text", + "dirs-next", + "dwrote", + "float-ord", + "freetype", + "lazy_static", + "libc", + "log", + "pathfinder_geometry", + "pathfinder_simd", + "servo-fontconfig", + "walkdir", + "winapi", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "freetype" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +dependencies = [ + "freetype-sys", + "libc", +] + +[[package]] +name = "freetype-sys" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +dependencies = [ + "cmake", + "libc", + "pkg-config", ] [[package]] @@ -136,6 +459,27 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gif" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "group" version = "0.12.0" @@ -151,15 +495,16 @@ dependencies = [ [[package]] name = "halo2_proofs" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e925780549adee8364c7f2b685c753f6f3df23bde520c67416e93bf615933760" +source = "git+https://github.com/zcash/halo2.git?rev=a898d65ae3ad3d41987666f6a03cfc15edae01c4#a898d65ae3ad3d41987666f6a03cfc15edae01c4" dependencies = [ "blake2b_simd", "ff", "group", "pasta_curves", + "plotters", "rand_core", "rayon", + "tabbycat", ] [[package]] @@ -171,6 +516,43 @@ dependencies = [ "libc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" + +[[package]] +name = "js-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -183,6 +565,21 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[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 = "memoffset" version = "0.6.5" @@ -192,6 +589,56 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniz_oxide" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +dependencies = [ + "adler32", +] + +[[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-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "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 = "num_cpus" version = "1.13.1" @@ -217,6 +664,116 @@ dependencies = [ "subtle", ] +[[package]] +name = "pathfinder_geometry" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" +dependencies = [ + "log", + "pathfinder_simd", +] + +[[package]] +name = "pathfinder_simd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "plotters" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +dependencies = [ + "chrono", + "font-kit", + "image", + "lazy_static", + "num-traits", + "pathfinder_geometry", + "plotters-backend", + "plotters-bitmap", + "plotters-svg", + "ttf-parser", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-bitmap" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21362fa905695e5618aefd169358f52e0e8bc4a8e05333cf780fda8cddc00b54" +dependencies = [ + "gif", + "image", + "plotters-backend", +] + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "png" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide", +] + +[[package]] +name = "proc-macro2" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + [[package]] name = "radium" version = "0.7.0" @@ -262,30 +819,334 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +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.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + +[[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 = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "servo-fontconfig" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" +dependencies = [ + "libc", + "servo-fontconfig-sys", +] + +[[package]] +name = "servo-fontconfig-sys" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" +dependencies = [ + "expat-sys", + "freetype-sys", + "pkg-config", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "subtle" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "syn" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tabbycat" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c45590f0f859197b4545be1b17b2bc3cc7bb075f7d1cc0ea1dc6521c0bf256a3" +dependencies = [ + "anyhow", + "derive_builder", + "regex", +] + [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "ttf-parser" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" + +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" + +[[package]] +name = "web-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" + +[[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-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[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 = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + [[package]] name = "wyz" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 42165be..b1ec261 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,14 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[[bin]] -name = "example1" -path = "src/example1.rs" +[lib] +name = "halo2_examples" +path = "src/lib.rs" + +[features] +dev-graph = ["halo2_proofs/dev-graph", "plotters"] [dependencies] -halo2_proofs = "0.1.0" +halo2_proofs = { git = "https://github.com/zcash/halo2.git", rev = "a898d65ae3ad3d41987666f6a03cfc15edae01c4"} +plotters = { version = "0.3.0", optional = true } +tabbycat = { version = "0.1", features = ["attributes"], optional = true } diff --git a/README.md b/README.md index 9434f39..da8e60e 100644 --- a/README.md +++ b/README.md @@ -12,5 +12,13 @@ cargo build Run examples ``` -cargo run --bin exmaple1 +cargo test -- --nocapture test_example1 +cargo test -- --nocapture test_example2 +cargo test -- --nocapture test_example3 +``` + +Plot the circuit layout +``` +cargo test --all-features -- --nocapture test_example1 +cargo test --all-features -- --nocapture test_example2 ``` diff --git a/src/example1.rs b/src/example1.rs index 2b92eb1..dd24e3e 100644 --- a/src/example1.rs +++ b/src/example1.rs @@ -4,7 +4,6 @@ use halo2_proofs::{ arithmetic::FieldExt, circuit::*, plonk::*, poly::Rotation, - pasta::Fp, dev::MockProver, }; #[derive(Debug, Clone)] @@ -14,7 +13,7 @@ struct ACell(AssignedCell); struct FiboConfig { pub advice: [Column; 3], pub selector: Selector, - pub instance: Column + pub instance: Column, } struct FiboChip { @@ -30,12 +29,12 @@ impl FiboChip { pub fn configure( meta: &mut ConstraintSystem, advice: [Column; 3], + instance: Column, ) -> FiboConfig { let col_a = advice[0]; let col_b = advice[1]; let col_c = advice[2]; let selector = meta.selector(); - let instance = meta.instance_column(); meta.enable_equality(col_a); meta.enable_equality(col_b); @@ -64,8 +63,8 @@ impl FiboChip { pub fn assign_first_row( &self, mut layouter: impl Layouter, - a: Option, - b: Option, + a: Value, + b: Value, ) -> Result<(ACell, ACell, ACell), Error>{ layouter.assign_region( || "first row", @@ -76,23 +75,21 @@ impl FiboChip { || "a", self.config.advice[0], 0, - || a.ok_or(Error::Synthesis), + || a, ).map(ACell)?; let b_cell = region.assign_advice( || "b", self.config.advice[1], 0, - || b.ok_or(Error::Synthesis), + || b, ).map(ACell)?; - let c_val = a.and_then(|a| b.map(|b| a + b)); - let c_cell = region.assign_advice( || "c", self.config.advice[2], 0, - || c_val.ok_or(Error::Synthesis), + || a + b, ).map(ACell)?; Ok((a_cell, b_cell, c_cell)) @@ -113,17 +110,13 @@ impl FiboChip { prev_b.0.copy_advice(|| "a", &mut region, self.config.advice[0], 0)?; prev_c.0.copy_advice(|| "b", &mut region, self.config.advice[1], 0)?; - let c_val = prev_b.0.value().and_then( - |b| { - prev_c.0.value().map(|c| *b + *c) - } - ); + let c_val = prev_b.0.value().copied() + prev_c.0.value(); let c_cell = region.assign_advice( || "c", self.config.advice[2], 0, - || c_val.ok_or(Error::Synthesis), + || c_val, ).map(ACell)?; Ok(c_cell) @@ -135,7 +128,7 @@ impl FiboChip { &self, mut layouter: impl Layouter, cell: &ACell, - row: usize + row: usize, ) -> Result<(), Error> { layouter.constrain_instance(cell.0.cell(), self.config.instance, row) } @@ -143,8 +136,8 @@ impl FiboChip { #[derive(Default)] struct MyCircuit { - pub a: Option, - pub b: Option, + pub a: Value, + pub b: Value, } impl Circuit for MyCircuit { @@ -159,7 +152,8 @@ impl Circuit for MyCircuit { let col_a = meta.advice_column(); let col_b = meta.advice_column(); let col_c = meta.advice_column(); - FiboChip::configure(meta, [col_a, col_b, col_c]) + let instance = meta.instance_column(); + FiboChip::configure(meta, [col_a, col_b, col_c], instance) } fn synthesize( @@ -187,31 +181,53 @@ impl Circuit for MyCircuit { prev_c = c_cell; } - chip.expose_public(layouter.namespace(|| "output"), &prev_c, 2)?; + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 2)?; Ok(()) } } -fn main() { - let k = 4; +mod tests { + use super::MyCircuit; + use halo2_proofs::{pasta::Fp, circuit::Value, dev::MockProver}; - let a = Fp::from(1); // F[0] - let b = Fp::from(1); // F[1] - let out = Fp::from(55); // F[9] + #[test] + fn test_example1() { + let k = 4; - let circuit = MyCircuit { - a: Some(a), - b: Some(b), - }; + let a = Fp::from(1); // F[0] + let b = Fp::from(1); // F[1] + let out = Fp::from(55); // F[9] - let mut public_input = vec![a, b, out]; + let circuit = MyCircuit { + a: Value::known(a), + b: Value::known(b), + }; - let prover = MockProver::run(k, &circuit, vec![public_input.clone()]).unwrap(); - prover.assert_satisfied(); + let mut public_input = vec![a, b, out]; - public_input[2] += Fp::one(); - let prover = MockProver::run(k, &circuit, vec![public_input.clone()]).unwrap(); - // uncomment the following line and the assert will fail - // prover.assert_satisfied(); + let prover = MockProver::run(k, &circuit, vec![public_input.clone()]).unwrap(); + prover.assert_satisfied(); + + public_input[2] += Fp::one(); + let prover = MockProver::run(k, &circuit, vec![public_input]).unwrap(); + // uncomment the following line and the assert will fail + // prover.assert_satisfied(); + } + + + #[cfg(feature = "dev-graph")] + #[test] + fn plot_fibo1() { + use plotters::prelude::*; + + let root = BitMapBackend::new("fib-1-layout.png", (1024, 3096)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("Fib 1 Layout", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit:: { a: Value::unknown(), b: Value::unknown() }; + halo2_proofs::dev::CircuitLayout::default() + .render(4, &circuit, &root) + .unwrap(); + } } diff --git a/src/example2.rs b/src/example2.rs new file mode 100644 index 0000000..647ec02 --- /dev/null +++ b/src/example2.rs @@ -0,0 +1,186 @@ +use std::{marker::PhantomData}; +use halo2_proofs::{ + arithmetic::FieldExt, + circuit::*, + plonk::*, + poly::Rotation, +}; + +#[derive(Debug, Clone)] +struct ACell(AssignedCell); + +#[derive(Debug, Clone)] +struct FiboConfig { + pub advice: Column, + pub selector: Selector, + pub instance: Column, +} + +struct FiboChip { + config: FiboConfig, + _marker: PhantomData, +} + +impl FiboChip { + pub fn construct(config: FiboConfig) -> Self { + Self { config, _marker: PhantomData } + } + + pub fn configure( + meta: &mut ConstraintSystem, + advice: Column, + instance: Column, + ) -> FiboConfig { + let selector = meta.selector(); + + meta.enable_equality(advice); + meta.enable_equality(instance); + + meta.create_gate("add", |meta| { + // + // advice | selector + // a | s + // b | + // c | + // + let s = meta.query_selector(selector); + let a = meta.query_advice(advice, Rotation::cur()); + let b = meta.query_advice(advice, Rotation::next()); + let c = meta.query_advice(advice, Rotation(2)); + vec![s * (a + b - c)] + }); + + FiboConfig { + advice, + selector, + instance, + } + } + + pub fn assign( + &self, + mut layouter: impl Layouter, + nrows: usize, + ) -> Result, Error>{ + layouter.assign_region( + || "entire fibonacci table", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + self.config.selector.enable(&mut region, 1)?; + + let mut a_cell = region.assign_advice_from_instance( + || "1", self.config.instance, 0, self.config.advice, 0)?; + let mut b_cell = region.assign_advice_from_instance( + || "1", self.config.instance, 1, self.config.advice, 1)?; + + for row in 2..nrows { + if row < nrows - 2 { + self.config.selector.enable(&mut region, row)?; + } + + let c_cell = region.assign_advice( + || "advice", + self.config.advice, + row, + || a_cell.value().copied() + b_cell.value(), + )?; + + a_cell = b_cell; + b_cell = c_cell; + } + + Ok(b_cell) + }) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +struct MyCircuit { + pub a: Option, + pub b: Option, +} + +impl Circuit for MyCircuit { + type Config = FiboConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advice = meta.advice_column(); + let instance = meta.instance_column(); + FiboChip::configure(meta, advice, instance) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = FiboChip::construct(config); + + let out_cell = chip.assign( + layouter.namespace(|| "entire table"), + 10, + )?; + + + chip.expose_public(layouter.namespace(|| "out"), out_cell, 2)?; + + Ok(()) + } +} + +mod tests { + use super::MyCircuit; + use halo2_proofs::{pasta::Fp, circuit::Value, dev::MockProver}; + + #[test] + fn test_example2() { + let k = 4; + + let a = Fp::from(1); // F[0] + let b = Fp::from(1); // F[1] + let out = Fp::from(55); // F[9] + + let circuit = MyCircuit { + a: Some(a), + b: Some(b), + }; + + let mut public_input = vec![a, b, out]; + + let prover = MockProver::run(k, &circuit, vec![public_input.clone()]).unwrap(); + prover.assert_satisfied(); + + public_input[2] += Fp::one(); + let prover = MockProver::run(k, &circuit, vec![public_input]).unwrap(); + // uncomment the following line and the assert will fail + // prover.assert_satisfied(); + } + + #[cfg(feature = "dev-graph")] + #[test] + fn plot_fibo2() { + use plotters::prelude::*; + let root = BitMapBackend::new("fib-2-layout.png", (1024, 3096)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root.titled("Fib 2 Layout", ("sans-serif", 60)).unwrap(); + + let circuit = MyCircuit:: { a: None, b: None }; + halo2_proofs::dev::CircuitLayout::default() + .render(4, &circuit, &root) + .unwrap(); + } +} diff --git a/src/example3.rs b/src/example3.rs new file mode 100644 index 0000000..5ec2736 --- /dev/null +++ b/src/example3.rs @@ -0,0 +1,132 @@ +use halo2_proofs::{ + arithmetic::FieldExt, + circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + pasta::Fp, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Expression, Selector}, + poly::Rotation, +}; +use crate::is_zero::{IsZeroChip, IsZeroConfig}; + +#[derive(Debug, Clone)] +struct FunctionConfig { + selector: Selector, + a: Column, + b: Column, + c: Column, + a_equals_b: IsZeroConfig, + output: Column, +} + +struct FunctionChip { + config: FunctionConfig, +} + +impl FunctionChip { + pub fn construct(config: FunctionConfig) -> Self { + Self { config } + } + + pub fn configure(meta: &mut ConstraintSystem) -> FunctionConfig { + let selector = meta.selector(); + let a = meta.advice_column(); + let b = meta.advice_column(); + let c = meta.advice_column(); + let output = meta.advice_column(); + + let is_zero_advice_column = meta.advice_column(); + let a_equals_b = IsZeroChip::configure( + meta, + |meta| meta.query_selector(selector), + |meta| meta.query_advice(a, Rotation::cur()) - meta.query_advice(b, Rotation::cur()), + is_zero_advice_column, + ); + + meta.create_gate("f(a, b, c) = if a == b {c} else {a - b}", |meta| { + let s = meta.query_selector(selector); + let a = meta.query_advice(a, Rotation::cur()); + let b = meta.query_advice(b, Rotation::cur()); + let c = meta.query_advice(c, Rotation::cur()); + let output = meta.query_advice(output, Rotation::cur()); + vec![ + s.clone() * (a_equals_b.expr() * (output.clone() - c)), + s * (Expression::Constant(F::one()) - a_equals_b.expr()) * (output - (a - b)), + ] + }); + + FunctionConfig { + selector, + a, + b, + c, + a_equals_b, + output, + } + } + + pub fn assign( + &self, + mut layouter: impl Layouter, + a: F, + b: F, + c: F, + ) -> Result, Error> { + let is_zero_chip = IsZeroChip::construct(self.config.a_equals_b.clone()); + + layouter.assign_region( + || "f(a, b, c) = if a == b {c} else {a - b}", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + region.assign_advice(|| "a", self.config.a, 0, || Value::known(a))?; + region.assign_advice(|| "b", self.config.b, 0, || Value::known(b))?; + region.assign_advice(|| "c", self.config.c, 0, || Value::known(c))?; + is_zero_chip.assign(&mut region, 0, Value::known(a - b))?; + + let output = if a == b { c } else { a - b }; + region.assign_advice(|| "output", self.config.output, 0, || Value::known(output)) + }, + ) + } +} + +#[derive(Default)] +struct FunctionCircuit { + a: F, + b: F, + c: F, +} + +impl Circuit for FunctionCircuit { + type Config = FunctionConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + FunctionChip::configure(meta) + } + + fn synthesize(&self, config: Self::Config, layouter: impl Layouter) -> Result<(), Error> { + let chip = FunctionChip::construct(config); + chip.assign(layouter, self.a, self.b, self.c)?; + Ok(()) + } +} + +mod tests { + use super::*; + + #[test] + fn test_example3() { + let circuit = FunctionCircuit { + a: Fp::from(10), + b: Fp::from(12), + c: Fp::from(15), + }; + + let prover = MockProver::run(4, &circuit, vec![]).unwrap(); + prover.assert_satisfied(); + } +} diff --git a/src/is_zero.rs b/src/is_zero.rs new file mode 100644 index 0000000..8f0334a --- /dev/null +++ b/src/is_zero.rs @@ -0,0 +1,75 @@ +use halo2_proofs::{ + arithmetic::FieldExt, + circuit::*, + plonk::*, + poly::Rotation, +}; + +#[derive(Clone, Debug)] +pub struct IsZeroConfig { + pub value_inv: Column, + pub is_zero_expr: Expression, +} + +impl IsZeroConfig { + pub fn expr(&self) -> Expression { + self.is_zero_expr.clone() + } +} + +pub struct IsZeroChip { + config: IsZeroConfig, +} + +impl IsZeroChip { + pub fn construct(config: IsZeroConfig) -> Self { + IsZeroChip { config } + } + + pub fn configure( + meta: &mut ConstraintSystem, + q_enable: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, + value: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, + value_inv: Column, + ) -> IsZeroConfig { + let mut is_zero_expr = Expression::Constant(F::zero()); + + meta.create_gate("is_zero", |meta| { + // + // valid | value | value_inv | 1 - value * value_inv | value * (1 - value* value_inv) + // ------+-------+------------+------------------------+------------------------------- + // yes | x | 1/x | 0 | 0 + // no | x | 0 | 1 | x + // yes | 0 | 0 | 1 | 0 + // yes | 0 | y | 1 | 0 + // + let value = value(meta); + let q_enable = q_enable(meta); + let value_inv = meta.query_advice(value_inv, Rotation::cur()); + + is_zero_expr = Expression::Constant(F::one()) - value.clone() * value_inv.clone(); + vec![q_enable * value * is_zero_expr.clone()] + }); + + IsZeroConfig { + value_inv, + is_zero_expr, + } + } + + pub fn assign( + &self, + region: &mut Region<'_, F>, + offset: usize, + value: Value, + ) -> Result<(), Error> { + let value_inv = value.map(|value| value.invert().unwrap_or(F::zero())); + region.assign_advice( + || "value inv", + self.config.value_inv, + offset, + || value_inv, + )?; + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5f8ae2b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +mod example1; +mod example2; +mod example3; +mod is_zero;